diff --git a/wdgt_absolute_layout.go b/wdgt_absolute_layout.go index 390e92d..5a69441 100644 --- a/wdgt_absolute_layout.go +++ b/wdgt_absolute_layout.go @@ -91,8 +91,9 @@ func (w *AbsoluteLayout) HandleResize(ev *tcell.EventResize) { w.updateWidgetLayouts() } -func (w *AbsoluteLayout) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *AbsoluteLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +// AbsoluteLayout doesn't have a default keymap +func (w *AbsoluteLayout) SetKeyMap(km KeyMap, def bool) { 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) diff --git a/wdgt_alert.go b/wdgt_alert.go index 115ae2b..8fa6486 100644 --- a/wdgt_alert.go +++ b/wdgt_alert.go @@ -44,7 +44,8 @@ type Alert struct { btnLayout *LinearLayout btnOk, btnCancel *Button - keyMap KeyMap + keyMap, customKeyMap KeyMap + logger func(string, ...any) } @@ -89,6 +90,7 @@ func (w *Alert) Init(id string, style tcell.Style) { tcell.KeyUp: w.SelectNext, tcell.KeyEnter: w.Do, }) + w.customKeyMap = BlankKeyMap() w.focusable = true } func (w *Alert) Id() string { return w.id } @@ -99,14 +101,26 @@ func (w *Alert) HandleResize(ev *tcell.EventResize) { w.layout.HandleResize(tcell.NewEventResize(w.w-2, w.h-2)) } -func (w *Alert) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Alert) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Alert) SetKeyMap(km KeyMap, def bool) { + if def { + 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) } } @@ -114,7 +128,9 @@ func (w *Alert) HandleKey(ev *tcell.EventKey) bool { if !w.active { return false } - return w.keyMap.Handle(ev) + b1 := w.keyMap.Handle(ev) + b2 := w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *Alert) HandleTime(ev *tcell.EventTime) { diff --git a/wdgt_asciiarttext.go b/wdgt_asciiarttext.go index 5cd61d5..724d0fa 100644 --- a/wdgt_asciiarttext.go +++ b/wdgt_asciiarttext.go @@ -66,7 +66,7 @@ func (w *ArtWidget) Init(id string, st tcell.Style) { } func (w *ArtWidget) Id() string { return w.id } func (w *ArtWidget) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } -func (w *ArtWidget) SetKeyMap(km KeyMap) { w.keyMap = km } +func (w *ArtWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *ArtWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *ArtWidget) RemoveFromKeyMap(km KeyMap) { for k := range km.Keys { diff --git a/wdgt_blank.go b/wdgt_blank.go index b87d0ab..102daf7 100644 --- a/wdgt_blank.go +++ b/wdgt_blank.go @@ -35,14 +35,17 @@ type BlankWidget struct { var _ Widget = (*BlankWidget)(nil) func NewBlankWidget(id string) *BlankWidget { - ret := &BlankWidget{id: id} + ret := &BlankWidget{ + id: id, + keyMap: BlankKeyMap(), + } return ret } func (w *BlankWidget) Init(id string, st tcell.Style) { w.keyMap = BlankKeyMap() } func (w *BlankWidget) Id() string { return w.id } func (w *BlankWidget) HandleResize(ev *tcell.EventResize) {} -func (w *BlankWidget) SetKeyMap(km KeyMap) { w.keyMap = km } +func (w *BlankWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *BlankWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *BlankWidget) RemoveFromKeyMap(km KeyMap) { for k := range km.Keys { diff --git a/wdgt_bordered.go b/wdgt_bordered.go index 5505eb3..8ed2778 100644 --- a/wdgt_bordered.go +++ b/wdgt_bordered.go @@ -69,9 +69,9 @@ func (w *BorderedWidget) HandleResize(ev *tcell.EventResize) { w.widget.HandleResize(tcell.NewEventResize(w.w-2, w.h-2)) } -func (w *BorderedWidget) SetKeyMap(km KeyMap) { w.widget.SetKeyMap(km) } -func (w *BorderedWidget) AddToKeyMap(km KeyMap) { w.widget.AddToKeyMap(km) } -func (w *BorderedWidget) RemoveFromKeyMap(km KeyMap) { w.widget.RemoveFromKeyMap(km) } +func (w *BorderedWidget) SetKeyMap(km KeyMap, def bool) { w.widget.SetKeyMap(km, def) } +func (w *BorderedWidget) AddToKeyMap(km KeyMap) { w.widget.AddToKeyMap(km) } +func (w *BorderedWidget) RemoveFromKeyMap(km KeyMap) { w.widget.RemoveFromKeyMap(km) } 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) diff --git a/wdgt_button.go b/wdgt_button.go index fb4e7a2..6692a24 100644 --- a/wdgt_button.go +++ b/wdgt_button.go @@ -36,10 +36,10 @@ type Button struct { x, y int w, h int - active bool - visible bool - focusable bool - keyMap KeyMap + active bool + visible bool + focusable bool + keyMap, customKeyMap KeyMap onPressed func() bool logger func(string, ...any) @@ -60,6 +60,7 @@ func (w *Button) Init(id string, style tcell.Style) { w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{ tcell.KeyEnter: func(ev *tcell.EventKey) bool { return w.onPressed() }, }) + w.customKeyMap = BlankKeyMap() w.onPressed = func() bool { return false } w.focusable = true } @@ -68,14 +69,20 @@ func (w *Button) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } -func (w *Button) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Button) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Button) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -83,7 +90,9 @@ func (w *Button) HandleKey(ev *tcell.EventKey) bool { if !w.active { return false } - return w.keyMap.Handle(ev) + b1 := w.keyMap.Handle(ev) + b2 := w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *Button) HandleTime(ev *tcell.EventTime) {} diff --git a/wdgt_chat.go b/wdgt_chat.go index c28fd44..e9afac3 100644 --- a/wdgt_chat.go +++ b/wdgt_chat.go @@ -51,7 +51,7 @@ type Chat struct { history []ChatMsg historyPosition int - keyMap KeyMap + keyMap, customKeyMap KeyMap } var _ Widget = (*Chat)(nil) @@ -74,14 +74,24 @@ func (w *Chat) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } -func (w *Chat) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Chat) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Chat) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -101,7 +111,9 @@ func (w *Chat) HandleKey(ev *tcell.EventKey) bool { w.value = w.value[:w.cursor] + w.value[w.cursor+1:] } } - if ok := w.keyMap.Handle(ev); ok { + b1 := w.keyMap.Handle(ev) + b2 := w.customKeyMap.Handle(ev) + if b1 || b2 { return true } @@ -245,6 +257,7 @@ func (w *Chat) initKeyMap() { return false }, }) + w.customKeyMap = BlankKeyMap() } func (w *Chat) SetTitle(ttl string) { w.title = ttl } func (w *Chat) Title() string { return w.title } diff --git a/wdgt_checkbox.go b/wdgt_checkbox.go index 9b0c7de..43d4875 100644 --- a/wdgt_checkbox.go +++ b/wdgt_checkbox.go @@ -45,8 +45,8 @@ type Checkbox struct { x, y int w, h int - keyMap KeyMap - stateRunes []rune + keyMap, customKeyMap KeyMap + stateRunes []rune } var _ Widget = (*Checkbox)(nil) @@ -69,20 +69,25 @@ func (w *Checkbox) Init(id string, style tcell.Style) { w.AddToKeyMap(NewRuneMap(map[rune]func(ev *tcell.EventKey) bool{ ' ': w.ToggleState, })) + w.customKeyMap = BlankKeyMap() } -func (w *Checkbox) Id() string { return w.id } -func (w *Checkbox) HandleResize(ev *tcell.EventResize) { - w.w, w.h = ev.Size() -} +func (w *Checkbox) Id() string { return w.id } +func (w *Checkbox) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } -func (w *Checkbox) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Checkbox) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Checkbox) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -90,7 +95,9 @@ func (w *Checkbox) HandleKey(ev *tcell.EventKey) bool { if !w.active { return false } - return w.keyMap.Handle(ev) + b1 := w.keyMap.Handle(ev) + b2 := w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *Checkbox) HandleTime(ev *tcell.EventTime) {} func (w *Checkbox) Draw(screen tcell.Screen) { diff --git a/wdgt_cli.go b/wdgt_cli.go index 104bf37..5887e7e 100644 --- a/wdgt_cli.go +++ b/wdgt_cli.go @@ -54,7 +54,7 @@ type Cli struct { commands []*CliCommand - keyMap KeyMap + keyMap, customKeyMap KeyMap } // TODO: Fix Command/SubCommand finding @@ -81,14 +81,20 @@ func (w *Cli) HandleResize(ev *tcell.EventResize) { } } -func (w *Cli) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Cli) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Cli) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -108,7 +114,8 @@ func (w *Cli) HandleKey(ev *tcell.EventKey) bool { w.value = w.value[:w.cursor] + w.value[w.cursor+1:] } } - if ok := w.keyMap.Handle(ev); ok { + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + if b1 || b2 { return true } diff --git a/wdgt_datepicker.go b/wdgt_datepicker.go index 2de0793..11783dc 100644 --- a/wdgt_datepicker.go +++ b/wdgt_datepicker.go @@ -45,7 +45,7 @@ type DatePicker struct { dateFld *Field dateNow *Button - keyMap KeyMap + keyMap, customKeyMap KeyMap logger func(string, ...any) } @@ -96,14 +96,20 @@ func (w *DatePicker) HandleResize(ev *tcell.EventResize) { w.dateNow.SetPos(Coord{X: wd - 6, Y: 0}) } -func (w *DatePicker) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *DatePicker) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *DatePicker) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -134,7 +140,9 @@ func (w *DatePicker) HandleKey(ev *tcell.EventKey) bool { } else if w.dateNow.Active() { return w.dateNow.HandleKey(ev) } - return w.keyMap.Handle(ev) + b1 := w.keyMap.Handle(ev) + b2 := w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *DatePicker) HandleTime(ev *tcell.EventTime) {} func (w *DatePicker) Draw(screen tcell.Screen) { @@ -191,6 +199,7 @@ func (w *DatePicker) updateUI() { func (w *DatePicker) initKeyMap() { w.keyMap = NewKeyMap(map[tcell.Key]func(ev *tcell.EventKey) bool{}) + w.customKeyMap = BlankKeyMap() } func (w *DatePicker) Format() string { return w.format } diff --git a/wdgt_debug.go b/wdgt_debug.go index dbaa27e..9686cca 100644 --- a/wdgt_debug.go +++ b/wdgt_debug.go @@ -106,8 +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)) } -func (w *DebugWidget) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *DebugWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *DebugWidget) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } +func (w *DebugWidget) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *DebugWidget) RemoveFromKeyMap(km KeyMap) { for k := range km.Keys { w.keyMap.Remove(k) diff --git a/wdgt_field.go b/wdgt_field.go index 3113863..7e83c9f 100644 --- a/wdgt_field.go +++ b/wdgt_field.go @@ -47,7 +47,7 @@ type Field struct { filter func(tcell.EventKey) bool onChange func(prev, curr string) - keyMap KeyMap + keyMap, customKeyMap KeyMap } var _ Widget = (*Field)(nil) @@ -73,20 +73,27 @@ func (w *Field) Init(id string, style tcell.Style) { tcell.KeyEnd: w.handleEnd, tcell.KeyCtrlU: w.clearValueBeforeCursor, }) + w.customKeyMap = BlankKeyMap() w.focusable = true } func (w *Field) Id() string { return w.id } func (w *Field) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } -func (w *Field) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Field) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Field) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -107,7 +114,9 @@ func (w *Field) HandleKey(ev *tcell.EventKey) bool { return w.handleBackspace(ev) } } - if ok := w.keyMap.Handle(ev); ok { + b1 := w.keyMap.Handle(ev) + b2 := w.customKeyMap.Handle(ev) + if b1 || b2 { return true } if w.filter != nil && !w.filter(*ev) { @@ -250,6 +259,12 @@ func (w *Field) SetValue(v string) { prev := w.value w.value = v w.doOnChange(prev, v) + if w.cursor > len(v) { + w.cursor = len(v) + } + if w.cursor < 0 { + w.cursor = 0 + } } func (w *Field) Value() string { return w.value } diff --git a/wdgt_filepicker.go b/wdgt_filepicker.go index 8cc747a..9042b84 100644 --- a/wdgt_filepicker.go +++ b/wdgt_filepicker.go @@ -50,7 +50,7 @@ type FilePicker struct { fileList *SimpleList btnSelect, btnCancel *Button - keyMap KeyMap + keyMap, customKeyMap KeyMap } var _ Widget = (*FilePicker)(nil) @@ -75,6 +75,7 @@ func (w *FilePicker) Init(id string, style tcell.Style) { w.layout.Add(w.btnCancel, nil, RelAncBL) w.focusable = true w.keyMap = BlankKeyMap() + w.customKeyMap = BlankKeyMap() } func (w *FilePicker) Id() string { return w.id } func (w *FilePicker) HandleResize(ev *tcell.EventResize) { @@ -84,14 +85,20 @@ func (w *FilePicker) HandleResize(ev *tcell.EventResize) { w.btnCancel.SetPos(Coord{X: w.x + 1, Y: w.y + w.h - 1}) } -func (w *FilePicker) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *FilePicker) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *FilePicker) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -99,7 +106,9 @@ func (w *FilePicker) HandleKey(ev *tcell.EventKey) bool { if !w.active { return false } - return w.keyMap.Handle(ev) + b1 := w.keyMap.Handle(ev) + b2 := w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *FilePicker) HandleTime(ev *tcell.EventTime) { w.layout.HandleTime(ev) } func (w *FilePicker) Draw(screen tcell.Screen) { diff --git a/wdgt_form.go b/wdgt_form.go index f05f366..581946d 100644 --- a/wdgt_form.go +++ b/wdgt_form.go @@ -45,7 +45,7 @@ type Form struct { hasSubmit bool hasCancel bool - keyMap KeyMap + keyMap, customKeyMap KeyMap } var _ Widget = (*Form)(nil) @@ -63,6 +63,8 @@ func (w *Form) Init(id string, style tcell.Style) { w.focusable = true w.submit = NewButton(fmt.Sprintf("%s-submit", id), style) w.cancel = NewButton(fmt.Sprintf("%s-cancel", id), style) + w.keyMap = BlankKeyMap() + w.customKeyMap = BlankKeyMap() } func (w *Form) Id() string { return w.id } @@ -90,14 +92,20 @@ func (w *Form) HandleResize(ev *tcell.EventResize) { } } -func (w *Form) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Form) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Form) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -121,7 +129,9 @@ func (w *Form) HandleKey(ev *tcell.EventKey) bool { w.updateWidgets() return w.cursor > pre } - return false + b1 := w.keyMap.Handle(ev) + b2 := w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *Form) HandleTime(ev *tcell.EventTime) {} func (w *Form) Draw(screen tcell.Screen) { diff --git a/wdgt_linear_layout.go b/wdgt_linear_layout.go index 387335c..2aebbe3 100644 --- a/wdgt_linear_layout.go +++ b/wdgt_linear_layout.go @@ -56,7 +56,7 @@ type LinearLayout struct { disableTab bool insetBorder bool - keyMap KeyMap + keyMap, customKeyMap KeyMap logger func(string, ...any) } @@ -98,6 +98,7 @@ func (w *LinearLayout) Init(id string, s tcell.Style) { } return w.ActivateNext() }) + w.customKeyMap = BlankKeyMap() } func (w *LinearLayout) Id() string { return w.id } @@ -106,14 +107,20 @@ func (w *LinearLayout) HandleResize(ev *tcell.EventResize) { w.updateWidgetLayouts() } -func (w *LinearLayout) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *LinearLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *LinearLayout) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -128,7 +135,8 @@ func (w *LinearLayout) HandleKey(ev *tcell.EventKey) bool { return true } } - return w.keyMap.Handle(ev) + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *LinearLayout) GetActiveWidgetIdx() int { return w.findActiveIdx() } @@ -494,6 +502,9 @@ func (w *LinearLayout) updateLLVWidgetPos(wd Widget) { c := Coord{} for i := range w.widgets { if w.widgets[i] == wd { + if i > 0 { + c.Y += 1 + } break } if w.widgets[i].Visible() { @@ -590,7 +601,11 @@ func (w *LinearLayout) getWeightedH(wd Widget) int { } else if w.stacked { return wd.MinH() } - return int(float64(w.h)*(float64(w.GetWeight(wd))/float64(w.totalWeight))) - 1 + use := int(float64(w.h)*(float64(w.GetWeight(wd))/float64(w.totalWeight))) - 1 + if use < wd.MinH() { + return wd.MinH() + } + return use } func (w *LinearLayout) getWeightedW(wd Widget) int { @@ -599,7 +614,11 @@ func (w *LinearLayout) getWeightedW(wd Widget) int { } else if w.stacked { return wd.MinW() } - return int(float64(w.w)*(float64(w.GetWeight(wd))/float64(w.totalWeight))) - 1 + use := int(float64(w.w)*(float64(w.GetWeight(wd))/float64(w.totalWeight))) - 1 + if use < wd.MinW() { + return wd.MinW() + } + return use } func (w *LinearLayout) SetStacked(s bool) { w.stacked = s } diff --git a/wdgt_menu.go b/wdgt_menu.go index 743a05b..b6768d1 100644 --- a/wdgt_menu.go +++ b/wdgt_menu.go @@ -47,7 +47,7 @@ type Menu struct { expanded bool vimMode bool - keyMap KeyMap + keyMap, customKeyMap KeyMap } type MenuType int @@ -81,6 +81,7 @@ func (w *Menu) Init(id string, style tcell.Style) { return false }, }) + w.customKeyMap = BlankKeyMap() w.focusable = true } func (w *Menu) Id() string { return w.id } @@ -123,14 +124,20 @@ func (w *Menu) handleResizeV(_ *tcell.EventResize) { } } -func (w *Menu) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Menu) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Menu) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -144,10 +151,12 @@ func (w *Menu) HandleKey(ev *tcell.EventKey) bool { w.SetActive(false) } return true - } else if ok := w.keyMap.Handle(ev); ok { - // Otherwise see if we handle it + } + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + if b1 || b2 { 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()) { diff --git a/wdgt_menu_item.go b/wdgt_menu_item.go index fb10a14..cdba34d 100644 --- a/wdgt_menu_item.go +++ b/wdgt_menu_item.go @@ -51,7 +51,7 @@ type MenuItem struct { expanded bool disabled bool - keyMap KeyMap + keyMap, customKeyMap KeyMap } var _ Widget = (*MenuItem)(nil) @@ -78,6 +78,8 @@ func (w *MenuItem) Init(id string, style tcell.Style) { return false }, }) + w.customKeyMap = BlankKeyMap() + for i := range w.items { w.items[i].SetActive(i == w.cursor) } @@ -89,14 +91,20 @@ func (w *MenuItem) HandleResize(ev *tcell.EventResize) { // TODO: Trickle-down HandleResize } -func (w *MenuItem) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *MenuItem) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *MenuItem) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -119,7 +127,8 @@ func (w *MenuItem) HandleKey(ev *tcell.EventKey) bool { } } // Look for a sub-item that's selected - return w.keyMap.Handle(ev) + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *MenuItem) HandleTime(ev *tcell.EventTime) { diff --git a/wdgt_prompt.go b/wdgt_prompt.go index c178f63..a095a25 100644 --- a/wdgt_prompt.go +++ b/wdgt_prompt.go @@ -46,7 +46,7 @@ type Prompt struct { btnOk, btnCancel *Button onOk func(string) bool - keyMap KeyMap + keyMap, customKeyMap KeyMap } var _ Widget = (*Prompt)(nil) @@ -68,6 +68,7 @@ func (w *Prompt) Init(id string, style tcell.Style) { w.btnCancel.SetLabel("Cancel") w.focusable = true w.keyMap = BlankKeyMap() + w.customKeyMap = BlankKeyMap() } func (w *Prompt) Id() string { return w.id } func (w *Prompt) HandleResize(ev *tcell.EventResize) { @@ -83,14 +84,20 @@ func (w *Prompt) HandleResize(ev *tcell.EventResize) { w.btnCancel.SetPos(Coord{X: w.x + 1, Y: w.y + w.h - 1}) } -func (w *Prompt) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Prompt) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Prompt) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -98,7 +105,8 @@ func (w *Prompt) HandleKey(ev *tcell.EventKey) bool { if !w.active { return false } - return w.keyMap.Handle(ev) + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *Prompt) HandleTime(ev *tcell.EventTime) { diff --git a/wdgt_relative_layout.go b/wdgt_relative_layout.go index 6063b82..cdc4ecd 100644 --- a/wdgt_relative_layout.go +++ b/wdgt_relative_layout.go @@ -84,8 +84,8 @@ func (w *RelativeLayout) HandleResize(ev *tcell.EventResize) { // TODO: Trickle-down HandleResize } -func (w *RelativeLayout) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *RelativeLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *RelativeLayout) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } +func (w *RelativeLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *RelativeLayout) RemoveFromKeyMap(km KeyMap) { for k := range km.Keys { w.keyMap.Remove(k) diff --git a/wdgt_searcher.go b/wdgt_searcher.go index 612301d..2304fdf 100644 --- a/wdgt_searcher.go +++ b/wdgt_searcher.go @@ -50,7 +50,7 @@ type Searcher struct { hideOnSelect bool logger func(string, ...any) - keyMap KeyMap + keyMap, customKeyMap KeyMap } var _ Widget = (*Searcher)(nil) @@ -79,6 +79,7 @@ func (w *Searcher) Init(id string, style tcell.Style) { tcell.KeyPgDn: w.handleKeyPgDn, tcell.KeyEnter: w.handleKeyEnter, }) + w.customKeyMap = BlankKeyMap() w.focusable = true } @@ -94,21 +95,29 @@ func (w *Searcher) HandleResize(ev *tcell.EventResize) { w.search.HandleResize(Coord{X: aW, Y: aH}.ResizeEvent()) } -func (w *Searcher) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Searcher) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Searcher) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } func (w *Searcher) HandleKey(ev *tcell.EventKey) bool { if !w.active { return false - } else if ok := w.keyMap.Handle(ev); ok { + } + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + if b1 || b2 { return true } return w.search.HandleKey(ev) @@ -174,18 +183,18 @@ func (w *Searcher) handleKeyEnter(ev *tcell.EventKey) bool { if w.hideOnSelect { w.visible = false } - if w.selectFunc != nil { - // Figure out our true index - var idx int - selV := w.filteredData[w.cursor] - for i := range w.data { - if w.data[i] == selV { - idx = i - } - } - return w.selectFunc(idx, selV) + if w.selectFunc == nil || len(w.filteredData) <= w.cursor { + return false } - return false + // Figure out our true index + var idx int + selV := w.filteredData[w.cursor] + for i := range w.data { + if w.data[i] == selV { + idx = i + } + } + return w.selectFunc(idx, selV) } func (w *Searcher) HandleTime(ev *tcell.EventTime) { w.search.HandleTime(ev) } diff --git a/wdgt_shrinkwrap.go b/wdgt_shrinkwrap.go index 27ddc16..45e6735 100644 --- a/wdgt_shrinkwrap.go +++ b/wdgt_shrinkwrap.go @@ -39,7 +39,7 @@ 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) HandleResize(ev *tcell.EventResize) { w.widget.HandleResize(ev) } -func (w *ShrinkWrap) SetKeyMap(km KeyMap) { w.widget.SetKeyMap(km) } +func (w *ShrinkWrap) SetKeyMap(km KeyMap, def bool) { w.widget.SetKeyMap(km, def) } func (w *ShrinkWrap) AddToKeyMap(km KeyMap) { w.widget.AddToKeyMap(km) } func (w *ShrinkWrap) RemoveFromKeyMap(km KeyMap) { w.widget.RemoveFromKeyMap(km) } func (w *ShrinkWrap) HandleKey(ev *tcell.EventKey) bool { return w.widget.HandleKey(ev) } diff --git a/wdgt_simple_list.go b/wdgt_simple_list.go index 84307d0..c81c304 100644 --- a/wdgt_simple_list.go +++ b/wdgt_simple_list.go @@ -43,9 +43,10 @@ type SimpleList struct { list []string itemsStyle map[int]tcell.Style - onSelect func(int, string) bool - keyMap KeyMap - vimMode bool + onChange func(int, string) bool + onSelect func(int, string) bool + keyMap, customKeyMap KeyMap + vimMode bool logger func(string, ...any) } @@ -84,22 +85,27 @@ func (w *SimpleList) Init(id string, style tcell.Style) { } return false }) + w.customKeyMap = BlankKeyMap() w.itemsStyle = make(map[int]tcell.Style) w.focusable = true } -func (w *SimpleList) Id() string { return w.id } -func (w *SimpleList) HandleResize(ev *tcell.EventResize) { - w.w, w.h = ev.Size() -} +func (w *SimpleList) Id() string { return w.id } +func (w *SimpleList) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } -func (w *SimpleList) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *SimpleList) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *SimpleList) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -107,8 +113,10 @@ func (w *SimpleList) HandleKey(ev *tcell.EventKey) bool { if !w.active || !w.focusable { return false } - return w.keyMap.Handle(ev) + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + return b1 || b2 } + func (w *SimpleList) HandleTime(ev *tcell.EventTime) {} func (w *SimpleList) Draw(screen tcell.Screen) { dS := w.style @@ -192,9 +200,15 @@ func (w *SimpleList) SetCursorWrap(b bool) { w.cursorWrap = b } func (w *SimpleList) MoveUp() bool { if w.cursor > 0 { w.cursor-- + if w.onChange != nil { + w.onChange(w.cursor, w.list[w.cursor]) + } return true } else if w.cursorWrap { w.cursor = len(w.list) - 1 + if w.onChange != nil { + w.onChange(w.cursor, w.list[w.cursor]) + } return true } return false @@ -203,9 +217,15 @@ func (w *SimpleList) MoveUp() bool { func (w *SimpleList) MoveDown() bool { if w.cursor < len(w.list)-1 { w.cursor++ + if w.onChange != nil { + w.onChange(w.cursor, w.list[w.cursor]) + } return true } else if w.cursorWrap { w.cursor = 0 + if w.onChange != nil { + w.onChange(w.cursor, w.list[w.cursor]) + } return true } return false @@ -266,3 +286,7 @@ func (w *SimpleList) Log(txt string, args ...any) { w.logger(txt, args...) } } + +func (w *SimpleList) SetOnChange(c func(int, string) bool) { w.onChange = c } + +func (w *SimpleList) GetAllItemStyles() map[int]tcell.Style { return w.itemsStyle } diff --git a/wdgt_spinner.go b/wdgt_spinner.go index e0feaa0..4fe5355 100644 --- a/wdgt_spinner.go +++ b/wdgt_spinner.go @@ -54,7 +54,7 @@ func (w *Spinner) Init(id string, st tcell.Style) { } func (w *Spinner) Id() string { return w.id } func (w *Spinner) HandleResize(ev *tcell.EventResize) {} -func (w *Spinner) SetKeyMap(km KeyMap) { w.keyMap = km } +func (w *Spinner) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } func (w *Spinner) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *Spinner) RemoveFromKeyMap(km KeyMap) { for k := range km.Keys { diff --git a/wdgt_table.go b/wdgt_table.go index d34fcf1..efc1b70 100644 --- a/wdgt_table.go +++ b/wdgt_table.go @@ -52,7 +52,7 @@ type Table struct { columnWidths []int - keyMap KeyMap + keyMap, customKeyMap KeyMap } var _ Widget = (*Table)(nil) @@ -85,20 +85,27 @@ func (w *Table) Init(id string, style tcell.Style) { w.border = wh.BRD_CSIMPLE w.focusable = true w.keyMap = BlankKeyMap() + w.customKeyMap = BlankKeyMap() } func (w *Table) Id() string { return w.id } func (w *Table) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } -func (w *Table) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Table) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Table) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -106,7 +113,8 @@ func (w *Table) HandleKey(ev *tcell.EventKey) bool { if !w.active { return false } - return w.keyMap.Handle(ev) + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + return b1 || b2 } func (w *Table) HandleTime(ev *tcell.EventTime) {} func (w *Table) Draw(screen tcell.Screen) { diff --git a/wdgt_text.go b/wdgt_text.go index ad3a0c4..42ee396 100644 --- a/wdgt_text.go +++ b/wdgt_text.go @@ -62,8 +62,8 @@ func (w *Text) Init(id string, style tcell.Style) { func (w *Text) Id() string { return w.id } func (w *Text) HandleResize(ev *tcell.EventResize) { w.w, w.h = ev.Size() } -func (w *Text) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *Text) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *Text) SetKeyMap(km KeyMap, def bool) { w.keyMap = km } +func (w *Text) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } func (w *Text) RemoveFromKeyMap(km KeyMap) { for k := range km.Keys { w.keyMap.Remove(k) @@ -72,7 +72,7 @@ func (w *Text) RemoveFromKeyMap(km KeyMap) { w.keyMap.RemoveRune(r) } } -func (w *Text) HandleKey(ev *tcell.EventKey) bool { return false } +func (w *Text) HandleKey(ev *tcell.EventKey) bool { return w.keyMap.Handle(ev) } func (w *Text) HandleTime(ev *tcell.EventTime) {} func (w *Text) Draw(screen tcell.Screen) { if !w.visible { diff --git a/wdgt_timefield.go b/wdgt_timefield.go index e786e3e..e549ad2 100644 --- a/wdgt_timefield.go +++ b/wdgt_timefield.go @@ -57,8 +57,8 @@ type TimeField struct { widgets []Widget - cursor int - keyMap KeyMap + cursor int + keyMap, customKeyMap KeyMap } // TODO: Allow changing the format. @@ -91,6 +91,7 @@ func (w *TimeField) Init(id string, style tcell.Style) { tcell.KeyHome: w.handleHome, tcell.KeyEnd: w.handleEnd, }) + w.customKeyMap = BlankKeyMap() w.visible = true w.focusable = true } @@ -138,14 +139,20 @@ func (w *TimeField) HandleResize(ev *tcell.EventResize) { } } -func (w *TimeField) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *TimeField) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *TimeField) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -154,9 +161,12 @@ func (w *TimeField) HandleKey(ev *tcell.EventKey) bool { return false } else if ev.Key() == tcell.KeyTab { return w.handleTab(ev) - } else if w.keyMap.Handle(ev) { + } + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + if b1 || b2 { return true - } else if w.cursor <= len(w.widgets) { + } + if w.cursor <= len(w.widgets) { return w.widgets[w.cursor].HandleKey(ev) } return false diff --git a/wdgt_top_menu_layout.go b/wdgt_top_menu_layout.go index ba25a69..1628184 100644 --- a/wdgt_top_menu_layout.go +++ b/wdgt_top_menu_layout.go @@ -43,8 +43,8 @@ type TopMenuLayout struct { visible bool focusable bool - layoutFlags LayoutFlag - keyMap KeyMap + layoutFlags LayoutFlag + keyMap, customKeyMap KeyMap logger func(string, ...any) } @@ -79,6 +79,7 @@ func (w *TopMenuLayout) Init(id string, s tcell.Style) { } return false }) + w.customKeyMap = BlankKeyMap() } func (w *TopMenuLayout) ToggleMenu() bool { @@ -121,14 +122,20 @@ func (w *TopMenuLayout) HandleResize(ev *tcell.EventResize) { } } -func (w *TopMenuLayout) SetKeyMap(km KeyMap) { w.keyMap = km } -func (w *TopMenuLayout) AddToKeyMap(km KeyMap) { w.keyMap.Merge(km) } +func (w *TopMenuLayout) SetKeyMap(km KeyMap, def bool) { + if def { + 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.keyMap.Remove(k) + w.customKeyMap.Remove(k) } for r := range km.Runes { - w.keyMap.RemoveRune(r) + w.customKeyMap.RemoveRune(r) } } @@ -136,8 +143,8 @@ func (w *TopMenuLayout) HandleKey(ev *tcell.EventKey) bool { if !w.active { return false } - - if w.keyMap.Handle(ev) { + b1, b2 := w.keyMap.Handle(ev), w.customKeyMap.Handle(ev) + if b1 || b2 { return true } if w.menu != nil && w.menu.Active() { diff --git a/widget.go b/widget.go index d131c65..e904cd8 100644 --- a/widget.go +++ b/widget.go @@ -32,7 +32,11 @@ type Widget interface { HandleResize(*tcell.EventResize) HandleKey(*tcell.EventKey) bool HandleTime(*tcell.EventTime) - SetKeyMap(km KeyMap) + // KeyMap Handling + // SetKeyMap sets a new keymap + // if 'def' is true, the default keymap is overwritten + // otherwise, it should be treated as a custom keymap + SetKeyMap(km KeyMap, def bool) AddToKeyMap(km KeyMap) RemoveFromKeyMap(km KeyMap) Draw(tcell.Screen)