package tview import ( "github.com/gdamore/tcell/v2" ) // Button is labeled box that triggers an action when selected. // // See https://github.com/rivo/tview/wiki/Button for an example. type Button struct { *Box // If set to true, the button cannot be activated. disabled bool // The text to be displayed inside the button. text string // The button's style (when deactivated). style tcell.Style // The button's style (when activated). activatedStyle tcell.Style // The button's style (when disabled). disabledStyle tcell.Style // An optional function which is called when the button was selected. selected func() // An optional function which is called when the user leaves the button. A // key is provided indicating which key was pressed to leave (tab or // backtab). exit func(tcell.Key) } // NewButton returns a new input field. func NewButton(label string) *Button { box := NewBox() box.SetRect(0, 0, TaggedStringWidth(label)+4, 1) return &Button{ Box: box, text: label, style: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor), activatedStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.InverseTextColor), disabledStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.ContrastSecondaryTextColor), } } // SetLabel sets the button text. func (b *Button) SetLabel(label string) *Button { b.text = label return b } // GetLabel returns the button text. func (b *Button) GetLabel() string { return b.text } // SetLabelColor sets the color of the button text. func (b *Button) SetLabelColor(color tcell.Color) *Button { 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.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.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 } // SetDisabledStyle sets the style of the button used when it is disabled. func (b *Button) SetDisabledStyle(style tcell.Style) *Button { b.disabledStyle = style return b } // SetDisabled sets whether or not the button is disabled. Disabled buttons // cannot be activated. // // If the button is part of a form, you should set focus to the form itself // after calling this function to set focus to the next non-disabled form item. func (b *Button) SetDisabled(disabled bool) *Button { b.disabled = disabled return b } // IsDisabled returns whether or not the button is disabled. func (b *Button) IsDisabled() bool { return b.disabled } // SetSelectedFunc sets a handler which is called when the button was selected. func (b *Button) SetSelectedFunc(handler func()) *Button { b.selected = handler return b } // SetExitFunc sets a handler which is called when the user leaves the button. // The callback function is provided with the key that was pressed, which is one // of the following: // // - KeyEscape: Leaving the button with no specific direction. // - KeyTab: Move to the next field. // - KeyBacktab: Move to the previous field. func (b *Button) SetExitFunc(handler func(key tcell.Key)) *Button { b.exit = handler return b } // Draw draws this primitive onto the screen. func (b *Button) Draw(screen tcell.Screen) { // Draw the box. style := b.style if b.disabled { style = b.disabledStyle } _, backgroundColor, _ := style.Decompose() if b.HasFocus() && !b.disabled { 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) // Draw label. x, y, width, height := b.GetInnerRect() if width > 0 && height > 0 { y = y + height/2 printWithStyle(screen, b.text, x, y, 0, width, AlignCenter, style, true) } } // InputHandler returns the handler for this primitive. func (b *Button) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) { return b.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) { if b.disabled { return } // Process key event. switch key := event.Key(); key { case tcell.KeyEnter: // Selected. if b.selected != nil { b.selected() } case tcell.KeyBacktab, tcell.KeyTab, tcell.KeyEscape: // Leave. No action. if b.exit != nil { b.exit(key) } } }) } // MouseHandler returns the mouse handler for this primitive. func (b *Button) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) { return b.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) { if b.disabled { return false, nil } if !b.InRect(event.Position()) { return false, nil } // Process mouse event. if action == MouseLeftDown { setFocus(b) consumed = true } else if action == MouseLeftClick { if b.selected != nil { b.selected() } consumed = true } return }) }