package gui import ( "fmt" "gitea.tyrel.dev/tyrel/itor/models" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "io" ) var ( titleStyle = lipgloss.NewStyle().MarginLeft(2) itemStyle = lipgloss.NewStyle().PaddingLeft(4) selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170")) paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 2, 4) ) type itemDelegate struct{} func (d itemDelegate) Height() int { return 1 } func (d itemDelegate) Spacing() int { return 0 } func (d itemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil } func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { i, ok := listItem.(models.Card) if !ok { return } checked := " " // not selected if i.Selected { checked = "✓" // selected! } str := fmt.Sprintf("[%s] %d. %s", checked, index+1, i.ToString()) fn := itemStyle.Render if index == m.Index() { fn = func(s string) string { return selectedItemStyle.Render("> " + s) } } fmt.Fprint(w, fn(str)) } func (m *model) updateSelect(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.selectList.SetWidth(msg.Width) return m, nil // Is it a key press? case tea.KeyMsg: switch msg.String() { case "ctrl+c", "q": return m, tea.Quit // The "up" and "k" keys move the selectCardIndex up case "up", "k": if m.selectCardIndex > 0 { m.selectCardIndex-- } // The "down" and "j" keys move the selectCardIndex down case "down", "j": if m.selectCardIndex < len(m.deck)-1 { m.selectCardIndex++ } // MODES case "d": m.switchMode(Draw) case "c": m.switchMode(Create) // The "enter" key and the spacebar (a literal space) toggle // the selected state for the item that the selectCardIndex is pointing at. case "enter", " ": card, ok := m.selectList.SelectedItem().(models.Card) if ok { idx := SliceIndex(len(m.deck), func(i int) bool { return m.deck[i].Id == card.Id }) fmt.Printf("%d IS THE CARD: %s", idx, card.Front) if _, ok := m.selected[idx]; ok { delete(m.selected, idx) m.deck[idx].Selected = false } else { m.selected[idx] = struct{}{} m.deck[idx].Selected = true } m.selectList.SetItem(idx, m.deck[idx]) } } } var cmd tea.Cmd m.selectList, cmd = m.selectList.Update(msg) return m, cmd } func (m *model) viewSelect() string { s := "Select cards to draw:\n\n" //// Iterate over our choices //for i, choice := range m.deck { // // // Is the selectCardIndex pointing at this choice? // cursor := " " // no selectCardIndex // if m.selectCardIndex == i { // cursor = ">" // selectCardIndex! // } // // // Is this choice selected? // checked := " " // not selected // if _, ok := m.selected[i]; ok { // checked = "✓" // selected! // } // // // Render the row // s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice.Front) //} s += m.selectList.View() // The footer s += "\nPress [↑/k] move up.\nPress [↓/j] move down.\nPress [enter/space] to toggle selection.\n" s += "\nPress [c] to Create.\nPress [d] to Draw.\nPress [q] to quit.\n" // Send the UI for rendering return s } func SliceIndex(limit int, predicate func(i int) bool) int { for i := 0; i < limit; i++ { if predicate(i) { return i } } return -1 }