Some Updates
This commit is contained in:
@@ -36,6 +36,11 @@ const (
|
||||
AlignRight
|
||||
)
|
||||
|
||||
// Return if r1 and r2 are the same, ignoring case
|
||||
func RuneEqualsNC(r1, r2 rune) bool {
|
||||
return unicode.ToLower(r1) == unicode.ToLower(r2)
|
||||
}
|
||||
|
||||
func Center(txt string, width int) string {
|
||||
if len(txt) >= width {
|
||||
// Trim from beg & end until width
|
||||
|
||||
@@ -58,6 +58,11 @@ func (f LayoutFlag) SetTopLeft() {
|
||||
f = LFAlignHLeft | LFAlignVTop
|
||||
}
|
||||
|
||||
func (f LayoutFlag) SetBottomCenter() {
|
||||
f.ClearAll()
|
||||
f = LFAlignHCenter | LFAlignVBottom
|
||||
}
|
||||
|
||||
func (f LayoutFlag) ClearAlignH() {
|
||||
f = f &^ LFAlignH
|
||||
f.Add(LFAlignHCenter)
|
||||
|
||||
@@ -28,6 +28,8 @@ type BlankWidget struct {
|
||||
id string
|
||||
x, y int
|
||||
keyMap KeyMap
|
||||
|
||||
wantH, wantW int
|
||||
}
|
||||
|
||||
var _ Widget = (*BlankWidget)(nil)
|
||||
@@ -71,7 +73,10 @@ func (w *BlankWidget) SetW(wd int) {}
|
||||
func (w *BlankWidget) SetH(h int) {}
|
||||
func (w *BlankWidget) GetW() int { return 0 }
|
||||
func (w *BlankWidget) GetH() int { return 0 }
|
||||
func (w *BlankWidget) WantW() int { return 0 }
|
||||
func (w *BlankWidget) WantH() int { return 0 }
|
||||
func (w *BlankWidget) WantW() int { return w.wantW }
|
||||
func (w *BlankWidget) WantH() int { return w.wantH }
|
||||
func (w *BlankWidget) MinW() int { return 0 }
|
||||
func (w *BlankWidget) MinH() int { return 0 }
|
||||
|
||||
func (w *BlankWidget) SetWantH(v int) { w.wantH = v }
|
||||
func (w *BlankWidget) SetWantW(v int) { w.wantW = v }
|
||||
|
||||
21
wdgt_cli.go
21
wdgt_cli.go
@@ -40,6 +40,7 @@ type Cli struct {
|
||||
active bool
|
||||
visible bool
|
||||
focusable bool
|
||||
minimized bool
|
||||
|
||||
title string
|
||||
rawLog []string
|
||||
@@ -77,6 +78,9 @@ func (w *Cli) Init(id string, s tcell.Style) {
|
||||
func (w *Cli) Id() string { return w.id }
|
||||
func (w *Cli) HandleResize(ev *tcell.EventResize) {
|
||||
w.w, w.h = ev.Size()
|
||||
if w.minimized {
|
||||
w.h = 3
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Cli) SetKeyMap(km KeyMap) { w.keyMap = km }
|
||||
@@ -174,8 +178,6 @@ func (w *Cli) Draw(screen tcell.Screen) {
|
||||
wh.DrawText(x, y, cursor, dStyle.Reverse(w.active), screen)
|
||||
x += 1
|
||||
wh.DrawText(x, y, wh.PadR(post, w.w-x-2), dStyle, screen)
|
||||
// wh.DrawText(w.x, y+1, fmt.Sprintf("Index: %d", w.historyPosition), dStyle, screen)
|
||||
// x += len(post) - 1
|
||||
}
|
||||
|
||||
func (w *Cli) Active() bool { return w.active }
|
||||
@@ -196,9 +198,15 @@ func (w *Cli) SetW(wd int) { w.w = wd }
|
||||
func (w *Cli) SetH(h int) { w.h = h }
|
||||
func (w *Cli) SetSize(c Coord) { w.w, w.h = c.X, c.Y }
|
||||
func (w *Cli) WantW() int { return wh.MaxInt }
|
||||
func (w *Cli) WantH() int { return wh.MaxInt }
|
||||
func (w *Cli) MinW() int { return 20 }
|
||||
func (w *Cli) MinH() int { return 6 }
|
||||
func (w *Cli) WantH() int {
|
||||
if w.minimized {
|
||||
return 3
|
||||
} else {
|
||||
return wh.MaxInt
|
||||
}
|
||||
}
|
||||
func (w *Cli) MinW() int { return 20 }
|
||||
func (w *Cli) MinH() int { return 6 }
|
||||
|
||||
func (w *Cli) initKeyMap() {
|
||||
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
|
||||
@@ -341,6 +349,9 @@ func (w *Cli) Clear() {
|
||||
w.log = []string{}
|
||||
}
|
||||
|
||||
func (w *Cli) SetMinimized(m bool) { w.minimized = m }
|
||||
func (w *Cli) IsMinimized() bool { return w.minimized }
|
||||
|
||||
type cliCommand func(args ...string) bool
|
||||
|
||||
// TODO
|
||||
|
||||
@@ -42,7 +42,7 @@ type Field struct {
|
||||
x, y int
|
||||
w, h int
|
||||
|
||||
filter func(*tcell.EventKey) bool
|
||||
filter func(tcell.EventKey) bool
|
||||
onChange func(prev, curr string)
|
||||
|
||||
keyMap KeyMap
|
||||
@@ -60,9 +60,9 @@ func (w *Field) Init(id string, style tcell.Style) {
|
||||
w.id = id
|
||||
w.style = style
|
||||
w.visible = true
|
||||
w.filter = func(ev *tcell.EventKey) bool {
|
||||
return wh.IsBS(*ev) ||
|
||||
wh.KeyIsDisplayable(*ev)
|
||||
w.filter = func(ev tcell.EventKey) bool {
|
||||
return wh.IsBS(ev) ||
|
||||
wh.KeyIsDisplayable(ev)
|
||||
}
|
||||
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{
|
||||
tcell.KeyLeft: w.handleLeft,
|
||||
@@ -98,7 +98,7 @@ func (w *Field) HandleKey(ev *tcell.EventKey) bool {
|
||||
if ok := w.keyMap.Handle(ev); ok {
|
||||
return true
|
||||
}
|
||||
if w.filter != nil && !w.filter(ev) {
|
||||
if w.filter != nil && !w.filter(*ev) {
|
||||
return false
|
||||
}
|
||||
if ev.Key() == tcell.KeyRune {
|
||||
@@ -238,3 +238,17 @@ func (w *Field) doOnChange(prev, curr string) {
|
||||
w.onChange(prev, curr)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Field) SetFilter(f func(ev tcell.EventKey) bool) {
|
||||
w.filter = func(ev tcell.EventKey) bool {
|
||||
// We always want to make sure we allow backspace.
|
||||
if wh.IsBS(ev) {
|
||||
return true
|
||||
}
|
||||
// We also always want to make sure it's displayable
|
||||
if !wh.KeyIsDisplayable(ev) {
|
||||
return false
|
||||
}
|
||||
return f(ev)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,6 +275,12 @@ func (w *LinearLayout) findActiveOrFirst() Widget {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *LinearLayout) ActivateWidget(n Widget) {
|
||||
for i := range w.widgets {
|
||||
w.widgets[i].SetActive(w.widgets[i] == n)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *LinearLayout) ActivateNext() bool {
|
||||
var found bool
|
||||
for i := range w.widgets {
|
||||
|
||||
21
wdgt_menu.go
21
wdgt_menu.go
@@ -140,6 +140,7 @@ func (w *Menu) HandleKey(ev *tcell.EventKey) bool {
|
||||
} else if w.items[w.cursor].HandleKey(ev) {
|
||||
// Active menuitem consumes this event
|
||||
if ev.Key() == tcell.KeyEnter {
|
||||
w.cursor = 0
|
||||
w.SetActive(false)
|
||||
}
|
||||
return true
|
||||
@@ -148,6 +149,21 @@ func (w *Menu) HandleKey(ev *tcell.EventKey) bool {
|
||||
return true
|
||||
}
|
||||
// See if we can find an item that matches the key pressed
|
||||
for i := range w.items {
|
||||
if wh.RuneEqualsNC(ev.Rune(), w.items[i].GetHotKey()) {
|
||||
if w.items[i].Active() {
|
||||
if w.items[i].HandleKey(ev) {
|
||||
// Reset the cursor
|
||||
w.cursor = 0
|
||||
w.SetActive(false)
|
||||
return true
|
||||
}
|
||||
}
|
||||
w.cursor = i
|
||||
// w.items[i].SetActive(true)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -178,9 +194,11 @@ func (w *Menu) drawHMenu(screen tcell.Screen) {
|
||||
}
|
||||
x += 2
|
||||
if w.expanded || (w.active && !w.manualExpand) {
|
||||
// pos := w.GetPos()
|
||||
// TODO: Use DrawOffset?
|
||||
for i := range w.items {
|
||||
w.items[i].SetActive(w.active && w.cursor == i)
|
||||
// pos.DrawOffset(w.items[i], screen)
|
||||
w.items[i].SetPos(Coord{X: x, Y: y})
|
||||
w.items[i].Draw(screen)
|
||||
x += len(w.items[i].Label()) + 2
|
||||
@@ -371,8 +389,9 @@ func (w *Menu) MoveDown(ev *tcell.EventKey) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *Menu) CreateMenuItem(lbl string, do func() bool, subItems ...*MenuItem) *MenuItem {
|
||||
func (w *Menu) CreateMenuItem(lbl string, do func() bool, hotKey rune, subItems ...*MenuItem) *MenuItem {
|
||||
d := NewMenuItem(fmt.Sprintf("menuitem-%s", lbl), tcell.StyleDefault)
|
||||
d.SetHotKey(hotKey)
|
||||
d.SetLabel(lbl)
|
||||
d.SetOnPressed(do)
|
||||
if len(subItems) > 0 {
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/gdamore/tcell"
|
||||
)
|
||||
|
||||
// TODO: Sub-Menus
|
||||
type MenuItem struct {
|
||||
id string
|
||||
label string
|
||||
@@ -44,6 +45,8 @@ type MenuItem struct {
|
||||
items []*MenuItem
|
||||
onPressed func() bool
|
||||
|
||||
hotKey rune
|
||||
|
||||
manualExpand bool
|
||||
expanded bool
|
||||
disabled bool
|
||||
@@ -101,6 +104,20 @@ func (w *MenuItem) HandleKey(ev *tcell.EventKey) bool {
|
||||
if !w.active {
|
||||
return false
|
||||
}
|
||||
// If the user hits the hotkey of this active item, call 'Enter' on it
|
||||
if wh.RuneEqualsNC(ev.Rune(), w.hotKey) {
|
||||
w.HandleKey(tcell.NewEventKey(tcell.KeyEnter, 0, 0))
|
||||
}
|
||||
for i := range w.items {
|
||||
if wh.RuneEqualsNC(ev.Rune(), w.items[i].GetHotKey()) {
|
||||
if w.items[i].Active() {
|
||||
return w.items[i].HandleKey(ev)
|
||||
}
|
||||
w.cursor = i
|
||||
w.updateActive()
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Look for a sub-item that's selected
|
||||
return w.keyMap.Handle(ev)
|
||||
}
|
||||
@@ -116,17 +133,29 @@ func (w *MenuItem) Draw(screen tcell.Screen) {
|
||||
return
|
||||
}
|
||||
st := w.style.Dim(w.disabled).Italic(w.disabled)
|
||||
// st := w.style.Reverse(w.active).Dim(w.disabled).Italic(w.disabled)
|
||||
x, y := w.x, w.y
|
||||
// wd := w.w
|
||||
fndHotKey := w.GetHotKey() != 0
|
||||
if w.expanded {
|
||||
if len(w.items) > 0 {
|
||||
wh.DrawText(x, y, fmt.Sprintf("╭%s╮", w.label), st, screen)
|
||||
wh.DrawText(x+1, y, fmt.Sprintf("%s", w.label), st.Reverse(true), screen)
|
||||
y += 1
|
||||
if len(w.items) > 0 {
|
||||
wh.TitledBorderFilled(w.x-1, y, w.x+w.WantW(), y+w.WantH(), fmt.Sprintf("╯%s╰", strings.Repeat(" ", len(w.label))), wh.BRD_CSIMPLE, w.style, screen)
|
||||
screen.SetContent(x, y, '╭', nil, st)
|
||||
x += 1
|
||||
for i := range w.label {
|
||||
if fndHotKey && wh.RuneEqualsNC(rune(w.label[i]), w.hotKey) {
|
||||
screen.SetContent(x, y, rune(w.label[i]), nil, st.Reverse(true).Underline(true))
|
||||
fndHotKey = false
|
||||
} else {
|
||||
screen.SetContent(x, y, rune(w.label[i]), nil, st.Reverse(true))
|
||||
}
|
||||
x += 1
|
||||
}
|
||||
screen.SetContent(x, y, '╮', nil, st)
|
||||
x = w.x
|
||||
y += 1
|
||||
if len(w.items) == 0 {
|
||||
return
|
||||
}
|
||||
wh.BorderFilled(w.x-1, y, w.x+w.WantW(), y+w.WantH(), wh.BRD_CSIMPLE, w.style, screen)
|
||||
wh.DrawText(w.x, y, fmt.Sprintf("╯%s╰", strings.Repeat(" ", len(w.label))), w.style, screen)
|
||||
x += 1
|
||||
y += 1
|
||||
// pos := w.GetPos()
|
||||
@@ -138,10 +167,32 @@ func (w *MenuItem) Draw(screen tcell.Screen) {
|
||||
y++
|
||||
}
|
||||
} else {
|
||||
wh.DrawText(x, y, fmt.Sprintf(" %s ", w.label), st.Reverse(true), screen)
|
||||
screen.SetContent(x, y, ' ', nil, st)
|
||||
x += 1
|
||||
for i := range w.label {
|
||||
if fndHotKey && wh.RuneEqualsNC(rune(w.label[i]), w.hotKey) {
|
||||
screen.SetContent(x, y, rune(w.label[i]), nil, st.Reverse(true).Underline(true))
|
||||
fndHotKey = false
|
||||
} else {
|
||||
screen.SetContent(x, y, rune(w.label[i]), nil, st.Reverse(true))
|
||||
}
|
||||
x += 1
|
||||
}
|
||||
screen.SetContent(x, y, ' ', nil, st)
|
||||
}
|
||||
} else {
|
||||
wh.DrawText(x, y, fmt.Sprintf(" %s ", w.label), st, screen)
|
||||
screen.SetContent(x, y, ' ', nil, st)
|
||||
x += 1
|
||||
for i := range w.label {
|
||||
if fndHotKey && wh.RuneEqualsNC(rune(w.label[i]), w.hotKey) {
|
||||
screen.SetContent(x, y, rune(w.label[i]), nil, st.Underline(true))
|
||||
fndHotKey = false
|
||||
} else {
|
||||
screen.SetContent(x, y, rune(w.label[i]), nil, st)
|
||||
}
|
||||
x += 1
|
||||
}
|
||||
screen.SetContent(x, y, ' ', nil, st)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +218,7 @@ func (w *MenuItem) GetH() int { return w.y }
|
||||
func (w *MenuItem) MinW() int { return w.w }
|
||||
func (w *MenuItem) MinH() int { return w.y }
|
||||
func (w *MenuItem) WantW() int {
|
||||
ret := len(w.label) + 2
|
||||
ret := len(w.label) + 4
|
||||
if len(w.items) > 0 {
|
||||
for i := range w.items {
|
||||
if w.items[i].WantW() > ret {
|
||||
@@ -263,3 +314,6 @@ func (w *MenuItem) FindItem(id string) *MenuItem {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *MenuItem) SetHotKey(r rune) { w.hotKey = r }
|
||||
func (w *MenuItem) GetHotKey() rune { return w.hotKey }
|
||||
|
||||
@@ -220,10 +220,11 @@ func (w *TopMenuLayout) Log(txt string, args ...any) {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *TopMenuLayout) CreateMenuItem(id, lbl string, do func() bool, subItems ...*MenuItem) *MenuItem {
|
||||
func (w *TopMenuLayout) CreateMenuItem(id, lbl string, do func() bool, hotKey rune, subItems ...*MenuItem) *MenuItem {
|
||||
d := NewMenuItem(id, tcell.StyleDefault)
|
||||
d.SetLabel(lbl)
|
||||
d.SetOnPressed(do)
|
||||
d.SetHotKey(hotKey)
|
||||
if len(subItems) > 0 {
|
||||
d.AddItems(subItems...)
|
||||
}
|
||||
@@ -247,3 +248,9 @@ func (w *TopMenuLayout) SetItemDisabled(id string, d bool) bool {
|
||||
}
|
||||
|
||||
func (w *TopMenuLayout) FindItem(id string) *MenuItem { return w.menu.FindItem(id) }
|
||||
func (w *TopMenuLayout) CloseMenu() {
|
||||
if w.menu != nil && w.menu.Active() {
|
||||
w.menu.SetActive(false)
|
||||
w.widget.SetActive(true)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user