...

Source file src/code.rocketnine.space/tslocum/cview/button.go

Documentation: code.rocketnine.space/tslocum/cview

     1  package cview
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/gdamore/tcell/v2"
     7  )
     8  
     9  // Button is labeled box that triggers an action when selected.
    10  type Button struct {
    11  	*Box
    12  
    13  	// The text to be displayed before the input area.
    14  	label []byte
    15  
    16  	// The label color.
    17  	labelColor tcell.Color
    18  
    19  	// The label color when the button is in focus.
    20  	labelColorFocused tcell.Color
    21  
    22  	// The background color when the button is in focus.
    23  	backgroundColorFocused tcell.Color
    24  
    25  	// An optional function which is called when the button was selected.
    26  	selected func()
    27  
    28  	// An optional function which is called when the user leaves the button. A
    29  	// key is provided indicating which key was pressed to leave (tab or backtab).
    30  	blur func(tcell.Key)
    31  
    32  	// An optional rune which is drawn after the label when the button is focused.
    33  	cursorRune rune
    34  
    35  	sync.RWMutex
    36  }
    37  
    38  // NewButton returns a new input field.
    39  func NewButton(label string) *Button {
    40  	box := NewBox()
    41  	box.SetRect(0, 0, TaggedStringWidth(label)+4, 1)
    42  	box.SetBackgroundColor(Styles.MoreContrastBackgroundColor)
    43  	return &Button{
    44  		Box:                    box,
    45  		label:                  []byte(label),
    46  		labelColor:             Styles.PrimaryTextColor,
    47  		labelColorFocused:      Styles.PrimaryTextColor,
    48  		cursorRune:             Styles.ButtonCursorRune,
    49  		backgroundColorFocused: Styles.ContrastBackgroundColor,
    50  	}
    51  }
    52  
    53  // SetLabel sets the button text.
    54  func (b *Button) SetLabel(label string) {
    55  	b.Lock()
    56  	defer b.Unlock()
    57  
    58  	b.label = []byte(label)
    59  }
    60  
    61  // GetLabel returns the button text.
    62  func (b *Button) GetLabel() string {
    63  	b.RLock()
    64  	defer b.RUnlock()
    65  
    66  	return string(b.label)
    67  }
    68  
    69  // SetLabelColor sets the color of the button text.
    70  func (b *Button) SetLabelColor(color tcell.Color) {
    71  	b.Lock()
    72  	defer b.Unlock()
    73  
    74  	b.labelColor = color
    75  }
    76  
    77  // SetLabelColorFocused sets the color of the button text when the button is
    78  // in focus.
    79  func (b *Button) SetLabelColorFocused(color tcell.Color) {
    80  	b.Lock()
    81  	defer b.Unlock()
    82  
    83  	b.labelColorFocused = color
    84  }
    85  
    86  // SetCursorRune sets the rune to show within the button when it is focused.
    87  func (b *Button) SetCursorRune(rune rune) {
    88  	b.Lock()
    89  	defer b.Unlock()
    90  
    91  	b.cursorRune = rune
    92  }
    93  
    94  // SetBackgroundColorFocused sets the background color of the button text when
    95  // the button is in focus.
    96  func (b *Button) SetBackgroundColorFocused(color tcell.Color) {
    97  	b.Lock()
    98  	defer b.Unlock()
    99  
   100  	b.backgroundColorFocused = color
   101  }
   102  
   103  // SetSelectedFunc sets a handler which is called when the button was selected.
   104  func (b *Button) SetSelectedFunc(handler func()) {
   105  	b.Lock()
   106  	defer b.Unlock()
   107  
   108  	b.selected = handler
   109  }
   110  
   111  // SetBlurFunc sets a handler which is called when the user leaves the button.
   112  // The callback function is provided with the key that was pressed, which is one
   113  // of the following:
   114  //
   115  //   - KeyEscape: Leaving the button with no specific direction.
   116  //   - KeyTab: Move to the next field.
   117  //   - KeyBacktab: Move to the previous field.
   118  func (b *Button) SetBlurFunc(handler func(key tcell.Key)) {
   119  	b.Lock()
   120  	defer b.Unlock()
   121  
   122  	b.blur = handler
   123  }
   124  
   125  // Draw draws this primitive onto the screen.
   126  func (b *Button) Draw(screen tcell.Screen) {
   127  	if !b.GetVisible() {
   128  		return
   129  	}
   130  
   131  	b.Lock()
   132  	defer b.Unlock()
   133  
   134  	// Draw the box.
   135  	borderColor := b.borderColor
   136  	backgroundColor := b.backgroundColor
   137  	if b.focus.HasFocus() {
   138  		b.backgroundColor = b.backgroundColorFocused
   139  		b.borderColor = b.labelColorFocused
   140  		defer func() {
   141  			b.borderColor = borderColor
   142  		}()
   143  	}
   144  	b.Unlock()
   145  	b.Box.Draw(screen)
   146  	b.Lock()
   147  	b.backgroundColor = backgroundColor
   148  
   149  	// Draw label.
   150  	x, y, width, height := b.GetInnerRect()
   151  	if width > 0 && height > 0 {
   152  		y = y + height/2
   153  		labelColor := b.labelColor
   154  		if b.focus.HasFocus() {
   155  			labelColor = b.labelColorFocused
   156  		}
   157  		_, pw := Print(screen, b.label, x, y, width, AlignCenter, labelColor)
   158  
   159  		// Draw cursor.
   160  		if b.focus.HasFocus() && b.cursorRune != 0 {
   161  			cursorX := x + int(float64(width)/2+float64(pw)/2)
   162  			if cursorX > x+width-1 {
   163  				cursorX = x + width - 1
   164  			} else if cursorX < x+width {
   165  				cursorX++
   166  			}
   167  			Print(screen, []byte(string(b.cursorRune)), cursorX, y, width, AlignLeft, labelColor)
   168  		}
   169  	}
   170  }
   171  
   172  // InputHandler returns the handler for this primitive.
   173  func (b *Button) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
   174  	return b.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
   175  		// Process key event.
   176  		if HitShortcut(event, Keys.Select, Keys.Select2) {
   177  			if b.selected != nil {
   178  				b.selected()
   179  			}
   180  		} else if HitShortcut(event, Keys.Cancel, Keys.MovePreviousField, Keys.MoveNextField) {
   181  			if b.blur != nil {
   182  				b.blur(event.Key())
   183  			}
   184  		}
   185  	})
   186  }
   187  
   188  // MouseHandler returns the mouse handler for this primitive.
   189  func (b *Button) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
   190  	return b.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
   191  		if !b.InRect(event.Position()) {
   192  			return false, nil
   193  		}
   194  
   195  		// Process mouse event.
   196  		if action == MouseLeftClick {
   197  			setFocus(b)
   198  			if b.selected != nil {
   199  				b.selected()
   200  			}
   201  			consumed = true
   202  		}
   203  
   204  		return
   205  	})
   206  }
   207  

View as plain text