forked from tslocum/cview
Store ListItem text as []byte instead of string
This commit is contained in:
parent
96b2dd5523
commit
d5edb975b6
7 changed files with 65 additions and 40 deletions
|
@ -154,7 +154,7 @@ func (c *ContextMenu) show(item int, x int, y int, setFocus func(Primitive)) {
|
|||
|
||||
if c.selected != nil {
|
||||
c.l.Unlock()
|
||||
c.selected(index, item.mainText, item.shortcut)
|
||||
c.selected(index, string(item.mainText), item.shortcut)
|
||||
} else {
|
||||
c.l.Unlock()
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"gitlab.com/tslocum/cview"
|
||||
|
@ -251,8 +251,8 @@ const tableSelectCell = `[green]func[white] [yellow]main[white]() {
|
|||
func Table(nextSlide func()) (title string, content cview.Primitive) {
|
||||
table := cview.NewTable().
|
||||
SetFixed(1, 1)
|
||||
for row, line := range bytes.Split([]byte(tableData), []byte("\n")) {
|
||||
for column, cell := range bytes.Split(line, []byte("|")) {
|
||||
for row, line := range strings.Split(tableData, "\n") {
|
||||
for column, cell := range strings.Split(line, "|") {
|
||||
color := tcell.ColorWhite.TrueColor()
|
||||
if row == 0 {
|
||||
color = tcell.ColorYellow.TrueColor()
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"gitlab.com/tslocum/cview"
|
||||
|
@ -14,7 +14,7 @@ func main() {
|
|||
app := cview.NewApplication()
|
||||
table := cview.NewTable().
|
||||
SetBorders(true)
|
||||
lorem := bytes.Split([]byte(loremIpsumText), []byte(" "))
|
||||
lorem := strings.Split(loremIpsumText, " ")
|
||||
cols, rows := 10, 40
|
||||
word := 0
|
||||
for r := 0; r < rows; r++ {
|
||||
|
|
|
@ -488,7 +488,7 @@ func (i *InputField) Autocomplete() *InputField {
|
|||
for index, entry := range entries {
|
||||
entry.enabled = true
|
||||
i.autocompleteList.AddItem(entry)
|
||||
if currentEntry < 0 && entry.mainText == i.text {
|
||||
if currentEntry < 0 && entry.GetMainText() == i.text {
|
||||
currentEntry = index
|
||||
}
|
||||
}
|
||||
|
@ -505,10 +505,12 @@ func (i *InputField) Autocomplete() *InputField {
|
|||
// autocompleteChanged gets called when another item in the
|
||||
// autocomplete list has been selected.
|
||||
func (i *InputField) autocompleteChanged(_ int, item *ListItem) {
|
||||
if len(item.secondaryText) > 0 && len(i.text) < len(item.secondaryText) {
|
||||
i.autocompleteListSuggestion = item.secondaryText[len(i.text):]
|
||||
} else if len(item.mainText) > len(i.text)+1 {
|
||||
i.autocompleteListSuggestion = item.mainText[len(i.text)+1:]
|
||||
mainText := item.GetMainText()
|
||||
secondaryText := item.GetSecondaryText()
|
||||
if len(secondaryText) > 0 && len(i.text) < len(secondaryText) {
|
||||
i.autocompleteListSuggestion = secondaryText[len(i.text):]
|
||||
} else if len(mainText) > len(i.text)+1 {
|
||||
i.autocompleteListSuggestion = mainText[len(i.text)+1:]
|
||||
} else {
|
||||
i.autocompleteListSuggestion = ""
|
||||
}
|
||||
|
@ -879,9 +881,9 @@ func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
|||
case tcell.KeyEnter: // We might be done.
|
||||
if i.autocompleteList != nil {
|
||||
currentItem := i.autocompleteList.GetCurrentItem()
|
||||
selectionText := currentItem.mainText
|
||||
if currentItem.secondaryText != "" {
|
||||
selectionText = currentItem.secondaryText
|
||||
selectionText := currentItem.GetMainText()
|
||||
if currentItem.GetSecondaryText() != "" {
|
||||
selectionText = currentItem.GetSecondaryText()
|
||||
}
|
||||
i.Unlock()
|
||||
i.SetText(selectionText)
|
||||
|
|
67
list.go
67
list.go
|
@ -12,8 +12,8 @@ import (
|
|||
// ListItem represents an item in a List.
|
||||
type ListItem struct {
|
||||
enabled bool // Whether or not the list item is selectable.
|
||||
mainText string // The main text of the list item.
|
||||
secondaryText string // A secondary text to be shown underneath the main text.
|
||||
mainText []byte // The main text of the list item.
|
||||
secondaryText []byte // A secondary text to be shown underneath the main text.
|
||||
shortcut rune // The key to select the list item directly, 0 if there is no shortcut.
|
||||
selected func() // The optional function which is called when the item is selected.
|
||||
reference interface{} // An optional reference object.
|
||||
|
@ -24,13 +24,13 @@ type ListItem struct {
|
|||
// NewListItem returns a new item for a list.
|
||||
func NewListItem(mainText string) *ListItem {
|
||||
return &ListItem{
|
||||
mainText: mainText,
|
||||
mainText: []byte(mainText),
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
// SetMainText sets the main text of the list item.
|
||||
func (l *ListItem) SetMainText(val string) *ListItem {
|
||||
// SetMainBytes sets the main text of the list item.
|
||||
func (l *ListItem) SetMainBytes(val []byte) *ListItem {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
|
@ -38,16 +38,26 @@ func (l *ListItem) SetMainText(val string) *ListItem {
|
|||
return l
|
||||
}
|
||||
|
||||
// GetMainText returns the item's main text.
|
||||
func (l *ListItem) GetMainText() string {
|
||||
// SetMainText sets the main text of the list item.
|
||||
func (l *ListItem) SetMainText(val string) *ListItem {
|
||||
return l.SetMainBytes([]byte(val))
|
||||
}
|
||||
|
||||
// GetMainBytes returns the item's main text.
|
||||
func (l *ListItem) GetMainBytes() []byte {
|
||||
l.RLock()
|
||||
defer l.RUnlock()
|
||||
|
||||
return l.mainText
|
||||
}
|
||||
|
||||
// SetSecondaryText sets a secondary text to be shown underneath the main text.
|
||||
func (l *ListItem) SetSecondaryText(val string) *ListItem {
|
||||
// GetMainText returns the item's main text.
|
||||
func (l *ListItem) GetMainText() string {
|
||||
return string(l.GetMainBytes())
|
||||
}
|
||||
|
||||
// SetSecondaryBytes sets a secondary text to be shown underneath the main text.
|
||||
func (l *ListItem) SetSecondaryBytes(val []byte) *ListItem {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
|
@ -55,14 +65,24 @@ func (l *ListItem) SetSecondaryText(val string) *ListItem {
|
|||
return l
|
||||
}
|
||||
|
||||
// GetSecondaryText returns the item's secondary text.
|
||||
func (l *ListItem) GetSecondaryText() string {
|
||||
// SetSecondaryText sets a secondary text to be shown underneath the main text.
|
||||
func (l *ListItem) SetSecondaryText(val string) *ListItem {
|
||||
return l.SetSecondaryBytes([]byte(val))
|
||||
}
|
||||
|
||||
// GetSecondaryBytes returns the item's secondary text.
|
||||
func (l *ListItem) GetSecondaryBytes() []byte {
|
||||
l.RLock()
|
||||
defer l.RUnlock()
|
||||
|
||||
return l.secondaryText
|
||||
}
|
||||
|
||||
// GetSecondaryText returns the item's secondary text.
|
||||
func (l *ListItem) GetSecondaryText() string {
|
||||
return string(l.GetSecondaryBytes())
|
||||
}
|
||||
|
||||
// SetShortcut sets the key to select the ListItem directly, 0 if there is no shortcut.
|
||||
func (l *ListItem) SetShortcut(val rune) *ListItem {
|
||||
l.Lock()
|
||||
|
@ -612,7 +632,7 @@ func (l *List) GetItemCount() int {
|
|||
func (l *List) GetItemText(index int) (main, secondary string) {
|
||||
l.RLock()
|
||||
defer l.RUnlock()
|
||||
return l.items[index].mainText, l.items[index].secondaryText
|
||||
return string(l.items[index].mainText), string(l.items[index].secondaryText)
|
||||
}
|
||||
|
||||
// SetItemText sets an item's main and secondary text. Panics if the index is
|
||||
|
@ -622,8 +642,8 @@ func (l *List) SetItemText(index int, main, secondary string) *List {
|
|||
defer l.Unlock()
|
||||
|
||||
item := l.items[index]
|
||||
item.mainText = main
|
||||
item.secondaryText = secondary
|
||||
item.mainText = []byte(main)
|
||||
item.secondaryText = []byte(secondary)
|
||||
return l
|
||||
}
|
||||
|
||||
|
@ -661,19 +681,22 @@ func (l *List) FindItems(mainSearch, secondarySearch string, mustContainBoth, ig
|
|||
secondarySearch = strings.ToLower(secondarySearch)
|
||||
}
|
||||
|
||||
mainSearchBytes := []byte(mainSearch)
|
||||
secondarySearchBytes := []byte(secondarySearch)
|
||||
|
||||
for index, item := range l.items {
|
||||
mainText := item.mainText
|
||||
secondaryText := item.secondaryText
|
||||
if ignoreCase {
|
||||
mainText = strings.ToLower(mainText)
|
||||
secondaryText = strings.ToLower(secondaryText)
|
||||
mainText = bytes.ToLower(mainText)
|
||||
secondaryText = bytes.ToLower(secondaryText)
|
||||
}
|
||||
|
||||
// strings.Contains() always returns true for a "" search.
|
||||
mainContained := strings.Contains(mainText, mainSearch)
|
||||
secondaryContained := strings.Contains(secondaryText, secondarySearch)
|
||||
mainContained := bytes.Contains(mainText, mainSearchBytes)
|
||||
secondaryContained := bytes.Contains(secondaryText, secondarySearchBytes)
|
||||
if mustContainBoth && mainContained && secondaryContained ||
|
||||
!mustContainBoth && (mainText != "" && mainContained || secondaryText != "" && secondaryContained) {
|
||||
!mustContainBoth && (len(mainText) > 0 && mainContained || len(secondaryText) > 0 && secondaryContained) {
|
||||
indices = append(indices, index)
|
||||
}
|
||||
}
|
||||
|
@ -871,7 +894,7 @@ func (l *List) Draw(screen tcell.Screen) {
|
|||
break
|
||||
}
|
||||
|
||||
if item.mainText == "" && item.secondaryText == "" && item.shortcut == 0 { // Divider
|
||||
if len(item.mainText) == 0 && len(item.secondaryText) == 0 && item.shortcut == 0 { // Divider
|
||||
Print(screen, []byte(string(tcell.RuneLTee)), (x-5)-l.paddingLeft, y, 1, AlignLeft, l.mainTextColor)
|
||||
Print(screen, bytes.Repeat([]byte(string(tcell.RuneHLine)), width+4+l.paddingLeft+l.paddingRight), (x-4)-l.paddingLeft, y, width+4+l.paddingLeft+l.paddingRight, AlignLeft, l.mainTextColor)
|
||||
Print(screen, []byte(string(tcell.RuneRTee)), (x-5)+width+5+l.paddingRight, y, 1, AlignLeft, l.mainTextColor)
|
||||
|
@ -905,7 +928,7 @@ func (l *List) Draw(screen tcell.Screen) {
|
|||
if index == l.currentItem && (!l.selectedFocusOnly || hasFocus) {
|
||||
textWidth := width
|
||||
if !l.highlightFullLine {
|
||||
if w := TaggedStringWidth(item.mainText); w < textWidth {
|
||||
if w := TaggedTextWidth(item.mainText); w < textWidth {
|
||||
textWidth = w
|
||||
}
|
||||
}
|
||||
|
@ -955,7 +978,7 @@ func (l *List) Draw(screen tcell.Screen) {
|
|||
// What's the longest option text?
|
||||
maxWidth := 0
|
||||
for _, option := range ctx.items {
|
||||
strWidth := TaggedStringWidth(option.mainText)
|
||||
strWidth := TaggedTextWidth(option.mainText)
|
||||
if option.shortcut != 0 {
|
||||
strWidth += 4
|
||||
}
|
||||
|
|
6
table.go
6
table.go
|
@ -53,9 +53,9 @@ type TableCell struct {
|
|||
// NewTableCell returns a new table cell with sensible defaults. That is, left
|
||||
// aligned text with the primary text color (see Styles) and a transparent
|
||||
// background (using the background of the Table).
|
||||
func NewTableCell(text []byte) *TableCell {
|
||||
func NewTableCell(text string) *TableCell {
|
||||
return &TableCell{
|
||||
Text: text,
|
||||
Text: []byte(text),
|
||||
Align: AlignLeft,
|
||||
Color: Styles.PrimaryTextColor,
|
||||
BackgroundColor: tcell.ColorDefault,
|
||||
|
@ -610,7 +610,7 @@ func (t *Table) SetCell(row, column int, cell *TableCell) *Table {
|
|||
}
|
||||
|
||||
// SetCellSimple calls SetCell() with the given text, left-aligned, in white.
|
||||
func (t *Table) SetCellSimple(row, column int, text []byte) *Table {
|
||||
func (t *Table) SetCellSimple(row, column int, text string) *Table {
|
||||
return t.SetCell(row, column, NewTableCell(text))
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ func tc(c *tableTestCase) *Table {
|
|||
|
||||
for row := 0; row < c.rows; row++ {
|
||||
for column := 0; column < c.columns; column++ {
|
||||
table.SetCellSimple(row, column, []byte(fmt.Sprintf("%d,%d", column, row)))
|
||||
table.SetCellSimple(row, column, fmt.Sprintf("%d,%d", column, row))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue