Reworking Keymaps

This commit is contained in:
2025-10-26 08:47:07 -05:00
parent cf47b5a4e4
commit d63e3a414a
30 changed files with 384 additions and 715 deletions

160
keymap.go
View File

@@ -23,71 +23,119 @@ package widgets
import "github.com/gdamore/tcell" import "github.com/gdamore/tcell"
type Key struct {
ev *tcell.EventKey
do []func(*tcell.EventKey) bool
desc string
}
func BuildEK(k tcell.Key) *tcell.EventKey { return tcell.NewEventKey(k, 0, 0) }
func BuildEKr(r rune) *tcell.EventKey { return tcell.NewEventKey(tcell.KeyRune, r, 0) }
func NewKey(ev *tcell.EventKey, do func(*tcell.EventKey) bool) *Key {
return &Key{
ev: ev,
do: []func(*tcell.EventKey) bool{do},
}
}
func (k *Key) AddBinding(do func(*tcell.EventKey) bool) *Key {
k.do = append(k.do, do)
return k
}
func (k *Key) SetDescription(d string) *Key {
k.desc = d
return k
}
func (k *Key) Matches(ev *tcell.EventKey) bool {
return k.ev.Key() == ev.Key() &&
k.ev.Rune() == ev.Rune() &&
k.ev.Modifiers() == ev.Modifiers()
}
func (k *Key) Handle(ev *tcell.EventKey) bool {
if !k.Matches(ev) {
return false
}
var cons bool
for _, d := range k.do {
cons = cons || d(ev)
}
return cons
}
type KeyMap struct { type KeyMap struct {
Keys map[tcell.Key]func(*tcell.EventKey) bool Keys []*Key
Runes map[rune]func(*tcell.EventKey) bool
} }
func BlankKeyMap() KeyMap { func BlankKeyMap() *KeyMap { return &KeyMap{} }
return KeyMap{ func NewKeyMap(k *Key, rest ...*Key) *KeyMap {
Keys: make(map[tcell.Key]func(*tcell.EventKey) bool), ret := &KeyMap{}
Runes: make(map[rune]func(*tcell.EventKey) bool), return ret
}
// Search through 'Keys', and return all that matches
func (m *KeyMap) Get(k *Key) *Key {
for _, key := range m.Keys {
if k.Matches(key.ev) {
return key
}
}
return nil
}
func (m *KeyMap) Merge(n *KeyMap) {
switch len(n.Keys) {
case 0:
return
case 1:
m.Add(n.Keys[0])
default:
m.Add(n.Keys[0], n.Keys[1:]...)
} }
} }
func NewKeyMap(m map[tcell.Key]func(*tcell.EventKey) bool) KeyMap { func (m *KeyMap) Add(k *Key, rest ...*Key) {
return KeyMap{ p := m.Get(k)
Keys: m, if p != nil {
Runes: make(map[rune]func(*tcell.EventKey) bool), for dIdx := range k.do {
} p.AddBinding(k.do[dIdx])
} }
if k.desc != "" {
func NewRuneMap(m map[rune]func(*tcell.EventKey) bool) KeyMap { p.SetDescription(k.desc)
return KeyMap{
Keys: make(map[tcell.Key]func(*tcell.EventKey) bool),
Runes: m,
}
}
func (m KeyMap) Merge(km KeyMap) {
for k, v := range km.Keys {
m.Keys[k] = v
}
for r, v := range km.Runes {
m.Runes[r] = v
}
}
func (m KeyMap) Add(k tcell.Key, do func(*tcell.EventKey) bool) { m.Keys[k] = do }
func (m KeyMap) Remove(k tcell.Key) { delete(m.Keys, k) }
func (m KeyMap) AddAll(all map[tcell.Key]func(*tcell.EventKey) bool) {
for k, v := range all {
m.Add(k, v)
}
}
func (m KeyMap) AddRune(k rune, do func(*tcell.EventKey) bool) { m.Runes[k] = do }
func (m KeyMap) RemoveRune(k rune) { delete(m.Runes, k) }
func (m KeyMap) AddRunes(all map[rune]func(*tcell.EventKey) bool) {
for k, v := range all {
m.AddRune(k, v)
}
}
func (m KeyMap) Handle(ev *tcell.EventKey) bool {
if ev.Key() == tcell.KeyRune {
for k, v := range m.Runes {
if ev.Rune() == k {
return v(ev)
}
} }
} else { } else {
for k, v := range m.Keys { m.Keys = append(m.Keys, k)
if ev.Key() == k { }
return v(ev) }
func (m *KeyMap) Remove(k *Key, rest ...*Key) {
do := func(k *Key) {
idx := -1
for i := range m.Keys {
if m.Keys[i].Matches(k.ev) {
idx = i
break
} }
} }
if idx == -1 {
return
}
m.Keys = append(m.Keys[:idx], m.Keys[idx+1:]...)
}
do(k)
for i := range rest {
do(rest[i])
} }
return false }
func (m *KeyMap) Handle(ev *tcell.EventKey) bool {
var cons bool
for _, k := range m.Keys {
cons = cons || k.Handle(ev)
}
return cons
} }

View File

