Skip to content
This repository has been archived by the owner on Feb 3, 2023. It is now read-only.

Commit

Permalink
form handle key up down and enter
Browse files Browse the repository at this point in the history
  • Loading branch information
ingbyr committed Sep 10, 2022
1 parent 4d08b04 commit bb66991
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 58 deletions.
26 changes: 16 additions & 10 deletions tui/form/choice.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (
FocusLastMode
)

var _ Widget = (*Choices)(nil)
var _ Item = (*Choices)(nil)

func NewChoice(items []list.DefaultItem) *Choices {
return &Choices{
Expand Down Expand Up @@ -107,7 +107,9 @@ func (c *Choices) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
c.cursorIndex++
}
case key.Matches(m, keys.Enter):
c.selectedIndex = c.cursorIndex
if c.cursorIndex >= 0 {
c.selectedIndex = c.cursorIndex
}
}
}
log.Debug(fmt.Sprintf("choice cursor %d selected %d", c.cursorIndex, c.selectedIndex))
Expand All @@ -121,9 +123,9 @@ func (c *Choices) Focus(mode FocusMode) tea.Cmd {
return nil
}
if mode == FocusFirstMode {
c.cursorIndex = -1
c.cursorIndex = 0
} else if mode == FocusLastMode {
c.cursorIndex = len(c.items)
c.cursorIndex = len(c.items) - 1
}
return nil
}
Expand All @@ -134,12 +136,16 @@ func (c *Choices) Unfocus() tea.Cmd {
return nil
}

func (c *Choices) HandleKeyUp() bool {
return !(c.cursorIndex == 0)
}

