diff --git a/tui/form/choice.go b/tui/form/choice.go index 77be3b4..fcf067d 100644 --- a/tui/form/choice.go +++ b/tui/form/choice.go @@ -22,31 +22,33 @@ var _ Item = (*Choices)(nil) func NewChoice(items []list.DefaultItem) *Choices { return &Choices{ - items: items, - SelectedPrefix: "[v]", - UnselectedPrefix: "[ ]", - MorePlaceHold: "...", - width: 0, - height: 0, - Spacing: 1, - focused: false, - cursorIndex: -1, - selectedIndex: -1, + items: items, + SelectedPrefix: "[v]", + UnselectedPrefix: "[ ]", + MorePlaceHold: "...", + ShowMorePlaceHold: true, + width: 0, + height: 0, + Spacing: 1, + focused: false, + cursorIndex: -1, + selectedIndex: -1, } } type Choices struct { - items []list.DefaultItem - SelectedPrefix string - UnselectedPrefix string - MorePlaceHold string - focused bool - focusedStyle lipgloss.Style - unfocusedStyle lipgloss.Style - width, height int - Spacing int - cursorIndex int - selectedIndex int + items []list.DefaultItem + SelectedPrefix string + UnselectedPrefix string + MorePlaceHold string + ShowMorePlaceHold bool + focused bool + focusedStyle lipgloss.Style + unfocusedStyle lipgloss.Style + width, height int + Spacing int + cursorIndex int + selectedIndex int } func (c *Choices) SetFocusedStyle(style lipgloss.Style) { @@ -62,34 +64,16 @@ func (c *Choices) Items() []list.DefaultItem { } func (c *Choices) View() string { - if c.height <= 0 { - return "" - } - h := 0 var b strings.Builder - for i := 0; i < len(c.items); i++ { - var ph int - if i == len(c.items)-1 { - ph = h + 1 - } else { - ph = h + 1 + c.Spacing - } - if ph > c.height { - b.WriteString(c.MorePlaceHold) - break - } else if ph == c.height && i != len(c.items)-1 { - b.WriteString(c.MorePlaceHold) - break - } - + for i := range c.items { if i == c.cursorIndex { b.WriteString(c.focusedStyle.Render(c.itemTitle(i))) } else { b.WriteString(c.unfocusedStyle.Render(c.itemTitle(i))) } - b.WriteString(cfg.LineBreak) - b.WriteString(strings.Repeat(cfg.LineBreak, c.Spacing)) - h += ph + if i < len(c.items)-1 { + b.WriteString(strings.Repeat(cfg.LineBreak, c.Spacing+1)) + } } return b.String() } @@ -171,6 +155,12 @@ func (c *Choices) SetWidth(width int) { func (c *Choices) SetHeight(height int) { c.height = height + ah := len(c.items) + len(c.items)*c.Spacing - 1 + if ah < height { + c.height = ah + } else { + c.height = height + } } func (c *Choices) itemTitle(idx int) string { diff --git a/tui/form/form.go b/tui/form/form.go index 7864624..99ac59c 100644 --- a/tui/form/form.go +++ b/tui/form/form.go @@ -1,11 +1,10 @@ package form import ( - "fmt" "github.com/charmbracelet/bubbles/key" + "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" - "gohost/log" "gohost/tui/keys" "gohost/tui/styles" "strings" @@ -16,7 +15,9 @@ func New() *Form { Items: make([]Item, 0), ItemFocusedStyle: styles.None, ItemUnfocusedStyle: styles.None, + MorePlaceHold: "...", Spacing: 0, + viewport: viewport.New(0, 0), preFocus: 0, focus: 0, } @@ -26,7 +27,9 @@ type Form struct { Items []Item ItemFocusedStyle lipgloss.Style ItemUnfocusedStyle lipgloss.Style + MorePlaceHold string Spacing int + viewport viewport.Model preFocus int focus int width int @@ -34,7 +37,7 @@ type Form struct { } func (v *Form) Init() tea.Cmd { - return nil + return v.viewport.Init() } func (v *Form) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -82,48 +85,24 @@ func (v *Form) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (v *Form) View() string { - if len(v.Items) == 0 { - return "" - } - h := v.Items[0].Height() - if h > v.height { - return "" - } - str := lipgloss.JoinVertical(lipgloss.Left, v.Items[0].View()) - - for i := 1; i < len(v.Items); i++ { - w := v.Items[i] - if i == len(v.Items) - 1 { - h += w.Height() - } else { - h += w.Height() + v.Spacing - } - if h >= v.height { - return str + var b strings.Builder + for i := range v.Items { + b.WriteString(v.Items[i].View()) + if i < len(v.Items)-1 { + b.WriteString(strings.Repeat(cfg.LineBreak, v.Spacing+1)) } - str += strings.Repeat(cfg.LineBreak, v.Spacing) - 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 + v.viewport.SetContent(b.String()) + return v.viewport.View() } func (v *Form) SetSize(width, height int) { v.width = width v.height = height - remain := v.height - len(v.Items) * v.Spacing + 1 - 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.Items)-1 { - w.SetHeight(remain) - log.Debug(fmt.Sprintf("base view w %d h %d", width, w.Height())) - } else { - w.SetHeight(height) - remain -= w.Height() - log.Debug(fmt.Sprintf("base view w %d h %d", width, w.Height())) - } + for _, item := range v.Items { + item.SetWidth(width) + v.viewport.Width = width + v.viewport.Height = height } } diff --git a/tui/node_view.go b/tui/node_view.go index 697f8f3..2e78344 100644 --- a/tui/node_view.go +++ b/tui/node_view.go @@ -19,7 +19,7 @@ type NodeView struct { func NewNodeView(model *Model) *NodeView { // Text inputs nodeNameTextInput := form.NewTextInput() - nodeNameTextInput.Prompt = "ID: " + nodeNameTextInput.Prompt = "Name: " nodeNameTextInput.Focus(form.FocusFirstMode) descTextInput := form.NewTextInput() @@ -31,6 +31,7 @@ func NewNodeView(model *Model) *NodeView { // Node type choices nodeTypeChoices := form.NewChoice([]list.DefaultItem{GroupNode, LocalHost, RemoteHost}) nodeTypeChoices.Spacing = 1 + nodeTypeChoices.ShowMorePlaceHold = false nodeForm := &NodeView{ model: model,