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 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. // SetBorderColor sets the box's border color.
func (b *Box) SetBorderColor(color tcell.Color) *Box { func (b *Box) SetBorderColor(color tcell.Color) *Box {
b.borderStyle = b.borderStyle.Foreground(color) b.borderStyle = b.borderStyle.Foreground(color)

View File

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

76
form.go
View File

@ -84,11 +84,11 @@ type Form struct {
// The text color of the input area. // The text color of the input area.
fieldTextColor tcell.Color fieldTextColor tcell.Color
// The background color of the buttons. // The style of the buttons when they are not focused.
buttonBackgroundColor tcell.Color buttonStyle tcell.Style
// The color of the button text. // The style of the buttons when they are focused.
buttonTextColor tcell.Color buttonActivatedStyle tcell.Style
// The last (valid) key that wsa sent to a "finished" handler or -1 if no // The last (valid) key that wsa sent to a "finished" handler or -1 if no
// such key is known yet. // such key is known yet.
@ -103,14 +103,14 @@ func NewForm() *Form {
box := NewBox().SetBorderPadding(1, 1, 1, 1) box := NewBox().SetBorderPadding(1, 1, 1, 1)
f := &Form{ f := &Form{
Box: box, Box: box,
itemPadding: 1, itemPadding: 1,
labelColor: Styles.SecondaryTextColor, labelColor: Styles.SecondaryTextColor,
fieldBackgroundColor: Styles.ContrastBackgroundColor, fieldBackgroundColor: Styles.ContrastBackgroundColor,
fieldTextColor: Styles.PrimaryTextColor, fieldTextColor: Styles.PrimaryTextColor,
buttonBackgroundColor: Styles.ContrastBackgroundColor, buttonStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor),
buttonTextColor: Styles.PrimaryTextColor, buttonActivatedStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.ContrastBackgroundColor),
lastFinishedKey: -1, lastFinishedKey: -1,
} }
return f return f
@ -158,15 +158,31 @@ func (f *Form) SetButtonsAlign(align int) *Form {
return f 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 { 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 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 { 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 return f
} }
@ -564,10 +580,8 @@ func (f *Form) Draw(screen tcell.Screen) {
if buttonWidth > space { if buttonWidth > space {
buttonWidth = space buttonWidth = space
} }
button.SetLabelColor(f.buttonTextColor). button.SetStyle(f.buttonStyle).
SetLabelColorActivated(f.buttonBackgroundColor). SetActivatedStyle(f.buttonActivatedStyle)
SetBackgroundColorActivated(f.buttonTextColor).
SetBackgroundColor(f.buttonBackgroundColor)
buttonIndex := index + len(f.items) buttonIndex := index + len(f.items)
positions[buttonIndex].x = x positions[buttonIndex].x = x
@ -671,16 +685,22 @@ func (f *Form) Focus(delegate func(p Primitive)) {
} }
} }
if f.focusedElement < len(f.items) { // Set the handler for all items and buttons.
// We're selecting an item. for index, item := range f.items {
item := f.items[f.focusedElement]
item.SetFinishedFunc(handler) item.SetFinishedFunc(handler)
delegate(item) if f.focusedElement == index {
} else { func(i FormItem) { // Wrapping might not be necessary anymore in future Go versions.
// We're selecting a button. defer delegate(i)
button := f.buttons[f.focusedElement-len(f.items)] }(item)
}
}
for index, button := range f.buttons {
button.SetExitFunc(handler) 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. // Calculate the width of this modal.
buttonsWidth := 0 buttonsWidth := 0
for _, button := range m.form.buttons { for _, button := range m.form.buttons {
buttonsWidth += TaggedStringWidth(button.label) + 4 + 2 buttonsWidth += TaggedStringWidth(button.text) + 4 + 2
} }
buttonsWidth -= 2 buttonsWidth -= 2
screenWidth, screenHeight := screen.Size() screenWidth, screenHeight := screen.Size()