@@ -45,7 +45,7 @@ type AbsoluteLayout struct {
visible bool visible bool
focusable bool focusable bool
keyMap KeyMap keyMap *KeyMap
cursor int cursor int
disableTab bool disableTab bool
@@ -80,17 +80,8 @@ func (w *AbsoluteLayout) HandleResize(ev *tcell.EventResize) {
w.updateWidgetLayouts() w.updateWidgetLayouts()
} }
// AbsoluteLayout doesn't have a default keymap func (w *AbsoluteLayout) GetKeyMap() *KeyMap { return w.keyMap }
func (w *AbsoluteLayout) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *AbsoluteLayout) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *AbsoluteLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) }
func (w *AbsoluteLayout) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *AbsoluteLayout) HandleKey(ev *tcell.EventKey) bool { func (w *AbsoluteLayout) HandleKey(ev *tcell.EventKey) bool {
if !w.disableTab && ev.Key() == tcell.KeyTab { if !w.disableTab && ev.Key() == tcell.KeyTab {

View File

@@ -44,7 +44,7 @@ type Alert struct {
btnLayout *LinearLayout btnLayout *LinearLayout
btnOk, btnCancel *Button btnOk, btnCancel *Button
keyMap, customKeyMap KeyMap keyMap *KeyMap
logger func(string, ...any) logger func(string, ...any)
} }
@@ -82,15 +82,14 @@ func (w *Alert) Init(id string, style tcell.Style) {
w.btnOk.SetActive(true) w.btnOk.SetActive(true)
w.btnLayout.Add(w.btnOk) w.btnLayout.Add(w.btnOk)
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyTab: w.SelectNext, NewKey(BuildEK(tcell.KeyTab), w.SelectNext),
tcell.KeyRight: w.SelectNext, NewKey(BuildEK(tcell.KeyRight), w.SelectNext),
tcell.KeyDown: w.SelectNext, NewKey(BuildEK(tcell.KeyDown), w.SelectNext),
tcell.KeyLeft: w.SelectNext, NewKey(BuildEK(tcell.KeyLeft), w.SelectNext),
tcell.KeyUp: w.SelectNext, NewKey(BuildEK(tcell.KeyUp), w.SelectNext),
tcell.KeyEnter: w.Do, NewKey(BuildEK(tcell.KeyEnter), w.Do),
}) )
w.customKeyMap = BlankKeyMap()
w.focusable = true w.focusable = true
} }
func (w *Alert) Id() string { return w.id } func (w *Alert) Id() string { return w.id }
@@ -101,36 +100,14 @@ func (w *Alert) HandleResize(ev *tcell.EventResize) {
w.layout.HandleResize(tcell.NewEventResize(w.w-2, w.h-2)) w.layout.HandleResize(tcell.NewEventResize(w.w-2, w.h-2))
} }
func (w *Alert) SetKeyMap(km KeyMap, def bool) { func (w *Alert) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Alert) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Alert) AddToKeyMap(km KeyMap) {
w.customKeyMap.Merge(km)
}
func (w *Alert) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
w.customKeyMap.RemoveRune(r)
}
}
func (w *Alert) HandleKey(ev *tcell.EventKey) bool { func (w *Alert) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
b1 := w.keyMap.Handle(ev) return w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
} }
func (w *Alert) HandleTime(ev *tcell.EventTime) { func (w *Alert) HandleTime(ev *tcell.EventTime) {

View File

@@ -44,7 +44,7 @@ type ArtWidget struct {
font string font string
text string text string
keyMap KeyMap keyMap *KeyMap
allFonts []ArtWidgetFont allFonts []ArtWidgetFont
currFont ArtWidgetFont currFont ArtWidgetFont
@@ -69,18 +69,10 @@ func (w *ArtWidget) Init(id string, st tcell.Style) {
} }
func (w *ArtWidget) Id() string { return w.id } func (w *ArtWidget) Id() string { return w.id }
func (w *ArtWidget) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } func (w *ArtWidget) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *ArtWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *ArtWidget) GetKeyMap() *KeyMap { return w.keyMap }
func (w *ArtWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *ArtWidget) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *ArtWidget) RemoveFromKeyMap(km KeyMap) { func (w *ArtWidget) HandleKey(ev *tcell.EventKey) bool { return false }
for k := range km.Keys { func (w *ArtWidget) HandleTime(ev *tcell.EventTime) {}
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *ArtWidget) HandleKey(ev *tcell.EventKey) bool { return false }
func (w *ArtWidget) HandleTime(ev *tcell.EventTime) {}
func (w *ArtWidget) Draw(screen tcell.Screen) { func (w *ArtWidget) Draw(screen tcell.Screen) {
if !w.visible { if !w.visible {
return return

View File

@@ -27,7 +27,7 @@ import "github.com/gdamore/tcell"
type BlankWidget struct { type BlankWidget struct {
id string id string
x, y int x, y int
keyMap KeyMap keyMap *KeyMap
wantH, wantW int wantH, wantW int
} }
@@ -45,19 +45,11 @@ func NewBlankWidget(id string) *BlankWidget {
func (w *BlankWidget) Init(id string, st tcell.Style) { w.keyMap = BlankKeyMap() } func (w *BlankWidget) Init(id string, st tcell.Style) { w.keyMap = BlankKeyMap() }
func (w *BlankWidget) Id() string { return w.id } func (w *BlankWidget) Id() string { return w.id }
func (w *BlankWidget) HandleResize(ev *tcell.EventResize) {} func (w *BlankWidget) HandleResize(ev *tcell.EventResize) {}
func (w *BlankWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *BlankWidget) GetKeyMap() *KeyMap { return w.keyMap }
func (w *BlankWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *BlankWidget) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *BlankWidget) RemoveFromKeyMap(km KeyMap) { func (w *BlankWidget) HandleKey(ev *tcell.EventKey) bool { return false }
for k := range km.Keys { func (w *BlankWidget) HandleTime(ev *tcell.EventTime) {}
w.keyMap.Remove(k) func (w *BlankWidget) Draw(screen tcell.Screen) {}
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *BlankWidget) HandleKey(ev *tcell.EventKey) bool { return false }
func (w *BlankWidget) HandleTime(ev *tcell.EventTime) {}
func (w *BlankWidget) Draw(screen tcell.Screen) {}
func (w *BlankWidget) Active() bool { return false } func (w *BlankWidget) Active() bool { return false }
func (w *BlankWidget) SetActive(a bool) {} func (w *BlankWidget) SetActive(a bool) {}

View File

@@ -69,13 +69,9 @@ func (w *BorderedWidget) HandleResize(ev *tcell.EventResize) {
w.widget.HandleResize(tcell.NewEventResize(w.w-2, w.h-2)) w.widget.HandleResize(tcell.NewEventResize(w.w-2, w.h-2))
} }
func (w *BorderedWidget) SetKeyMap(km KeyMap, def bool) { w.widget.SetKeyMap(km, def) } func (w *BorderedWidget) GetKeyMap() *KeyMap { return w.widget.GetKeyMap() }
func (w *BorderedWidget) AddToKeyMap(km KeyMap) { w.widget.AddToKeyMap(km) } func (w *BorderedWidget) SetKeyMap(km *KeyMap) { w.widget.SetKeyMap(km) }
func (w *BorderedWidget) RemoveFromKeyMap(km KeyMap) { w.widget.RemoveFromKeyMap(km) } func (w *BorderedWidget) HandleKey(ev *tcell.EventKey) bool { return w.widget.HandleKey(ev) }
func (w *BorderedWidget) HandleKey(ev *tcell.EventKey) bool {
w.Log("BW(%s) Active(%s) Handlekey", w.Id(), w.widget.Id())
return w.widget.HandleKey(ev)
}
func (w *BorderedWidget) HandleTime(ev *tcell.EventTime) { w.widget.HandleTime(ev) } func (w *BorderedWidget) HandleTime(ev *tcell.EventTime) { w.widget.HandleTime(ev) }

View File

@@ -38,7 +38,7 @@ type BufferWidget struct {
buffer *Buffer buffer *Buffer
keyMap KeyMap keyMap *KeyMap
timeMap *TimeMap timeMap *TimeMap
} }
@@ -64,16 +64,8 @@ func (w *BufferWidget) Id() string { return w.id }
func (w *BufferWidget) HandleResize(ev *tcell.EventResize) { func (w *BufferWidget) HandleResize(ev *tcell.EventResize) {
} }
func (w *BufferWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *BufferWidget) GetKeyMap() *KeyMap { return w.keyMap }
func (w *BufferWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *BufferWidget) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *BufferWidget) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *BufferWidget) HandleKey(ev *tcell.EventKey) bool { func (w *BufferWidget) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {

View File

@@ -36,10 +36,10 @@ type Button struct {
x, y int x, y int
w, h int w, h int
active bool active bool
visible bool visible bool
focusable bool focusable bool
keyMap, customKeyMap KeyMap keyMap *KeyMap
onPressed func() bool onPressed func() bool
logger func(string, ...any) logger func(string, ...any)
@@ -57,10 +57,7 @@ func (w *Button) Init(id string, style tcell.Style) {
w.id = id w.id = id
w.style = style w.style = style
w.visible = true w.visible = true
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool { return w.onPressed() }))
tcell.KeyEnter: func(ev *tcell.EventKey) bool { return w.onPressed() },
})
w.customKeyMap = BlankKeyMap()
w.onPressed = func() bool { return false } w.onPressed = func() bool { return false }
w.focusable = true w.focusable = true
} }
@@ -69,30 +66,14 @@ func (w *Button) HandleResize(ev *tcell.EventResize) {
w.w, w.h = ev.Size() w.w, w.h = ev.Size()
} }
func (w *Button) SetKeyMap(km KeyMap, def bool) { func (w *Button) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Button) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Button) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Button) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Button) HandleKey(ev *tcell.EventKey) bool { func (w *Button) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
b1 := w.keyMap.Handle(ev) return w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
} }
func (w *Button) HandleTime(ev *tcell.EventTime) {} func (w *Button) HandleTime(ev *tcell.EventTime) {}

View File

