diff --git a/dropdown.go b/dropdown.go index 8946da2..9360146 100644 --- a/dropdown.go +++ b/dropdown.go @@ -140,6 +140,9 @@ type DropDown struct { // The symbol to draw at the end of the field when opened. dropDownOpenSymbol rune + // The symbol used to draw the selected item when opened. + dropDownSelectedSymbol rune + // A flag that determines whether the drop down symbol is always drawn. alwaysDrawDropDownSymbol bool @@ -166,12 +169,16 @@ func NewDropDown() *DropDown { prefixTextColor: Styles.ContrastSecondaryTextColor, dropDownSymbol: Styles.DropDownSymbol, dropDownOpenSymbol: Styles.DropDownOpenSymbol, + dropDownSelectedSymbol: Styles.DropDownSelectedSymbol, abbreviationChars: Styles.DropDownAbbreviationChars, labelColorFocused: ColorUnset, fieldBackgroundColorFocused: ColorUnset, fieldTextColorFocused: ColorUnset, } + if sym := d.dropDownSelectedSymbol; sym != 0 { + list.SetIndicators(" "+string(sym)+" ", "", " ", "") + } d.focus = d return d @@ -191,6 +198,21 @@ func (d *DropDown) SetDropDownOpenSymbolRune(symbol rune) { d.Lock() defer d.Unlock() d.dropDownOpenSymbol = symbol + + if symbol != 0 { + d.list.SetIndicators(" "+string(symbol)+" ", "", " ", "") + } else { + d.list.SetIndicators("", "", "", "") + } + +} + +// SetDropDownSelectedSymbolRune sets the rune to be drawn at the start of the +// selected list item. +func (d *DropDown) SetDropDownSelectedSymbolRune(symbol rune) { + d.Lock() + defer d.Unlock() + d.dropDownSelectedSymbol = symbol } // SetAlwaysDrawDropDownSymbol sets a flad that determines whether the drop @@ -415,7 +437,8 @@ func (d *DropDown) getFieldWidth() int { } fieldWidth += len(d.optionPrefix) + len(d.optionSuffix) fieldWidth += len(d.currentOptionPrefix) + len(d.currentOptionSuffix) - fieldWidth += 3 // space + dropDownSymbol + space + // space space + dropDownSymbol + space + fieldWidth += 4 return fieldWidth } diff --git a/list.go b/list.go index 5599978..2ab11da 100644 --- a/list.go +++ b/list.go @@ -194,6 +194,15 @@ type List struct { // The height of the list the last time it was drawn. height int + // Prefix and suffix strings drawn for unselected elements. + unselectedPrefix, unselectedSuffix []byte + + // Prefix and suffix strings drawn for selected elements. + selectedPrefix, selectedSuffix []byte + + // Maximum prefix and suffix width. + prefixWidth, suffixWidth int + sync.RWMutex } @@ -627,6 +636,24 @@ func (l *List) SetItemEnabled(index int, enabled bool) { item.disabled = !enabled } +// SetIndicators is used to set prefix and suffix indicators for selected and unselected items. +func (l *List) SetIndicators(selectedPrefix, selectedSuffix, unselectedPrefix, unselectedSuffix string) { + l.Lock() + defer l.Unlock() + l.selectedPrefix = []byte(selectedPrefix) + l.selectedSuffix = []byte(selectedSuffix) + l.unselectedPrefix = []byte(unselectedPrefix) + l.unselectedSuffix = []byte(unselectedSuffix) + l.prefixWidth = len(selectedPrefix) + if len(unselectedPrefix) > l.prefixWidth { + l.prefixWidth = len(unselectedPrefix) + } + l.suffixWidth = len(selectedSuffix) + if len(unselectedSuffix) > l.suffixWidth { + l.suffixWidth = len(unselectedSuffix) + } +} + // FindItems searches the main and secondary texts for the given strings and // returns a list of item indices in which those strings are found. One of the // two search strings may be empty, it will then be ignored. Indices are always @@ -866,7 +893,7 @@ func (l *List) Draw(screen tcell.Screen) { // Determine the dimensions. x, y, width, height := l.GetInnerRect() leftEdge := x - fullWidth := width + l.paddingLeft + l.paddingRight + fullWidth := width + l.paddingLeft + l.paddingRight + l.prefixWidth + l.suffixWidth bottomLimit := y + height l.height = height @@ -934,7 +961,25 @@ func (l *List) Draw(screen tcell.Screen) { RenderScrollBar(screen, l.scrollBarVisibility, scrollBarX, y, scrollBarHeight, len(l.items), scrollBarCursor, index-l.itemOffset, l.hasFocus, l.scrollBarColor) y++ continue - } else if item.disabled { + } + + if index == l.currentItem { + if len(l.selectedPrefix) > 0 { + mainText = append(l.selectedPrefix, mainText...) + } + if len(l.selectedSuffix) > 0 { + mainText = append(mainText, l.selectedSuffix...) + } + + } else { + if len(l.unselectedPrefix) > 0 { + mainText = append(l.unselectedPrefix, mainText...) + } + if len(l.unselectedSuffix) > 0 { + mainText = append(mainText, l.unselectedSuffix...) + } + } + if item.disabled { // Shortcuts. if showShortcuts && item.shortcut != 0 { Print(screen, []byte(fmt.Sprintf("(%c)", item.shortcut)), x-5, y, 4, AlignRight, tcell.ColorDarkSlateGray.TrueColor()) diff --git a/styles.go b/styles.go index 52d54bc..e03f976 100644 --- a/styles.go +++ b/styles.go @@ -39,6 +39,7 @@ type Theme struct { DropDownAbbreviationChars string // The chars to show when the option's text gets shortened. DropDownSymbol rune // The symbol to draw at the end of the field when closed. DropDownOpenSymbol rune // The symbol to draw at the end of the field when opened. + DropDownSelectedSymbol rune // The symbol to draw to indicate the selected list item. // Scroll bar ScrollBarColor tcell.Color @@ -80,6 +81,7 @@ var Styles = Theme{ DropDownAbbreviationChars: "...", DropDownSymbol: '◀', DropDownOpenSymbol: '▼', + DropDownSelectedSymbol: '▶', ScrollBarColor: tcell.ColorWhite.TrueColor(),