From 03bdc867bee4ce7355079090c396d9ec861fc4bb Mon Sep 17 00:00:00 2001 From: Oliver <480930+rivo@users.noreply.github.com> Date: Wed, 3 Apr 2024 15:46:31 +0200 Subject: [PATCH] Fixed inconsistent selection styles in List, bugfixes in printWithStyle, removed reliance on ColorDefault. Fixes #954, resolves #960 --- dropdown.go | 5 ++-- inputfield.go | 6 ++--- list.go | 75 +++++++++++++++++---------------------------------- strings.go | 2 +- util.go | 15 +++++------ 5 files changed, 37 insertions(+), 66 deletions(-) diff --git a/dropdown.go b/dropdown.go index a67761d..11400ed 100644 --- a/dropdown.go +++ b/dropdown.go @@ -91,9 +91,8 @@ type DropDown struct { func NewDropDown() *DropDown { list := NewList() list.ShowSecondaryText(false). - SetMainTextColor(Styles.PrimitiveBackgroundColor). - SetSelectedTextColor(Styles.PrimitiveBackgroundColor). - SetSelectedBackgroundColor(Styles.PrimaryTextColor). + SetMainTextStyle(tcell.StyleDefault.Background(Styles.MoreContrastBackgroundColor).Foreground(Styles.PrimitiveBackgroundColor)). + SetSelectedStyle(tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.PrimitiveBackgroundColor)). SetHighlightFullLine(true). SetBackgroundColor(Styles.MoreContrastBackgroundColor) diff --git a/inputfield.go b/inputfield.go index 6a6ec1e..27b74bc 100644 --- a/inputfield.go +++ b/inputfield.go @@ -138,7 +138,7 @@ func NewInputField() *InputField { }) i.textArea.textStyle = tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor) i.textArea.placeholderStyle = tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.ContrastSecondaryTextColor) - i.autocompleteStyles.main = tcell.StyleDefault.Foreground(Styles.PrimitiveBackgroundColor) + i.autocompleteStyles.main = tcell.StyleDefault.Background(Styles.MoreContrastBackgroundColor).Foreground(Styles.PrimitiveBackgroundColor) i.autocompleteStyles.selected = tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.PrimitiveBackgroundColor) i.autocompleteStyles.background = Styles.MoreContrastBackgroundColor return i @@ -242,8 +242,8 @@ func (i *InputField) GetPlaceholderStyle() tcell.Style { } // SetAutocompleteStyles sets the colors and style of the autocomplete entries. -// For details, see List.SetMainTextStyle(), List.SetSelectedStyle(), and -// Box.SetBackgroundColor(). +// For details, see [List.SetMainTextStyle], [List.SetSelectedStyle], and +// [Box.SetBackgroundColor]. func (i *InputField) SetAutocompleteStyles(background tcell.Color, main, selected tcell.Style) *InputField { i.autocompleteStyles.background = background i.autocompleteStyles.main = main diff --git a/list.go b/list.go index 8e59fe9..2271926 100644 --- a/list.go +++ b/list.go @@ -76,11 +76,6 @@ type List struct { // are not affected. horizontalOffset int - // Set to true if a currently visible item flows over the right border of - // the box. This is set by the Draw() function. It determines the behaviour - // of the right arrow key. - overflowing bool - // An optional function which is called when the user has navigated to a // list item. changed func(index int, mainText, secondaryText string, shortcut rune) @@ -99,9 +94,9 @@ func NewList() *List { Box: NewBox(), showSecondaryText: true, wrapAround: true, - mainTextStyle: tcell.StyleDefault.Foreground(Styles.PrimaryTextColor), - secondaryTextStyle: tcell.StyleDefault.Foreground(Styles.TertiaryTextColor), - shortcutStyle: tcell.StyleDefault.Foreground(Styles.SecondaryTextColor), + mainTextStyle: tcell.StyleDefault.Foreground(Styles.PrimaryTextColor).Background(Styles.PrimitiveBackgroundColor), + secondaryTextStyle: tcell.StyleDefault.Foreground(Styles.TertiaryTextColor).Background(Styles.PrimitiveBackgroundColor), + shortcutStyle: tcell.StyleDefault.Foreground(Styles.SecondaryTextColor).Background(Styles.PrimitiveBackgroundColor), selectedStyle: tcell.StyleDefault.Foreground(Styles.PrimitiveBackgroundColor).Background(Styles.PrimaryTextColor), } } @@ -495,10 +490,7 @@ func (l *List) Draw(screen tcell.Screen) { } // Draw the list items. - var ( - maxWidth int // The maximum printed item width. - overflowing bool // Whether a text's end exceeds the right border. - ) + var maxWidth int // The maximum printed item width. for index, item := range l.items { if index < l.itemOffset { continue @@ -510,54 +502,38 @@ func (l *List) Draw(screen tcell.Screen) { // Shortcuts. if showShortcuts && item.Shortcut != 0 { - printWithStyle(screen, fmt.Sprintf("(%s)", string(item.Shortcut)), x-5, y, 0, 4, AlignRight, l.shortcutStyle, true) + printWithStyle(screen, fmt.Sprintf("(%s)", string(item.Shortcut)), x-5, y, 0, 4, AlignRight, l.shortcutStyle, false) } // Main text. - _, end, printedWidth := printWithStyle(screen, item.MainText, x, y, l.horizontalOffset, width, AlignLeft, l.mainTextStyle, true) + selected := index == l.currentItem && (!l.selectedFocusOnly || l.HasFocus()) + style := l.mainTextStyle + if selected { + style = l.selectedStyle + } + _, _, printedWidth := printWithStyle(screen, item.MainText, x, y, l.horizontalOffset, width, AlignLeft, style, false) if printedWidth > maxWidth { maxWidth = printedWidth } - if end < len(item.MainText) { - overflowing = true - } - // Background color of selected text. - if index == l.currentItem && (!l.selectedFocusOnly || l.HasFocus()) { - textWidth := width - if !l.highlightFullLine { - if w := TaggedStringWidth(item.MainText); w < textWidth { - textWidth = w - } - } - - mainTextColor, _, _ := l.mainTextStyle.Decompose() - for bx := 0; bx < textWidth; bx++ { - m, c, style, _ := screen.GetContent(x+bx, y) - fg, _, _ := style.Decompose() - style = l.selectedStyle - if fg != mainTextColor { - style = style.Foreground(fg) - } - screen.SetContent(x+bx, y, m, c, style) + // Draw until the end of the line if requested. + if selected && l.highlightFullLine { + for bx := printedWidth; bx < width; bx++ { + screen.SetContent(x+bx, y, ' ', nil, style) } } y++ - if y >= bottomLimit { break } // Secondary text. if l.showSecondaryText { - _, end, printedWidth := printWithStyle(screen, item.SecondaryText, x, y, l.horizontalOffset, width, AlignLeft, l.secondaryTextStyle, true) + _, _, printedWidth := printWithStyle(screen, item.SecondaryText, x, y, l.horizontalOffset, width, AlignLeft, l.secondaryTextStyle, false) if printedWidth > maxWidth { maxWidth = printedWidth } - if end < len(item.SecondaryText) { - overflowing = true - } y++ } } @@ -569,7 +545,6 @@ func (l *List) Draw(screen tcell.Screen) { l.horizontalOffset -= width - maxWidth l.Draw(screen) } - l.overflowing = overflowing } // adjustOffset adjusts the vertical offset to keep the current selection in @@ -612,17 +587,9 @@ func (l *List) InputHandler() func(event *tcell.EventKey, setFocus func(p Primit case tcell.KeyBacktab, tcell.KeyUp: l.currentItem-- case tcell.KeyRight: - if l.overflowing { - l.horizontalOffset += 2 // We shift by 2 to account for two-cell characters. - } else { - l.currentItem++ - } + l.horizontalOffset += 2 // We shift by 2 to account for two-cell characters. case tcell.KeyLeft: - if l.horizontalOffset > 0 { - l.horizontalOffset -= 2 - } else { - l.currentItem-- - } + l.horizontalOffset -= 2 case tcell.KeyHome: l.currentItem = 0 case tcell.KeyEnd: @@ -762,6 +729,12 @@ func (l *List) MouseHandler() func(action MouseAction, event *tcell.EventMouse, l.itemOffset++ } consumed = true + case MouseScrollLeft: + l.horizontalOffset-- + consumed = true + case MouseScrollRight: + l.horizontalOffset++ + consumed = true } return diff --git a/strings.go b/strings.go index 08cbf7b..70bce60 100644 --- a/strings.go +++ b/strings.go @@ -92,7 +92,7 @@ func (s *stepState) Style() tcell.Style { // are the first grapheme cluster, the remaining string, and the new state. Pass // the remaining string and the returned state to the next call. If the rest // string is empty, parsing is complete. Call the returned state's methods for -// boundary and width information. +// boundary and cluster width information. // // The returned cluster may be empty if the given string consists of only // (parsed) tags. The boundary and width information will be meaningless in diff --git a/util.go b/util.go index 7a9d2d7..b275c8c 100644 --- a/util.go +++ b/util.go @@ -66,19 +66,18 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth, } // Skip beginning and measure width. - var ( - state *stepState - textWidth int - ) + var textWidth int + state := &stepState{ + unisegState: -1, + style: style, + } str := text for len(str) > 0 { _, str, state = step(str, state, stepOptionsStyle) if skipWidth > 0 { skipWidth -= state.Width() - if skipWidth <= 0 { - text = str - style = state.Style() - } + text = str + style = state.Style() start += state.GrossLength() } else { textWidth += state.Width()