@@ -51,7 +51,7 @@ type Chat struct {
history []ChatMsg history []ChatMsg
historyPosition int historyPosition int
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*Chat)(nil) var _ Widget = (*Chat)(nil)
@@ -74,26 +74,8 @@ func (w *Chat) HandleResize(ev *tcell.EventResize) {
w.w, w.h = ev.Size() w.w, w.h = ev.Size()
} }
func (w *Chat) SetKeyMap(km KeyMap, def bool) { func (w *Chat) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Chat) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Chat) AddToKeyMap(km KeyMap) {
w.customKeyMap.Merge(km)
}
func (w *Chat) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Chat) HandleKey(ev *tcell.EventKey) bool { func (w *Chat) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
@@ -111,9 +93,7 @@ func (w *Chat) HandleKey(ev *tcell.EventKey) bool {
w.value = w.value[:w.cursor] + w.value[w.cursor+1:] w.value = w.value[:w.cursor] + w.value[w.cursor+1:]
} }
} }
b1 := w.keyMap.Handle(ev) if w.keyMap.Handle(ev) {
b2 := w.customKeyMap.Handle(ev)
if b1 || b2 {
return true return true
} }
@@ -201,12 +181,12 @@ func (w *Chat) MinW() int { return 2 + 20 }
func (w *Chat) MinH() int { return 6 } func (w *Chat) MinH() int { return 6 }
func (w *Chat) initKeyMap() { func (w *Chat) initKeyMap() {
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyEsc: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyEsc), func(ev *tcell.EventKey) bool {
w.SetActive(false) w.SetActive(false)
return true return true
}, }),
tcell.KeyUp: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyUp), func(ev *tcell.EventKey) bool {
if w.historyPosition < len(w.history)-1 { if w.historyPosition < len(w.history)-1 {
w.historyPosition++ w.historyPosition++
w.value = w.history[w.historyPosition].Message w.value = w.history[w.historyPosition].Message
@@ -214,8 +194,8 @@ func (w *Chat) initKeyMap() {
return true return true
} }
return false return false
}, }),
tcell.KeyDown: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyDown), func(ev *tcell.EventKey) bool {
if w.historyPosition > -1 { if w.historyPosition > -1 {
w.historyPosition-- w.historyPosition--
if w.historyPosition == -1 { if w.historyPosition == -1 {
@@ -227,37 +207,36 @@ func (w *Chat) initKeyMap() {
return true return true
} }
return false return false
}, }),
tcell.KeyLeft: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyLeft), func(ev *tcell.EventKey) bool {
if w.cursor > 0 { if w.cursor > 0 {
w.cursor-- w.cursor--
return true return true
} }
return false return false
}, }),
tcell.KeyRight: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyRight), func(ev *tcell.EventKey) bool {
if w.cursor < len(w.value) { if w.cursor < len(w.value) {
w.cursor++ w.cursor++
return true return true
} }
return false return false
}, }),
tcell.KeyCtrlU: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyCtrlU), func(ev *tcell.EventKey) bool {
w.value = w.value[w.cursor:] w.value = w.value[w.cursor:]
w.cursor = 0 w.cursor = 0
return true return true
}, }),
tcell.KeyTab: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyTab), func(ev *tcell.EventKey) bool {
// Auto-complete // Auto-complete
// TODO: Find best guess for current word // TODO: Find best guess for current word
return false return false
}, }),
tcell.KeyEnter: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
// TODO: Submit the message // TODO: Submit the message
return false return false
}, }),
}) )
w.customKeyMap = BlankKeyMap()
} }
func (w *Chat) SetTitle(ttl string) { w.title = ttl } func (w *Chat) SetTitle(ttl string) { w.title = ttl }
func (w *Chat) Title() string { return w.title } func (w *Chat) Title() string { return w.title }

View File

@@ -45,8 +45,8 @@ type Checkbox struct {
x, y int x, y int
w, h int w, h int
keyMap, customKeyMap KeyMap keyMap *KeyMap
stateRunes []rune stateRunes []rune
} }
var _ Widget = (*Checkbox)(nil) var _ Widget = (*Checkbox)(nil)
@@ -63,43 +63,22 @@ func (w *Checkbox) Init(id string, style tcell.Style) {
w.visible = true w.visible = true
w.stateRunes = []rune{'X', ' ', '-'} w.stateRunes = []rune{'X', ' ', '-'}
w.focusable = true w.focusable = true
w.keyMap = KeyMap{ w.keyMap = NewKeyMap(
Keys: map[tcell.Key]func(ev *tcell.EventKey) bool{ NewKey(BuildEK(tcell.KeyEnter), w.ToggleState),
tcell.KeyEnter: w.ToggleState, NewKey(BuildEKr(' '), w.ToggleState),
}, )
Runes: map[rune]func(ev *tcell.EventKey) bool{
' ': w.ToggleState,
},
}
w.customKeyMap = BlankKeyMap()
} }
func (w *Checkbox) Id() string { return w.id } func (w *Checkbox) Id() string { return w.id }
func (w *Checkbox) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } func (w *Checkbox) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *Checkbox) SetKeyMap(km KeyMap, def bool) { func (w *Checkbox) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Checkbox) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Checkbox) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Checkbox) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Checkbox) HandleKey(ev *tcell.EventKey) bool { func (w *Checkbox) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
b1 := w.keyMap.Handle(ev) return w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
} }
func (w *Checkbox) HandleTime(ev *tcell.EventTime) {} func (w *Checkbox) HandleTime(ev *tcell.EventTime) {}
func (w *Checkbox) Draw(screen tcell.Screen) { func (w *Checkbox) Draw(screen tcell.Screen) {

View File

@@ -54,7 +54,7 @@ type Cli struct {
commands []*CliCommand commands []*CliCommand
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
// TODO: Fix Command/SubCommand finding // TODO: Fix Command/SubCommand finding
@@ -81,22 +81,8 @@ func (w *Cli) HandleResize(ev *tcell.EventResize) {
} }
} }
func (w *Cli) SetKeyMap(km KeyMap, def bool) { func (w *Cli) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Cli) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Cli) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Cli) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Cli) HandleKey(ev *tcell.EventKey) bool { func (w *Cli) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
@@ -114,8 +100,7 @@ func (w *Cli) HandleKey(ev *tcell.EventKey) bool {
w.value = w.value[:w.cursor] + w.value[w.cursor+1:] w.value = w.value[:w.cursor] + w.value[w.cursor+1:]
} }
} }
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) if w.keyMap.Handle(ev) {
if b1 || b2 {
return true return true
} }
@@ -216,12 +201,12 @@ func (w *Cli) MinW() int { return 20 }
func (w *Cli) MinH() int { return 6 } func (w *Cli) MinH() int { return 6 }
func (w *Cli) initKeyMap() { func (w *Cli) initKeyMap() {
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyEsc: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyEsc), func(ev *tcell.EventKey) bool {
w.SetActive(false) w.SetActive(false)
return true return true
}, }),
tcell.KeyUp: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyUp), func(ev *tcell.EventKey) bool {
if w.historyPosition < len(w.history)-1 { if w.historyPosition < len(w.history)-1 {
w.historyPosition++ w.historyPosition++
w.value = w.history[w.historyPosition] w.value = w.history[w.historyPosition]
@@ -229,8 +214,8 @@ func (w *Cli) initKeyMap() {
return true return true
} }
return false return false
}, }),
tcell.KeyDown: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyDown), func(ev *tcell.EventKey) bool {
if w.historyPosition > -1 { if w.historyPosition > -1 {
w.historyPosition-- w.historyPosition--
if w.historyPosition == -1 { if w.historyPosition == -1 {
@@ -242,27 +227,27 @@ func (w *Cli) initKeyMap() {
return true return true
} }
return false return false
}, }),
tcell.KeyLeft: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyLeft), func(ev *tcell.EventKey) bool {
if w.cursor > 0 { if w.cursor > 0 {
w.cursor-- w.cursor--
return true return true
} }
return false return false
}, }),
tcell.KeyRight: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyRight), func(ev *tcell.EventKey) bool {
if w.cursor < len(w.value) { if w.cursor < len(w.value) {
w.cursor++ w.cursor++
return true return true
} }
return false return false
}, }),
tcell.KeyCtrlU: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyCtrlU), func(ev *tcell.EventKey) bool {
w.value = w.value[w.cursor:] w.value = w.value[w.cursor:]
w.cursor = 0 w.cursor = 0
return true return true
}, }),
tcell.KeyTab: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyTab), func(ev *tcell.EventKey) bool {
// Auto-complete // Auto-complete
guess := w.findBestGuess() guess := w.findBestGuess()
if guess != nil { if guess != nil {
@@ -273,8 +258,8 @@ func (w *Cli) initKeyMap() {
return true return true
} }
return false return false
}, }),
tcell.KeyEnter: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
args := strings.Split(w.value, " ") args := strings.Split(w.value, " ")
w.historyPosition = -1 w.historyPosition = -1
w.value = "" w.value = ""
@@ -289,8 +274,8 @@ func (w *Cli) initKeyMap() {
} }
w.history = append(w.history, fmt.Sprintf("%s: command not found", w.value)) w.history = append(w.history, fmt.Sprintf("%s: command not found", w.value))
return true return true
}, }),
tcell.KeyPgUp: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyPgUp), func(ev *tcell.EventKey) bool {
if w.logPosition < len(w.log)-w.h-2 { if w.logPosition < len(w.log)-w.h-2 {
w.logPosition += (w.h - 2) w.logPosition += (w.h - 2)
if w.logPosition > len(w.log) { if w.logPosition > len(w.log) {
@@ -299,8 +284,8 @@ func (w *Cli) initKeyMap() {
return true return true
} }
return false return false
}, }),
tcell.KeyPgDn: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyPgDn), func(ev *tcell.EventKey) bool {
if w.logPosition > 0 { if w.logPosition > 0 {
w.logPosition -= (w.h - 2) w.logPosition -= (w.h - 2)
if w.logPosition < 0 { if w.logPosition < 0 {
@@ -309,8 +294,8 @@ func (w *Cli) initKeyMap() {
return true return true
} }
return false return false
}, }),
}) )
} }
func (w *Cli) SetTitle(ttl string) { w.title = ttl } func (w *Cli) SetTitle(ttl string) { w.title = ttl }
func (w *Cli) Title() string { return w.title } func (w *Cli) Title() string { return w.title }

View File

@@ -45,7 +45,7 @@ type DatePicker struct {
dateFld *Field dateFld *Field
dateNow *Button dateNow *Button
keyMap, customKeyMap KeyMap keyMap *KeyMap
logger func(string, ...any) logger func(string, ...any)
} }
@@ -96,38 +96,15 @@ func (w *DatePicker) HandleResize(ev *tcell.EventResize) {
w.dateNow.SetPos(Coord{X: wd - 6, Y: 0}) w.dateNow.SetPos(Coord{X: wd - 6, Y: 0})
} }
func (w *DatePicker) SetKeyMap(km KeyMap, def bool) { func (w *DatePicker) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *DatePicker) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *DatePicker) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *DatePicker) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *DatePicker) HandleKey(ev *tcell.EventKey) bool { func (w *DatePicker) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
if ev.Key() == tcell.KeyTab { if w.keyMap.Handle(ev) {
if w.dateFld.Active() { return true
w.dateFld.SetActive(false)
w.dateNow.SetActive(true)
return true
} else if w.dateNow.Active() {
w.dateFld.SetActive(false)
w.dateNow.SetActive(false)
return false
}
return false
} }
if w.dateFld.Active() { if w.dateFld.Active() {
if w.dateFld.HandleKey(ev) { if w.dateFld.HandleKey(ev) {
@@ -140,9 +117,7 @@ func (w *DatePicker) HandleKey(ev *tcell.EventKey) bool {
} else if w.dateNow.Active() { } else if w.dateNow.Active() {
return w.dateNow.HandleKey(ev) return w.dateNow.HandleKey(ev)
} }
b1 := w.keyMap.Handle(ev) return false
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
} }
func (w *DatePicker) HandleTime(ev *tcell.EventTime) {} func (w *DatePicker) HandleTime(ev *tcell.EventTime) {}
func (w *DatePicker) Draw(screen tcell.Screen) { func (w *DatePicker) Draw(screen tcell.Screen) {
@@ -198,8 +173,20 @@ func (w *DatePicker) updateUI() {
} }
func (w *DatePicker) initKeyMap() { func (w *DatePicker) initKeyMap() {
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{}) w.keyMap = NewKeyMap(
w.customKeyMap = BlankKeyMap() NewKey(BuildEK(tcell.KeyTab), func(ev *tcell.EventKey) bool {
if w.dateFld.Active() {
w.dateFld.SetActive(false)
w.dateNow.SetActive(true)
return true
} else if w.dateNow.Active() {
w.dateFld.SetActive(false)
w.dateNow.SetActive(false)
return true
}
return false
}),
)
} }
func (w *DatePicker) Format() string { return w.format } func (w *DatePicker) Format() string { return w.format }

View File

@@ -43,7 +43,7 @@ type DebugWidget struct {
focusable bool focusable bool
mTL, mBR Coord // Margins (Top-Right & Bottom Left) mTL, mBR Coord // Margins (Top-Right & Bottom Left)
keyMap KeyMap keyMap *KeyMap
logger func(string, ...any) logger func(string, ...any)
} }
@@ -106,16 +106,8 @@ func (w *DebugWidget) HandleResize(ev *tcell.EventResize) {
w.widget.HandleResize(tcell.NewEventResize(w.w-w.mTL.X-w.mBR.X, w.h-w.mTL.Y-w.mBR.Y)) w.widget.HandleResize(tcell.NewEventResize(w.w-w.mTL.X-w.mBR.X, w.h-w.mTL.Y-w.mBR.Y))
} }
func (w *DebugWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *DebugWidget) GetKeyMap() *KeyMap { return w.keyMap }
func (w *DebugWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *DebugWidget) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *DebugWidget) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *DebugWidget) HandleKey(ev *tcell.EventKey) bool { func (w *DebugWidget) HandleKey(ev *tcell.EventKey) bool {
if ok := w.keyMap.Handle(ev); ok { if ok := w.keyMap.Handle(ev); ok {

View File

@@ -47,7 +47,7 @@ type Field struct {
filter func(tcell.EventKey) bool filter func(tcell.EventKey) bool
onChange func(prev, curr string) onChange func(prev, curr string)
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*Field)(nil) var _ Widget = (*Field)(nil)
@@ -66,36 +66,21 @@ func (w *Field) Init(id string, style tcell.Style) {
return wh.IsBS(ev) || return wh.IsBS(ev) ||
wh.KeyIsDisplayable(ev) wh.KeyIsDisplayable(ev)
} }
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyLeft: w.handleLeft, NewKey(BuildEK(tcell.KeyLeft), w.handleLeft),
tcell.KeyRight: w.handleRight, NewKey(BuildEK(tcell.KeyRight), w.handleRight),
tcell.KeyHome: w.handleHome, NewKey(BuildEK(tcell.KeyHome), w.handleHome),
tcell.KeyEnd: w.handleEnd, NewKey(BuildEK(tcell.KeyEnd), w.handleEnd),
tcell.KeyCtrlU: w.clearValueBeforeCursor, NewKey(BuildEK(tcell.KeyCtrlU), w.clearValueBeforeCursor),
}) )
w.customKeyMap = BlankKeyMap()
w.focusable = true w.focusable = true
} }
func (w *Field) Id() string { return w.id } func (w *Field) Id() string { return w.id }
func (w *Field) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } func (w *Field) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *Field) SetKeyMap(km KeyMap, def bool) { func (w *Field) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Field) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Field) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Field) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Field) HandleKey(ev *tcell.EventKey) bool { func (w *Field) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
@@ -114,9 +99,7 @@ func (w *Field) HandleKey(ev *tcell.EventKey) bool {
return w.handleBackspace(ev) return w.handleBackspace(ev)
} }
} }
b1 := w.keyMap.Handle(ev) if w.keyMap.Handle(ev) {
b2 := w.customKeyMap.Handle(ev)
if b1 || b2 {
return true return true
} }
if w.filter != nil && !w.filter(*ev) { if w.filter != nil && !w.filter(*ev) {

View File

@@ -49,7 +49,7 @@ type FilePicker struct {
error error error error
keyMap, customKeyMap KeyMap keyMap *KeyMap
logger func(string, ...any) logger func(string, ...any)
} }
@@ -77,7 +77,6 @@ func (w *FilePicker) Init(id string, style tcell.Style) {
w.focusable = true w.focusable = true
w.keyMap = BlankKeyMap() w.keyMap = BlankKeyMap()
w.customKeyMap = BlankKeyMap()
w.refreshFileList() w.refreshFileList()
} }
@@ -96,30 +95,14 @@ func (w *FilePicker) HandleResize(ev *tcell.EventResize) {
w.Log("%s: HandleResize(%d, %d)", w.id, wd, ht) w.Log("%s: HandleResize(%d, %d)", w.id, wd, ht)
} }
func (w *FilePicker) SetKeyMap(km KeyMap, def bool) { func (w *FilePicker) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *FilePicker) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *FilePicker) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *FilePicker) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *FilePicker) HandleKey(ev *tcell.EventKey) bool { func (w *FilePicker) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
b1 := w.keyMap.Handle(ev) return w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
} }
func (w *FilePicker) HandleTime(ev *tcell.EventTime) { func (w *FilePicker) HandleTime(ev *tcell.EventTime) {

View File

@@ -45,7 +45,7 @@ type Form struct {
hasSubmit bool hasSubmit bool
hasCancel bool hasCancel bool
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*Form)(nil) var _ Widget = (*Form)(nil)
@@ -64,7 +64,6 @@ func (w *Form) Init(id string, style tcell.Style) {
w.submit = NewButton(fmt.Sprintf("%s-submit", id), style) w.submit = NewButton(fmt.Sprintf("%s-submit", id), style)
w.cancel = NewButton(fmt.Sprintf("%s-cancel", id), style) w.cancel = NewButton(fmt.Sprintf("%s-cancel", id), style)
w.keyMap = BlankKeyMap() w.keyMap = BlankKeyMap()
w.customKeyMap = BlankKeyMap()
} }
func (w *Form) Id() string { return w.id } func (w *Form) Id() string { return w.id }
@@ -92,22 +91,8 @@ func (w *Form) HandleResize(ev *tcell.EventResize) {
} }
} }
func (w *Form) SetKeyMap(km KeyMap, def bool) { func (w *Form) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Form) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Form) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Form) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Form) HandleKey(ev *tcell.EventKey) bool { func (w *Form) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
@@ -129,9 +114,7 @@ func (w *Form) HandleKey(ev *tcell.EventKey) bool {
w.updateWidgets() w.updateWidgets()
return w.cursor > pre return w.cursor > pre
} }
b1 := w.keyMap.Handle(ev) return w.keyMap.Handle(ev)
b2 := w.customKeyMap.Handle(ev)
return b1 || b2
} }
func (w *Form) HandleTime(ev *tcell.EventTime) {} func (w *Form) HandleTime(ev *tcell.EventTime) {}
func (w *Form) Draw(screen tcell.Screen) { func (w *Form) Draw(screen tcell.Screen) {

View File

@@ -56,7 +56,7 @@ type LinearLayout struct {
disableTab bool disableTab bool
insetBorder bool insetBorder bool
keyMap, customKeyMap KeyMap keyMap *KeyMap
logger func(string, ...any) logger func(string, ...any)
} }
@@ -84,8 +84,7 @@ func (w *LinearLayout) Init(id string, s tcell.Style) {
w.defFlags = LayoutFlag(LFAlignHCenter | LFAlignVCenter) w.defFlags = LayoutFlag(LFAlignHCenter | LFAlignVCenter)
w.layoutFlags = make(map[Widget]LayoutFlag) w.layoutFlags = make(map[Widget]LayoutFlag)
w.layoutWeights = make(map[Widget]int) w.layoutWeights = make(map[Widget]int)
w.keyMap = BlankKeyMap() w.keyMap = NewKeyMap(NewKey(BuildEK(tcell.KeyTab), func(ev *tcell.EventKey) bool {
w.keyMap.Add(tcell.KeyTab, func(ev *tcell.EventKey) bool {
active := w.findActive() active := w.findActive()
if active == nil && len(w.widgets) > 0 { if active == nil && len(w.widgets) > 0 {
// No widget is active, but we do have some // No widget is active, but we do have some
@@ -97,8 +96,7 @@ func (w *LinearLayout) Init(id string, s tcell.Style) {
return false return false
} }
return w.ActivateNext() return w.ActivateNext()
}) }))
w.customKeyMap = BlankKeyMap()
} }
func (w *LinearLayout) Id() string { return w.id } func (w *LinearLayout) Id() string { return w.id }
@@ -107,22 +105,8 @@ func (w *LinearLayout) HandleResize(ev *tcell.EventResize) {
w.updateWidgetLayouts() w.updateWidgetLayouts()
} }
func (w *LinearLayout) SetKeyMap(km KeyMap, def bool) { func (w *LinearLayout) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *LinearLayout) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *LinearLayout) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *LinearLayout) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *LinearLayout) HandleKey(ev *tcell.EventKey) bool { func (w *LinearLayout) HandleKey(ev *tcell.EventKey) bool {
if !w.active || w.disableTab { if !w.active || w.disableTab {
@@ -134,8 +118,7 @@ func (w *LinearLayout) HandleKey(ev *tcell.EventKey) bool {
return true return true
} }
} }
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) return w.keyMap.Handle(ev)
return b1 || b2
} }
func (w *LinearLayout) GetActiveWidgetIdx() int { return w.findActiveIdx() } func (w *LinearLayout) GetActiveWidgetIdx() int { return w.findActiveIdx() }
@@ -335,6 +318,7 @@ func (w *LinearLayout) FindById(id string) Widget {
} }
return nil return nil
} }
func (w *LinearLayout) Contains(n Widget) bool { func (w *LinearLayout) Contains(n Widget) bool {
return w.IndexOf(n) >= 0 return w.IndexOf(n) >= 0
} }

