1
0
mirror of https://github.com/rivo/tview.git synced 2025-04-24 13:48:56 +08:00

Using tcell.Style for buttons, allowing us to control it better. Resolves #704

This commit is contained in:
Oliver 2022-12-17 19:20:43 +01:00
parent 5bc948d2ca
commit ccce554c38
4 changed files with 93 additions and 59 deletions

6
box.go
View File

@ -263,6 +263,12 @@ func (b *Box) SetBorder(show bool) *Box {
return b
}
// SetBorderStyle sets the box's border style.
func (b *Box) SetBorderStyle(style tcell.Style) *Box {
b.borderStyle = style
return b
}
// SetBorderColor sets the box's border color.
func (b *Box) SetBorderColor(color tcell.Color) *Box {
b.borderStyle = b.borderStyle.Foreground(color)

View File

@ -10,17 +10,14 @@ import (
type Button struct {
*Box
// The text to be displayed before the input area.
label string
// The text to be displayed inside the button.
text string
// The label color.
labelColor tcell.Color
// The button's style (when deactivated).
style tcell.Style
// The label color when the button is in focus.
labelColorActivated tcell.Color
// The background color when the button is in focus.
backgroundColorActivated tcell.Color
// The button's style (when activated).
activatedStyle tcell.Style
// An optional function which is called when the button was selected.
selected func()
@ -33,45 +30,56 @@ type Button struct {
// NewButton returns a new input field.
func NewButton(label string) *Button {
box := NewBox().SetBackgroundColor(Styles.ContrastBackgroundColor)
box := NewBox()
box.SetRect(0, 0, TaggedStringWidth(label)+4, 1)
return &Button{
Box: box,
label: label,
labelColor: Styles.PrimaryTextColor,
labelColorActivated: Styles.InverseTextColor,
backgroundColorActivated: Styles.PrimaryTextColor,
text: label,
style: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor),
activatedStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.InverseTextColor),
}
}
// SetLabel sets the button text.
func (b *Button) SetLabel(label string) *Button {
b.label = label
b.text = label
return b
}
// GetLabel returns the button text.
func (b *Button) GetLabel() string {
return b.label
return b.text
}
// SetLabelColor sets the color of the button text.
func (b *Button) SetLabelColor(color tcell.Color) *Button {
b.labelColor = color
b.style = b.style.Foreground(color)
return b
}
// SetStyle sets the style of the button used when it is not focused.
func (b *Button) SetStyle(style tcell.Style) *Button {
b.style = style
return b
}
// SetLabelColorActivated sets the color of the button text when the button is
// in focus.
func (b *Button) SetLabelColorActivated(color tcell.Color) *Button {
b.labelColorActivated = color
b.activatedStyle = b.activatedStyle.Foreground(color)
return b
}
// SetBackgroundColorActivated sets the background color of the button text when
// the button is in focus.
func (b *Button) SetBackgroundColorActivated(color tcell.Color) *Button {
b.backgroundColorActivated = color
b.activatedStyle = b.activatedStyle.Background(color)
return b
}
// SetActivatedStyle sets the style of the button used when it is focused.
func (b *Button) SetActivatedStyle(style tcell.Style) *Button {
b.activatedStyle = style
return b
}
@ -96,27 +104,27 @@ func (b *Button) SetExitFunc(handler func(key tcell.Key)) *Button {
// Draw draws this primitive onto the screen.
func (b *Button) Draw(screen tcell.Screen) {
// Draw the box.
borderColor := b.GetBorderColor()
backgroundColor := b.GetBackgroundColor()
style := b.style
_, backgroundColor, _ := style.Decompose()
if b.HasFocus() {
b.SetBackgroundColor(b.backgroundColorActivated)
b.SetBorderColor(b.labelColorActivated)
style = b.activatedStyle
_, backgroundColor, _ = style.Decompose()
// Highlight button for one drawing cycle.
borderColor := b.GetBorderColor()
b.SetBorderColor(backgroundColor)
defer func() {
b.SetBorderColor(borderColor)
}()
}
b.SetBackgroundColor(backgroundColor)
b.Box.DrawForSubclass(screen, b)
b.backgroundColor = backgroundColor
// Draw label.
x, y, width, height := b.GetInnerRect()
if width > 0 && height > 0 {
y = y + height/2
labelColor := b.labelColor
if b.HasFocus() {
labelColor = b.labelColorActivated
}
Print(screen, b.label, x, y, width, AlignCenter, labelColor)
printWithStyle(screen, b.text, x, y, 0, width, AlignCenter, style, true)
}
}

64
form.go
View File

@ -84,11 +84,11 @@ type Form struct {
// The text color of the input area.
fieldTextColor tcell.Color
// The background color of the buttons.
buttonBackgroundColor tcell.Color
// The style of the buttons when they are not focused.
buttonStyle tcell.Style
// The color of the button text.
buttonTextColor tcell.Color
// The style of the buttons when they are focused.
buttonActivatedStyle tcell.Style
// The last (valid) key that wsa sent to a "finished" handler or -1 if no
// such key is known yet.
@ -108,8 +108,8 @@ func NewForm() *Form {
labelColor: Styles.SecondaryTextColor,
fieldBackgroundColor: Styles.ContrastBackgroundColor,
fieldTextColor: Styles.PrimaryTextColor,
buttonBackgroundColor: Styles.ContrastBackgroundColor,
buttonTextColor: Styles.PrimaryTextColor,
buttonStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor),
buttonActivatedStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.ContrastBackgroundColor),
lastFinishedKey: -1,
}
@ -158,15 +158,31 @@ func (f *Form) SetButtonsAlign(align int) *Form {
return f
}
// SetButtonBackgroundColor sets the background color of the buttons.
// SetButtonBackgroundColor sets the background color of the buttons. This is
// also the text color of the buttons when they are focused.
func (f *Form) SetButtonBackgroundColor(color tcell.Color) *Form {
f.buttonBackgroundColor = color
f.buttonStyle = f.buttonStyle.Background(color)
f.buttonActivatedStyle = f.buttonActivatedStyle.Foreground(color)
return f
}
// SetButtonTextColor sets the color of the button texts.
// SetButtonTextColor sets the color of the button texts. This is also the
// background of the buttons when they are focused.
func (f *Form) SetButtonTextColor(color tcell.Color) *Form {
f.buttonTextColor = color
f.buttonStyle = f.buttonStyle.Foreground(color)
f.buttonActivatedStyle = f.buttonActivatedStyle.Background(color)
return f
}
// SetButtonStyle sets the style of the buttons when they are not focused.
func (f *Form) SetButtonStyle(style tcell.Style) *Form {
f.buttonStyle = style
return f
}
// SetButtonActivatedStyle sets the style of the buttons when they are focused.
func (f *Form) SetButtonActivatedStyle(style tcell.Style) *Form {
f.buttonActivatedStyle = style
return f
}
@ -564,10 +580,8 @@ func (f *Form) Draw(screen tcell.Screen) {
if buttonWidth > space {
buttonWidth = space
}
button.SetLabelColor(f.buttonTextColor).
SetLabelColorActivated(f.buttonBackgroundColor).
SetBackgroundColorActivated(f.buttonTextColor).
SetBackgroundColor(f.buttonBackgroundColor)
button.SetStyle(f.buttonStyle).
SetActivatedStyle(f.buttonActivatedStyle)
buttonIndex := index + len(f.items)
positions[buttonIndex].x = x
@ -671,16 +685,22 @@ func (f *Form) Focus(delegate func(p Primitive)) {
}
}
if f.focusedElement < len(f.items) {
// We're selecting an item.
item := f.items[f.focusedElement]
// Set the handler for all items and buttons.
for index, item := range f.items {
item.SetFinishedFunc(handler)
delegate(item)
} else {
// We're selecting a button.
button := f.buttons[f.focusedElement-len(f.items)]
if f.focusedElement == index {
func(i FormItem) { // Wrapping might not be necessary anymore in future Go versions.
defer delegate(i)
}(item)
}
}
for index, button := range f.buttons {
button.SetExitFunc(handler)
delegate(button)
if f.focusedElement == index+len(f.items) {
func(b *Button) { // Wrapping might not be necessary anymore in future Go versions.
defer delegate(b)
}(button)
}
}
}

View File

@ -148,7 +148,7 @@ func (m *Modal) Draw(screen tcell.Screen) {
// Calculate the width of this modal.
buttonsWidth := 0
for _, button := range m.form.buttons {
buttonsWidth += TaggedStringWidth(button.label) + 4 + 2
buttonsWidth += TaggedStringWidth(button.text) + 4 + 2
}
buttonsWidth -= 2
screenWidth, screenHeight := screen.Size()