Fixed inconsistent selection styles in List, bugfixes in printWithStyle, removed reliance on ColorDefault. Fixes #954, resolves #960

pull/966/head
Oliver 2 months ago
parent fec4f00cf0
commit 03bdc867be

@ -91,9 +91,8 @@ type DropDown struct {
func NewDropDown() *DropDown { func NewDropDown() *DropDown {
list := NewList() list := NewList()
list.ShowSecondaryText(false). list.ShowSecondaryText(false).
SetMainTextColor(Styles.PrimitiveBackgroundColor). SetMainTextStyle(tcell.StyleDefault.Background(Styles.MoreContrastBackgroundColor).Foreground(Styles.PrimitiveBackgroundColor)).
SetSelectedTextColor(Styles.PrimitiveBackgroundColor). SetSelectedStyle(tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.PrimitiveBackgroundColor)).
SetSelectedBackgroundColor(Styles.PrimaryTextColor).
SetHighlightFullLine(true). SetHighlightFullLine(true).
SetBackgroundColor(Styles.MoreContrastBackgroundColor) SetBackgroundColor(Styles.MoreContrastBackgroundColor)

@ -138,7 +138,7 @@ func NewInputField() *InputField {
}) })
i.textArea.textStyle = tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor) i.textArea.textStyle = tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor)
i.textArea.placeholderStyle = tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.ContrastSecondaryTextColor) 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.selected = tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.PrimitiveBackgroundColor)
i.autocompleteStyles.background = Styles.MoreContrastBackgroundColor i.autocompleteStyles.background = Styles.MoreContrastBackgroundColor
return i return i
@ -242,8 +242,8 @@ func (i *InputField) GetPlaceholderStyle() tcell.Style {
} }
// SetAutocompleteStyles sets the colors and style of the autocomplete entries. // SetAutocompleteStyles sets the colors and style of the autocomplete entries.
// For details, see List.SetMainTextStyle(), List.SetSelectedStyle(), and // For details, see [List.SetMainTextStyle], [List.SetSelectedStyle], and
// Box.SetBackgroundColor(). // [Box.SetBackgroundColor].
func (i *InputField) SetAutocompleteStyles(background tcell.Color, main, selected tcell.Style) *InputField { func (i *InputField) SetAutocompleteStyles(background tcell.Color, main, selected tcell.Style) *InputField {
i.autocompleteStyles.background = background i.autocompleteStyles.background = background
i.autocompleteStyles.main = main i.autocompleteStyles.main = main

@ -76,11 +76,6 @@ type List struct {
// are not affected. // are not affected.
horizontalOffset int 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 // An optional function which is called when the user has navigated to a
// list item. // list item.
changed func(index int, mainText, secondaryText string, shortcut rune) changed func(index int, mainText, secondaryText string, shortcut rune)
@ -99,9 +94,9 @@ func NewList() *List {
Box: NewBox(), Box: NewBox(),
showSecondaryText: true, showSecondaryText: true,
wrapAround: true, wrapAround: true,
mainTextStyle: tcell.StyleDefault.Foreground(Styles.PrimaryTextColor), mainTextStyle: tcell.StyleDefault.Foreground(Styles.PrimaryTextColor).Background(Styles.PrimitiveBackgroundColor),
secondaryTextStyle: tcell.StyleDefault.Foreground(Styles.TertiaryTextColor), secondaryTextStyle: tcell.StyleDefault.Foreground(Styles.TertiaryTextColor).Background(Styles.PrimitiveBackgroundColor),
shortcutStyle: tcell.StyleDefault.Foreground(Styles.SecondaryTextColor), shortcutStyle: tcell.StyleDefault.Foreground(Styles.SecondaryTextColor).Background(Styles.PrimitiveBackgroundColor),
selectedStyle: tcell.StyleDefault.Foreground(Styles.PrimitiveBackgroundColor).Background(Styles.PrimaryTextColor), selectedStyle: tcell.StyleDefault.Foreground(Styles.PrimitiveBackgroundColor).Background(Styles.PrimaryTextColor),
} }
} }
@ -495,10 +490,7 @@ func (l *List) Draw(screen tcell.Screen) {
} }
// Draw the list items. // Draw the list items.
var ( var maxWidth int // The maximum printed item width.
maxWidth int // The maximum printed item width.
overflowing bool // Whether a text's end exceeds the right border.
)
for index, item := range l.items { for index, item := range l.items {
if index < l.itemOffset { if index < l.itemOffset {
continue continue
@ -510,54 +502,38 @@ func (l *List) Draw(screen tcell.Screen) {
// Shortcuts. // Shortcuts.
if showShortcuts && item.Shortcut != 0 { 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. // 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 { if printedWidth > maxWidth {
maxWidth = printedWidth 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() // Draw until the end of the line if requested.
for bx := 0; bx < textWidth; bx++ { if selected && l.highlightFullLine {
m, c, style, _ := screen.GetContent(x+bx, y) for bx := printedWidth; bx < width; bx++ {
fg, _, _ := style.Decompose() screen.SetContent(x+bx, y, ' ', nil, style)
style = l.selectedStyle
if fg != mainTextColor {
style = style.Foreground(fg)
}
screen.SetContent(x+bx, y, m, c, style)
} }
} }
y++ y++
if y >= bottomLimit { if y >= bottomLimit {
break break
} }
// Secondary text. // Secondary text.
if l.showSecondaryText { 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 { if printedWidth > maxWidth {
maxWidth = printedWidth maxWidth = printedWidth
} }
if end < len(item.SecondaryText) {
overflowing = true
}
y++ y++
} }
} }
@ -569,7 +545,6 @@ func (l *List) Draw(screen tcell.Screen) {
l.horizontalOffset -= width - maxWidth l.horizontalOffset -= width - maxWidth
l.Draw(screen) l.Draw(screen)
} }
l.overflowing = overflowing
} }
// adjustOffset adjusts the vertical offset to keep the current selection in // 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: case tcell.KeyBacktab, tcell.KeyUp:
l.currentItem-- l.currentItem--
case tcell.KeyRight: case tcell.KeyRight:
if l.overflowing { l.horizontalOffset += 2 // We shift by 2 to account for two-cell characters.
l.horizontalOffset += 2 // We shift by 2 to account for two-cell characters.
} else {
l.currentItem++
}
case tcell.KeyLeft: case tcell.KeyLeft:
if l.horizontalOffset > 0 { l.horizontalOffset -= 2
l.horizontalOffset -= 2
} else {
l.currentItem--
}
case tcell.KeyHome: case tcell.KeyHome:
l.currentItem = 0 l.currentItem = 0
case tcell.KeyEnd: case tcell.KeyEnd:
@ -762,6 +729,12 @@ func (l *List) MouseHandler() func(action MouseAction, event *tcell.EventMouse,
l.itemOffset++ l.itemOffset++
} }
consumed = true consumed = true
case MouseScrollLeft:
l.horizontalOffset--
consumed = true
case MouseScrollRight:
l.horizontalOffset++
consumed = true
} }
return return

@ -92,7 +92,7 @@ func (s *stepState) Style() tcell.Style {
// are the first grapheme cluster, the remaining string, and the new state. Pass // 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 // 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 // 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 // The returned cluster may be empty if the given string consists of only
// (parsed) tags. The boundary and width information will be meaningless in // (parsed) tags. The boundary and width information will be meaningless in

@ -66,19 +66,18 @@ func printWithStyle(screen tcell.Screen, text string, x, y, skipWidth, maxWidth,
} }
// Skip beginning and measure width. // Skip beginning and measure width.
var ( var textWidth int
state *stepState state := &stepState{
textWidth int unisegState: -1,
) style: style,
}
str := text str := text
for len(str) > 0 { for len(str) > 0 {
_, str, state = step(str, state, stepOptionsStyle) _, str, state = step(str, state, stepOptionsStyle)
if skipWidth > 0 { if skipWidth > 0 {
skipWidth -= state.Width() skipWidth -= state.Width()
if skipWidth <= 0 { text = str
text = str style = state.Style()
style = state.Style()
}
start += state.GrossLength() start += state.GrossLength()
} else { } else {
textWidth += state.Width() textWidth += state.Width()

Loading…
Cancel
Save