View File

@@ -47,7 +47,7 @@ type Menu struct {
expanded bool expanded bool
vimMode bool vimMode bool
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
type MenuType int type MenuType int
@@ -69,19 +69,18 @@ func (w *Menu) Init(id string, style tcell.Style) {
w.id = id w.id = id
w.style = style w.style = style
w.visible = true w.visible = true
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyRight: w.MoveRight, NewKey(BuildEK(tcell.KeyRight), w.MoveRight),
tcell.KeyLeft: w.MoveLeft, NewKey(BuildEK(tcell.KeyLeft), w.MoveLeft),
tcell.KeyUp: w.MoveUp, NewKey(BuildEK(tcell.KeyUp), w.MoveUp),
tcell.KeyDown: w.MoveDown, NewKey(BuildEK(tcell.KeyDown), w.MoveDown),
tcell.KeyEnter: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
if w.onPressed != nil { if w.onPressed != nil {
return w.onPressed() return w.onPressed()
} }
return false return false
}, }),
}) )
w.customKeyMap = BlankKeyMap()
w.focusable = true w.focusable = true
} }
func (w *Menu) Id() string { return w.id } func (w *Menu) Id() string { return w.id }
@@ -124,22 +123,8 @@ func (w *Menu) handleResizeV(_ *tcell.EventResize) {
} }
} }
func (w *Menu) SetKeyMap(km KeyMap, def bool) { func (w *Menu) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Menu) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Menu) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Menu) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Menu) HandleKey(ev *tcell.EventKey) bool { func (w *Menu) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
@@ -152,8 +137,7 @@ func (w *Menu) HandleKey(ev *tcell.EventKey) bool {
} }
return true return true
} }
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) if w.keyMap.Handle(ev) {
if b1 || b2 {
return true return true
} }

