button.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. package tview
  2. import (
  3. "github.com/gdamore/tcell/v2"
  4. )
  5. // Button is labeled box that triggers an action when selected.
  6. //
  7. // See https://github.com/rivo/tview/wiki/Button for an example.
  8. type Button struct {
  9. *Box
  10. // If set to true, the button cannot be activated.
  11. disabled bool
  12. // The text to be displayed inside the button.
  13. text string
  14. // The button's style (when deactivated).
  15. style tcell.Style
  16. // The button's style (when activated).
  17. activatedStyle tcell.Style
  18. // The button's style (when disabled).
  19. disabledStyle tcell.Style
  20. // An optional function which is called when the button was selected.
  21. selected func()
  22. // An optional function which is called when the user leaves the button. A
  23. // key is provided indicating which key was pressed to leave (tab or
  24. // backtab).
  25. exit func(tcell.Key)
  26. }
  27. // NewButton returns a new input field.
  28. func NewButton(label string) *Button {
  29. box := NewBox()
  30. box.SetRect(0, 0, TaggedStringWidth(label)+4, 1)
  31. return &Button{
  32. Box: box,
  33. text: label,
  34. style: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.PrimaryTextColor),
  35. activatedStyle: tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.InverseTextColor),
  36. disabledStyle: tcell.StyleDefault.Background(Styles.ContrastBackgroundColor).Foreground(Styles.ContrastSecondaryTextColor),
  37. }
  38. }
  39. // SetLabel sets the button text.
  40. func (b *Button) SetLabel(label string) *Button {
  41. b.text = label
  42. return b
  43. }
  44. // GetLabel returns the button text.
  45. func (b *Button) GetLabel() string {
  46. return b.text
  47. }
  48. // SetLabelColor sets the color of the button text.
  49. func (b *Button) SetLabelColor(color tcell.Color) *Button {
  50. b.style = b.style.Foreground(color)
  51. return b
  52. }
  53. // SetStyle sets the style of the button used when it is not focused.
  54. func (b *Button) SetStyle(style tcell.Style) *Button {
  55. b.style = style
  56. return b
  57. }
  58. // SetLabelColorActivated sets the color of the button text when the button is
  59. // in focus.
  60. func (b *Button) SetLabelColorActivated(color tcell.Color) *Button {
  61. b.activatedStyle = b.activatedStyle.Foreground(color)
  62. return b
  63. }
  64. // SetBackgroundColorActivated sets the background color of the button text when
  65. // the button is in focus.
  66. func (b *Button) SetBackgroundColorActivated(color tcell.Color) *Button {
  67. b.activatedStyle = b.activatedStyle.Background(color)
  68. return b
  69. }
  70. // SetActivatedStyle sets the style of the button used when it is focused.
  71. func (b *Button) SetActivatedStyle(style tcell.Style) *Button {
  72. b.activatedStyle = style
  73. return b
  74. }
  75. // SetDisabledStyle sets the style of the button used when it is disabled.
  76. func (b *Button) SetDisabledStyle(style tcell.Style) *Button {
  77. b.disabledStyle = style
  78. return b
  79. }
  80. // SetDisabled sets whether or not the button is disabled. Disabled buttons
  81. // cannot be activated.
  82. //
  83. // If the button is part of a form, you should set focus to the form itself
  84. // after calling this function to set focus to the next non-disabled form item.
  85. func (b *Button) SetDisabled(disabled bool) *Button {
  86. b.disabled = disabled
  87. return b
  88. }
  89. // IsDisabled returns whether or not the button is disabled.
  90. func (b *Button) IsDisabled() bool {
  91. return b.disabled
  92. }
  93. // SetSelectedFunc sets a handler which is called when the button was selected.
  94. func (b *Button) SetSelectedFunc(handler func()) *Button {
  95. b.selected = handler
  96. return b
  97. }
  98. // SetExitFunc sets a handler which is called when the user leaves the button.
  99. // The callback function is provided with the key that was pressed, which is one
  100. // of the following:
  101. //
  102. // - KeyEscape: Leaving the button with no specific direction.
  103. // - KeyTab: Move to the next field.
  104. // - KeyBacktab: Move to the previous field.
  105. func (b *Button) SetExitFunc(handler func(key tcell.Key)) *Button {
  106. b.exit = handler
  107. return b
  108. }
  109. // Draw draws this primitive onto the screen.
  110. func (b *Button) Draw(screen tcell.Screen) {
  111. // Draw the box.
  112. style := b.style
  113. if b.disabled {
  114. style = b.disabledStyle
  115. }
  116. _, backgroundColor, _ := style.Decompose()
  117. if b.HasFocus() && !b.disabled {
  118. style = b.activatedStyle
  119. _, backgroundColor, _ = style.Decompose()
  120. // Highlight button for one drawing cycle.
  121. borderColor := b.GetBorderColor()
  122. b.SetBorderColor(backgroundColor)
  123. defer func() {
  124. b.SetBorderColor(borderColor)
  125. }()
  126. }
  127. b.SetBackgroundColor(backgroundColor)
  128. b.Box.DrawForSubclass(screen, b)
  129. // Draw label.
  130. x, y, width, height := b.GetInnerRect()
  131. if width > 0 && height > 0 {
  132. y = y + height/2
  133. printWithStyle(screen, b.text, x, y, 0, width, AlignCenter, style, true)
  134. }
  135. }
  136. // InputHandler returns the handler for this primitive.
  137. func (b *Button) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
  138. return b.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
  139. if b.disabled {
  140. return
  141. }
  142. // Process key event.
  143. switch key := event.Key(); key {
  144. case tcell.KeyEnter: // Selected.
  145. if b.selected != nil {
  146. b.selected()
  147. }
  148. case tcell.KeyBacktab, tcell.KeyTab, tcell.KeyEscape: // Leave. No action.
  149. if b.exit != nil {
  150. b.exit(key)
  151. }
  152. }
  153. })
  154. }
  155. // MouseHandler returns the mouse handler for this primitive.
  156. func (b *Button) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
  157. return b.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
  158. if b.disabled {
  159. return false, nil
  160. }
  161. if !b.InRect(event.Position()) {
  162. return false, nil
  163. }
  164. // Process mouse event.
  165. if action == MouseLeftDown {
  166. setFocus(b)
  167. consumed = true
  168. } else if action == MouseLeftClick {
  169. if b.selected != nil {
  170. b.selected()
  171. }
  172. consumed = true
  173. }
  174. return
  175. })
  176. }