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

This commit is contained in:
Oliver 2024-04-03 15:46:31 +02:00
parent fec4f00cf0
commit 03bdc867be
5 changed files with 37 additions and 66 deletions

View File

@ -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)

View File

@ -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

71
list.go
View File

@ -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++
}
case tcell.KeyLeft:
if l.horizontalOffset > 0 {
l.horizontalOffset -= 2
} else {
l.currentItem--
}
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

View File

@ -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

11
util.go
View File

@ -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()
}
start += state.GrossLength()
} else {
textWidth += state.Width()