View File

@@ -51,7 +51,7 @@ type MenuItem struct {
expanded bool expanded bool
disabled bool disabled bool
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*MenuItem)(nil) var _ Widget = (*MenuItem)(nil)
@@ -66,19 +66,18 @@ func (w *MenuItem) Init(id string, style tcell.Style) {
w.id = id w.id = id
w.style = style w.style = style
w.visible = true w.visible = true
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyUp: w.MoveUp, NewKey(BuildEK(tcell.KeyUp), w.MoveUp),
tcell.KeyDown: w.MoveDown, NewKey(BuildEK(tcell.KeyDown), w.MoveDown),
tcell.KeyEnter: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
if w.onPressed != nil { if w.onPressed != nil {
return w.onPressed() return w.onPressed()
} else if len(w.items) > w.cursor && w.items[w.cursor].HandleKey(ev) { } else if len(w.items) > w.cursor && w.items[w.cursor].HandleKey(ev) {
return true return true
} }
return false return false
}, }),
}) )
w.customKeyMap = BlankKeyMap()
for i := range w.items { for i := range w.items {
w.items[i].SetActive(i == w.cursor) w.items[i].SetActive(i == w.cursor)
@@ -91,22 +90,8 @@ func (w *MenuItem) HandleResize(ev *tcell.EventResize) {
// TODO: Trickle-down HandleResize // TODO: Trickle-down HandleResize
} }
func (w *MenuItem) SetKeyMap(km KeyMap, def bool) { func (w *MenuItem) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *MenuItem) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *MenuItem) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *MenuItem) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *MenuItem) HandleKey(ev *tcell.EventKey) bool { func (w *MenuItem) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
@@ -127,8 +112,7 @@ func (w *MenuItem) HandleKey(ev *tcell.EventKey) bool {
} }
} }
// Look for a sub-item that's selected // Look for a sub-item that's selected
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) return w.keyMap.Handle(ev)
return b1 || b2
} }
func (w *MenuItem) HandleTime(ev *tcell.EventTime) { func (w *MenuItem) HandleTime(ev *tcell.EventTime) {

View File

@@ -46,7 +46,7 @@ type Prompt struct {
btnOk, btnCancel *Button btnOk, btnCancel *Button
onOk func(string) bool onOk func(string) bool
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*Prompt)(nil) var _ Widget = (*Prompt)(nil)
@@ -68,7 +68,6 @@ func (w *Prompt) Init(id string, style tcell.Style) {
w.btnCancel.SetLabel("Cancel") w.btnCancel.SetLabel("Cancel")
w.focusable = true w.focusable = true
w.keyMap = BlankKeyMap() w.keyMap = BlankKeyMap()
w.customKeyMap = BlankKeyMap()
} }
func (w *Prompt) Id() string { return w.id } func (w *Prompt) Id() string { return w.id }
func (w *Prompt) HandleResize(ev *tcell.EventResize) { func (w *Prompt) HandleResize(ev *tcell.EventResize) {
@@ -84,29 +83,14 @@ func (w *Prompt) HandleResize(ev *tcell.EventResize) {
w.btnCancel.SetPos(Coord{X: w.x + 1, Y: w.y + w.h - 1}) w.btnCancel.SetPos(Coord{X: w.x + 1, Y: w.y + w.h - 1})
} }
func (w *Prompt) SetKeyMap(km KeyMap, def bool) { func (w *Prompt) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Prompt) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Prompt) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Prompt) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Prompt) HandleKey(ev *tcell.EventKey) bool { func (w *Prompt) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) return w.keyMap.Handle(ev)
return b1 || b2
} }
func (w *Prompt) HandleTime(ev *tcell.EventTime) { func (w *Prompt) HandleTime(ev *tcell.EventTime) {

View File

@@ -37,7 +37,7 @@ type RelativeLayout struct {
visible bool visible bool
focusable bool focusable bool
keyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*RelativeLayout)(nil) var _ Widget = (*RelativeLayout)(nil)
@@ -85,16 +85,8 @@ func (w *RelativeLayout) HandleResize(ev *tcell.EventResize) {
// TODO: Trickle-down HandleResize // TODO: Trickle-down HandleResize
} }
func (w *RelativeLayout) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *RelativeLayout) GetKeyMap() *KeyMap { return w.keyMap }
func (w *RelativeLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *RelativeLayout) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *RelativeLayout) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *RelativeLayout) HandleKey(ev *tcell.EventKey) bool { return w.keyMap.Handle(ev) } func (w *RelativeLayout) HandleKey(ev *tcell.EventKey) bool { return w.keyMap.Handle(ev) }
func (w *RelativeLayout) HandleTime(ev *tcell.EventTime) { func (w *RelativeLayout) HandleTime(ev *tcell.EventTime) {
for i := range w.widgets { for i := range w.widgets {

View File

@@ -54,7 +54,7 @@ type Searcher struct {
hideOnSelect bool hideOnSelect bool
logger func(string, ...any) logger func(string, ...any)
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*Searcher)(nil) var _ Widget = (*Searcher)(nil)
@@ -74,16 +74,15 @@ func (w *Searcher) Init(id string, style tcell.Style) {
w.search.SetOnChange(func(prev, curr string) { w.search.SetOnChange(func(prev, curr string) {
w.updateFilter() w.updateFilter()
}) })
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyUp: w.handleKeyUp, NewKey(BuildEK(tcell.KeyUp), w.handleKeyUp),
tcell.KeyDown: w.handleKeyDown, NewKey(BuildEK(tcell.KeyDown), w.handleKeyDown),
tcell.KeyHome: w.handleKeyHome, NewKey(BuildEK(tcell.KeyHome), w.handleKeyHome),
tcell.KeyEnd: w.handleKeyEnd, NewKey(BuildEK(tcell.KeyEnd), w.handleKeyEnd),
tcell.KeyPgUp: w.handleKeyPgUp, NewKey(BuildEK(tcell.KeyPgUp), w.handleKeyPgUp),
tcell.KeyPgDn: w.handleKeyPgDn, NewKey(BuildEK(tcell.KeyPgDn), w.handleKeyPgDn),
tcell.KeyEnter: w.handleKeyEnter, NewKey(BuildEK(tcell.KeyEnter), w.handleKeyEnter),
}) )
w.customKeyMap = BlankKeyMap()
w.focusable = true w.focusable = true
w.filteredToTrue = make(map[int]int) w.filteredToTrue = make(map[int]int)
} }
@@ -101,41 +100,22 @@ func (w *Searcher) HandleResize(ev *tcell.EventResize) {
// w.buildBuffer() // w.buildBuffer()
} }
func (w *Searcher) SetKeyMap(km KeyMap, def bool) { func (w *Searcher) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Searcher) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Searcher) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Searcher) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Searcher) HandleKey(ev *tcell.EventKey) bool { func (w *Searcher) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
sel := w.cursor sel := w.cursor
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) ret := w.keyMap.Handle(ev)
var ret bool if !ret {
if !b1 && !b2 {
ret = w.search.HandleKey(ev) ret = w.search.HandleKey(ev)
} }
if w.cursor != sel && w.onChange != nil { if w.cursor != sel && w.onChange != nil {
w.onChange(w.cursor, w.filteredData[w.cursor]) w.onChange(w.cursor, w.filteredData[w.cursor])
} }
if b1 || b2 || ret { return ret
// w.buildBuffer()
return true
}
return false
} }
func (w *Searcher) handleKeyUp(ev *tcell.EventKey) bool { func (w *Searcher) handleKeyUp(ev *tcell.EventKey) bool {

View File

@@ -39,9 +39,9 @@ func (w *ShrinkWrap) Init(id string, st tcell.Style) { w.widget.Init(id, st)
func (w *ShrinkWrap) Id() string { return w.widget.Id() } func (w *ShrinkWrap) Id() string { return w.widget.Id() }
func (w *ShrinkWrap) HandleResize(ev *tcell.EventResize) { w.widget.HandleResize(ev) } func (w *ShrinkWrap) HandleResize(ev *tcell.EventResize) { w.widget.HandleResize(ev) }
func (w *ShrinkWrap) SetKeyMap(km KeyMap, def bool) { w.widget.SetKeyMap(km, def) } func (w *ShrinkWrap) GetKeyMap() *KeyMap { return w.widget.GetKeyMap() }
func (w *ShrinkWrap) AddToKeyMap(km KeyMap) { w.widget.AddToKeyMap(km) } func (w *ShrinkWrap) SetKeyMap(km *KeyMap) { w.widget.SetKeyMap(km) }
func (w *ShrinkWrap) RemoveFromKeyMap(km KeyMap) { w.widget.RemoveFromKeyMap(km) }
func (w *ShrinkWrap) HandleKey(ev *tcell.EventKey) bool { return w.widget.HandleKey(ev) } func (w *ShrinkWrap) HandleKey(ev *tcell.EventKey) bool { return w.widget.HandleKey(ev) }
func (w *ShrinkWrap) HandleTime(ev *tcell.EventTime) { w.widget.HandleTime(ev) } func (w *ShrinkWrap) HandleTime(ev *tcell.EventTime) { w.widget.HandleTime(ev) }
func (w *ShrinkWrap) Draw(screen tcell.Screen) { w.widget.Draw(screen) } func (w *ShrinkWrap) Draw(screen tcell.Screen) { w.widget.Draw(screen) }

View File

@@ -44,10 +44,10 @@ type SimpleList struct {
list []string list []string
itemsStyle map[int]tcell.Style itemsStyle map[int]tcell.Style
onChange func(int, string) bool onChange func(int, string) bool
onSelect func(int, string) bool onSelect func(int, string) bool
keyMap, customKeyMap KeyMap keyMap *KeyMap
vimMode bool vimMode bool
logger func(string, ...any) logger func(string, ...any)
} }
@@ -64,49 +64,48 @@ func (w *SimpleList) Init(id string, style tcell.Style) {
w.id = id w.id = id
w.style = style w.style = style
w.focusable = true w.focusable = true
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyUp: func(_ *tcell.EventKey) bool { return w.MoveUp() }, NewKey(BuildEK(tcell.KeyUp), func(_ *tcell.EventKey) bool { return w.MoveUp() }),
tcell.KeyDown: func(_ *tcell.EventKey) bool { return w.MoveDown() }, NewKey(BuildEK(tcell.KeyDown), func(_ *tcell.EventKey) bool { return w.MoveDown() }),
tcell.KeyEnter: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyEnter), func(ev *tcell.EventKey) bool {
if w.onSelect != nil && w.cursor < len(w.list) { if w.onSelect != nil && w.cursor < len(w.list) {
return w.onSelect(w.cursor, w.list[w.cursor]) return w.onSelect(w.cursor, w.list[w.cursor])
} }
return false return false
}, }),
tcell.KeyPgDn: func(_ *tcell.EventKey) bool { return w.PageDn() }, NewKey(BuildEK(tcell.KeyPgDn), func(_ *tcell.EventKey) bool { return w.PageDn() }),
tcell.KeyPgUp: func(_ *tcell.EventKey) bool { return w.PageUp() }, NewKey(BuildEK(tcell.KeyPgUp), func(_ *tcell.EventKey) bool { return w.PageUp() }),
}) NewKey(BuildEKr('j'), func(ev *tcell.EventKey) bool {
w.keyMap.AddRune('j', func(ev *tcell.EventKey) bool { if !w.vimMode {
if !w.vimMode { return false
}
return w.MoveDown()
}),
NewKey(BuildEKr('k'), func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
return w.MoveUp()
}),
NewKey(BuildEKr('b'), func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
if ev.Modifiers()&tcell.ModCtrl != 0 {
return w.PageUp()
}
return false return false
} }),
return w.MoveDown() NewKey(BuildEKr('f'), func(ev *tcell.EventKey) bool {
}) if !w.vimMode {
w.keyMap.AddRune('k', func(ev *tcell.EventKey) bool { return false
if !w.vimMode { }
if ev.Modifiers()&tcell.ModCtrl != 0 {
return w.PageDn()
}
return false return false
} }),
return w.MoveUp() )
})
w.keyMap.AddRune('b', func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
if ev.Modifiers()&tcell.ModCtrl != 0 {
return w.PageUp()
}
return false
})
w.keyMap.AddRune('f', func(ev *tcell.EventKey) bool {
if !w.vimMode {
return false
}
if ev.Modifiers()&tcell.ModCtrl != 0 {
return w.PageDn()
}
return false
})
w.customKeyMap = BlankKeyMap()
w.itemsStyle = make(map[int]tcell.Style) w.itemsStyle = make(map[int]tcell.Style)
w.focusable = true w.focusable = true
} }
@@ -114,29 +113,14 @@ func (w *SimpleList) Init(id string, style tcell.Style) {
func (w *SimpleList) Id() string { return w.id } func (w *SimpleList) Id() string { return w.id }
func (w *SimpleList) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } func (w *SimpleList) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *SimpleList) SetKeyMap(km KeyMap, def bool) { func (w *SimpleList) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *SimpleList) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *SimpleList) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *SimpleList) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *SimpleList) HandleKey(ev *tcell.EventKey) bool { func (w *SimpleList) HandleKey(ev *tcell.EventKey) bool {
if !w.active || !w.focusable { if !w.active || !w.focusable {
return false return false
} }
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) return w.keyMap.Handle(ev)
return b1 || b2
} }
func (w *SimpleList) HandleTime(ev *tcell.EventTime) {} func (w *SimpleList) HandleTime(ev *tcell.EventTime) {}
@@ -294,10 +278,10 @@ func (w *SimpleList) PageUp() bool {
func (w *SimpleList) PageDn() bool { func (w *SimpleList) PageDn() bool {
w.cursor += w.h w.cursor += w.h
if len(w.border) > 0 { if len(w.border) > 0 {
w.cursor -= 2 w.cursor -= 1
} }
if w.cursor > len(w.list)-2 { if w.cursor > len(w.list)-1 {
w.cursor = len(w.list) - 2 w.cursor = len(w.list) - 1
} }
return true return true
} }

View File

@@ -36,7 +36,7 @@ type Spinner struct {
frames []rune frames []rune
lastTick time.Time lastTick time.Time
tickInterval time.Duration tickInterval time.Duration
keyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*Spinner)(nil) var _ Widget = (*Spinner)(nil)
@@ -60,16 +60,10 @@ func (w *Spinner) Init(id string, st tcell.Style) {
} }
func (w *Spinner) Id() string { return w.id } func (w *Spinner) Id() string { return w.id }
func (w *Spinner) HandleResize(ev *tcell.EventResize) {} func (w *Spinner) HandleResize(ev *tcell.EventResize) {}
func (w *Spinner) SetKeyMap(km KeyMap, def bool) { w.keyMap = km }
func (w *Spinner) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *Spinner) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Spinner) RemoveFromKeyMap(km KeyMap) { func (w *Spinner) SetKeyMap(km *KeyMap) { w.keyMap = km }
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *Spinner) HandleKey(ev *tcell.EventKey) bool { return false } func (w *Spinner) HandleKey(ev *tcell.EventKey) bool { return false }
func (w *Spinner) HandleTime(ev *tcell.EventTime) { func (w *Spinner) HandleTime(ev *tcell.EventTime) {
w.currentFrame = (w.currentFrame + 1) % len(w.frames) w.currentFrame = (w.currentFrame + 1) % len(w.frames)

View File

@@ -52,7 +52,7 @@ type Table struct {
columnWidths []int columnWidths []int
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*Table)(nil) var _ Widget = (*Table)(nil)
@@ -85,36 +85,20 @@ func (w *Table) Init(id string, style tcell.Style) {
w.border = wh.BRD_CSIMPLE w.border = wh.BRD_CSIMPLE
w.focusable = true w.focusable = true
w.keyMap = BlankKeyMap() w.keyMap = BlankKeyMap()
w.customKeyMap = BlankKeyMap()
} }
func (w *Table) Id() string { return w.id } func (w *Table) Id() string { return w.id }
func (w *Table) HandleResize(ev *tcell.EventResize) { func (w *Table) HandleResize(ev *tcell.EventResize) {
w.w, w.h = ev.Size() w.w, w.h = ev.Size()
} }
func (w *Table) SetKeyMap(km KeyMap, def bool) { func (w *Table) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *Table) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *Table) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *Table) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *Table) HandleKey(ev *tcell.EventKey) bool { func (w *Table) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) return w.keyMap.Handle(ev)
return b1 || b2
} }
func (w *Table) HandleTime(ev *tcell.EventTime) {} func (w *Table) HandleTime(ev *tcell.EventTime) {}
func (w *Table) Draw(screen tcell.Screen) { func (w *Table) Draw(screen tcell.Screen) {

View File

@@ -40,7 +40,7 @@ type Text struct {
visible bool visible bool
active bool active bool
focusable bool focusable bool
keyMap KeyMap keyMap *KeyMap
} }
var _ Widget = (*Text)(nil) var _ Widget = (*Text)(nil)
@@ -62,16 +62,9 @@ func (w *Text) Init(id string, style tcell.Style) {
func (w *Text) Id() string { return w.id } func (w *Text) Id() string { return w.id }
func (w *Text) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } func (w *Text) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() }
func (w *Text) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *Text) GetKeyMap() *KeyMap { return w.keyMap }
func (w *Text) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *Text) SetKeyMap(km *KeyMap) { w.keyMap = km }
func (w *Text) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.keyMap.Remove(k)
}
for r := range km.Runes {
w.keyMap.RemoveRune(r)
}
}
func (w *Text) HandleKey(ev *tcell.EventKey) bool { return w.keyMap.Handle(ev) } func (w *Text) HandleKey(ev *tcell.EventKey) bool { return w.keyMap.Handle(ev) }
func (w *Text) HandleTime(ev *tcell.EventTime) {} func (w *Text) HandleTime(ev *tcell.EventTime) {}
func (w *Text) Draw(screen tcell.Screen) { func (w *Text) Draw(screen tcell.Screen) {

View File

@@ -57,8 +57,8 @@ type TimeField struct {
widgets []Widget widgets []Widget
cursor int cursor int
keyMap, customKeyMap KeyMap keyMap *KeyMap
} }
// TODO: Allow changing the format. // TODO: Allow changing the format.
@@ -87,11 +87,10 @@ func (w *TimeField) Init(id string, style tcell.Style) {
w.fldHour, w.fldMinute, w.fldSecond, w.btnNow, w.fldHour, w.fldMinute, w.fldSecond, w.btnNow,
) )
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyHome: w.handleHome, NewKey(BuildEK(tcell.KeyHome), w.handleHome),
tcell.KeyEnd: w.handleEnd, NewKey(BuildEK(tcell.KeyEnd), w.handleEnd),
}) )
w.customKeyMap = BlankKeyMap()
w.visible = true w.visible = true
w.focusable = true w.focusable = true
} }
@@ -139,22 +138,8 @@ func (w *TimeField) HandleResize(ev *tcell.EventResize) {
} }
} }
func (w *TimeField) SetKeyMap(km KeyMap, def bool) { func (w *TimeField) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *TimeField) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *TimeField) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *TimeField) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *TimeField) HandleKey(ev *tcell.EventKey) bool { func (w *TimeField) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
@@ -162,8 +147,7 @@ func (w *TimeField) HandleKey(ev *tcell.EventKey) bool {
} else if ev.Key() == tcell.KeyTab { } else if ev.Key() == tcell.KeyTab {
return w.handleTab(ev) return w.handleTab(ev)
} }
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) if w.keyMap.Handle(ev) {
if b1 || b2 {
return true return true
} }
if w.cursor <= len(w.widgets) { if w.cursor <= len(w.widgets) {

View File

@@ -43,8 +43,8 @@ type TopMenuLayout struct {
visible bool visible bool
focusable bool focusable bool
layoutFlags LayoutFlag layoutFlags LayoutFlag
keyMap, customKeyMap KeyMap keyMap *KeyMap
logger func(string, ...any) logger func(string, ...any)
} }
@@ -68,18 +68,17 @@ func (w *TopMenuLayout) Init(id string, s tcell.Style) {
w.menu.SetType(MenuTypeH) w.menu.SetType(MenuTypeH)
w.widget = NewBlankWidget("blank") w.widget = NewBlankWidget("blank")
w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ w.keyMap = NewKeyMap(
tcell.KeyEscape: func(ev *tcell.EventKey) bool { NewKey(BuildEK(tcell.KeyEscape), func(ev *tcell.EventKey) bool {
return w.ToggleMenu() return w.ToggleMenu()
}, }),
}) NewKey(BuildEKr(' '), func(ev *tcell.EventKey) bool {
w.keyMap.AddRune(' ', func(ev *tcell.EventKey) bool { if ev.Modifiers()&tcell.ModAlt != 0 {
if ev.Modifiers()&tcell.ModAlt != 0 { return w.ToggleMenu()
return w.ToggleMenu() }
} return false
return false }),
}) )
w.customKeyMap = BlankKeyMap()
} }
func (w *TopMenuLayout) ToggleMenu() bool { func (w *TopMenuLayout) ToggleMenu() bool {
@@ -122,29 +121,14 @@ func (w *TopMenuLayout) HandleResize(ev *tcell.EventResize) {
} }
} }
func (w *TopMenuLayout) SetKeyMap(km KeyMap, def bool) { func (w *TopMenuLayout) GetKeyMap() *KeyMap { return w.keyMap }
if def { func (w *TopMenuLayout) SetKeyMap(km *KeyMap) { w.keyMap = km }
w.keyMap = km
} else {
w.customKeyMap = km
}
}
func (w *TopMenuLayout) AddToKeyMap(km KeyMap) { w.customKeyMap.Merge(km) }
func (w *TopMenuLayout) RemoveFromKeyMap(km KeyMap) {
for k := range km.Keys {
w.customKeyMap.Remove(k)
}
for r := range km.Runes {
w.customKeyMap.RemoveRune(r)
}
}
func (w *TopMenuLayout) HandleKey(ev *tcell.EventKey) bool { func (w *TopMenuLayout) HandleKey(ev *tcell.EventKey) bool {
if !w.active { if !w.active {
return false return false
} }
b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) if w.keyMap.Handle(ev) {
if b1 || b2 {
return true return true
} }
if w.menu != nil && w.menu.Active() { if w.menu != nil && w.menu.Active() {

View File

@@ -33,12 +33,10 @@ type Widget interface {
HandleKey(*tcell.EventKey) bool HandleKey(*tcell.EventKey) bool
HandleTime(*tcell.EventTime) HandleTime(*tcell.EventTime)
// KeyMap Handling // KeyMap Handling
// SetKeyMap sets a new keymap // SetKeyMap overwrites the keymap
// if 'def' is true, the default keymap is overwritten GetKeyMap() *KeyMap
// otherwise, it should be treated as a custom keymap SetKeyMap(km *KeyMap)
SetKeyMap(km KeyMap, def bool)
AddToKeyMap(km KeyMap)
RemoveFromKeyMap(km KeyMap)
Draw(tcell.Screen) Draw(tcell.Screen)
Active() bool Active() bool
SetActive(bool) SetActive(bool)