func (c *Choices) HandleKeyDown() bool {
return !(c.cursorIndex == len(c.Items())-1)
func (c *Choices) InterceptKey(keyMsg tea.KeyMsg) bool {
switch {
case key.Matches(keyMsg, keys.Up):
return !(c.cursorIndex == 0)
case key.Matches(keyMsg, keys.Down):
return !(c.cursorIndex == len(c.Items())-1)
case key.Matches(keyMsg, keys.Enter):
return true
}
return false
}

func (c *Choices) SetWidth(width int) {
Expand Down
70 changes: 43 additions & 27 deletions tui/form/form.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

type Form interface {
tea.Model
AddWidget(widget Widget)
AddWidget(widget Item)
FocusNextWidget() []tea.Cmd
FocusPreWidget() []tea.Cmd
SetSize(width, height int)
Expand All @@ -22,15 +22,15 @@ var _ Form = (*BaseForm)(nil)

func New() *BaseForm {
return &BaseForm{
Widgets: make([]Widget, 0),
Items: make([]Item, 0),
WidgetStyle: styles.None,
preFocus: 0,
focus: 0,
}
}

type BaseForm struct {
Widgets []Widget
Items []Item
WidgetStyle lipgloss.Style
preFocus int
focus int
Expand All @@ -39,7 +39,7 @@ type BaseForm struct {
}

func (v *BaseForm) Init() tea.Cmd {
panic("implement me")
return nil
}

func (v *BaseForm) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
Expand All @@ -50,14 +50,36 @@ func (v *BaseForm) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
v.SetSize(m.Width, m.Height)
return v, nil
case tea.KeyMsg:
focusedItem := v.Items[v.focus]
switch {
case key.Matches(m, keys.Up), key.Matches(m, keys.Down):
_, cmd = v.Widgets[v.focus].Update(msg)
case key.Matches(m, keys.Up):
intercepted := focusedItem.InterceptKey(m)
_, cmd = focusedItem.Update(msg)
if intercepted {
return v, cmd
}
cmds = append(cmds, v.FocusPreWidget()...)
return v, cmd
case key.Matches(m, keys.Down):
intercepted := focusedItem.InterceptKey(m)
_, cmd = focusedItem.Update(msg)
if intercepted {
return v, cmd
}
cmds = append(cmds, v.FocusNextWidget()...)
return v, cmd
case key.Matches(m, keys.Enter):
intercepted := focusedItem.InterceptKey(m)
_, cmd = focusedItem.Update(msg)
if intercepted {
return v, cmd
}
cmds = append(cmds, v.FocusNextWidget()...)
return v, cmd
}
}
for i := 0; i < len(v.Widgets); i++ {
_, cmd = v.Widgets[i].Update(msg)
for i := 0; i < len(v.Items); i++ {
_, cmd = v.Items[i].Update(msg)
cmds = append(cmds, cmd)
}

Expand All @@ -66,16 +88,16 @@ func (v *BaseForm) Update(msg tea.Msg) (tea.Model, tea.Cmd) {

func (v *BaseForm) View() string {
var str string
for i := 0; i < len(v.Widgets); i++ {
w := v.Widgets[i]
for i := 0; i < len(v.Items); i++ {
w := v.Items[i]
if w.Height()+lipgloss.Height(str) > v.height {
return str
}
if i == 0 {
str = lipgloss.JoinVertical(lipgloss.Left, w.View())
continue
}
str = lipgloss.JoinVertical(lipgloss.Left, str, v.Widgets[i].View())
str = lipgloss.JoinVertical(lipgloss.Left, str, v.Items[i].View())
//log.Debug(fmt.Sprintf("cur h %d, view h %d", lipgloss.Height(str), v.height))
}
return str
Expand All @@ -84,11 +106,11 @@ func (v *BaseForm) SetSize(width, height int) {
v.width = width
v.height = height
remain := v.height
height = v.height / len(v.Widgets)
for i := 0; i < len(v.Widgets); i++ {
w := v.Widgets[i]
height = v.height / len(v.Items)
for i := 0; i < len(v.Items); i++ {
w := v.Items[i]
w.SetWidth(width)
if i == len(v.Widgets)-1 {
if i == len(v.Items)-1 {
w.SetHeight(remain)
log.Debug(fmt.Sprintf("base view w %d h %d", width, w.Height()))
} else {
Expand All @@ -99,11 +121,11 @@ func (v *BaseForm) SetSize(width, height int) {
}
}

func (v *BaseForm) AddWidget(widget Widget) {
func (v *BaseForm) AddWidget(widget Item) {
if widget == nil {
return
}
v.Widgets = append(v.Widgets, widget)
v.Items = append(v.Items, widget)
}

func (v *BaseForm) FocusNextWidget() []tea.Cmd {
Expand All @@ -123,23 +145,17 @@ func (v *BaseForm) FocusPreWidget() []tea.Cmd {
}

func (v *BaseForm) idxAfterFocusWidget() int {
if v.Widgets[v.focus].HandleKeyDown() {
return v.focus
}
idx := v.focus + 1
if idx >= len(v.Widgets) {
if idx >= len(v.Items) {
idx = 0
}
return idx
}

func (v *BaseForm) idxBeforeFocusWidget() int {
if v.Widgets[v.focus].HandleKeyUp() {
return v.focus
}
idx := v.focus - 1
if idx < 0 {
idx = len(v.Widgets) - 1
idx = len(v.Items) - 1
}
return idx
}
Expand All @@ -148,7 +164,7 @@ func (v *BaseForm) setFocusWidget(idx int, mode FocusMode) []tea.Cmd {
v.preFocus = v.focus
v.focus = idx
return []tea.Cmd{
v.Widgets[v.preFocus].Unfocus(),
v.Widgets[v.focus].Focus(mode),
v.Items[v.preFocus].Unfocus(),
v.Items[v.focus].Focus(mode),
}
}
5 changes: 2 additions & 3 deletions tui/form/widget.go → tui/form/item.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import (

var cfg = config.Instance()

type Widget interface {
type Item interface {
tea.Model
Focus(mode FocusMode) tea.Cmd
Unfocus() tea.Cmd
HandleKeyUp() bool
HandleKeyDown() bool
SetWidth(width int)
SetHeight(height int)
Width() int
Height() int
InterceptKey(m tea.KeyMsg) bool
}
8 changes: 2 additions & 6 deletions tui/form/textinput.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"gohost/tui/styles"
)

var _ Widget = (*TextInput)(nil)
var _ Item = (*TextInput)(nil)

func NewTextInput() *TextInput {
t := &TextInput{
Expand Down Expand Up @@ -59,10 +59,6 @@ func (t *TextInput) Unfocus() tea.Cmd {
return nil
}

func (t *TextInput) HandleKeyUp() bool {
return false
}

func (t *TextInput) HandleKeyDown() bool {
func (t *TextInput) InterceptKey(keyMsg tea.KeyMsg) bool {
return false
}
14 changes: 2 additions & 12 deletions tui/node_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package tui

import (
"fmt"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
Expand Down Expand Up @@ -62,21 +61,12 @@ func (v *NodeView) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
log.Debug(fmt.Sprintf("node view w %d h %d", m.Width, m.Height))
case tea.KeyMsg:
if v.model.state == nodeViewState {
switch {
// FIXME enter duplicated on last item
case key.Matches(m, keys.Up):
cmds = append(cmds, v.FocusPreWidget()...)
case key.Matches(m, keys.Down):
cmds = append(cmds, v.FocusNextWidget()...)
}
_, cmd = v.BaseForm.Update(msg)
} else {
return nil, tea.Batch(cmds...)
return nil, nil
}
}

_, cmd = v.BaseForm.Update(msg)
cmds = append(cmds, cmd)

return v, tea.Batch(cmds...)
}

Expand Down

0 comments on commit bb66991

Please sign in to comment.