...

Source file src/code.rocket9labs.com/tslocum/etk/button.go

Documentation: code.rocket9labs.com/tslocum/etk

     1  package etk
     2  
     3  import (
     4  	"image"
     5  	"image/color"
     6  	"sync"
     7  
     8  	"code.rocket9labs.com/tslocum/etk/messeji"
     9  	"github.com/hajimehoshi/ebiten/v2"
    10  	"golang.org/x/image/font"
    11  )
    12  
    13  // Button is a clickable button.
    14  type Button struct {
    15  	*Box
    16  	field        *messeji.TextField
    17  	borderSize   int
    18  	borderTop    color.RGBA
    19  	borderRight  color.RGBA
    20  	borderBottom color.RGBA
    21  	borderLeft   color.RGBA
    22  	onSelected   func() error
    23  	pressed      bool
    24  }
    25  
    26  // NewButton returns a new Button widget.
    27  func NewButton(label string, onSelected func() error) *Button {
    28  	textColor := Style.ButtonTextColor
    29  	if textColor.A == 0 {
    30  		textColor = Style.TextColorDark
    31  	}
    32  	f := newText()
    33  	f.SetText(label)
    34  	f.SetForegroundColor(textColor)
    35  	f.SetHorizontal(messeji.AlignCenter)
    36  	f.SetVertical(messeji.AlignCenter)
    37  	f.SetScrollBarVisible(false)
    38  
    39  	b := &Button{
    40  		Box:          NewBox(),
    41  		field:        f,
    42  		onSelected:   onSelected,
    43  		borderSize:   Scale(Style.BorderSize),
    44  		borderTop:    Style.BorderColorTop,
    45  		borderRight:  Style.BorderColorRight,
    46  		borderBottom: Style.BorderColorBottom,
    47  		borderLeft:   Style.BorderColorLeft,
    48  	}
    49  	b.SetBackground(Style.ButtonBgColor)
    50  	return b
    51  }
    52  
    53  // SetRect sets the position and size of the Button.
    54  func (b *Button) SetRect(r image.Rectangle) {
    55  	b.Box.rect = r
    56  
    57  	b.field.SetRect(r)
    58  
    59  	for _, w := range b.children {
    60  		w.SetRect(r)
    61  	}
    62  }
    63  
    64  // SetBorderSize sets the size of the border around the button.
    65  func (b *Button) SetBorderSize(size int) {
    66  	b.Lock()
    67  	defer b.Unlock()
    68  
    69  	b.borderSize = size
    70  }
    71  
    72  // SetBorderColors sets the color of the top, right, bottom and left border.
    73  func (b *Button) SetBorderColors(top color.RGBA, right color.RGBA, bottom color.RGBA, left color.RGBA) {
    74  	b.Lock()
    75  	defer b.Unlock()
    76  
    77  	b.borderTop = top
    78  	b.borderRight = right
    79  	b.borderBottom = bottom
    80  	b.borderLeft = left
    81  }
    82  
    83  // Text returns the content of the text buffer.
    84  func (b *Button) Text() string {
    85  	b.Lock()
    86  	defer b.Unlock()
    87  
    88  	return b.field.Text()
    89  }
    90  
    91  // SetText sets the text in the field.
    92  func (b *Button) SetText(text string) {
    93  	b.Lock()
    94  	defer b.Unlock()
    95  
    96  	b.field.SetText(text)
    97  }
    98  
    99  // SetFont sets the font face of the text within the field.
   100  func (b *Button) SetFont(face font.Face, mutex *sync.Mutex) {
   101  	b.Lock()
   102  	defer b.Unlock()
   103  
   104  	b.field.SetFont(face, mutex)
   105  }
   106  
   107  // HandleKeyboard is called when a keyboard event occurs.
   108  func (b *Button) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
   109  	return false, nil
   110  }
   111  
   112  // HandleMouse is called when a mouse event occurs.
   113  func (b *Button) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
   114  	if !clicked {
   115  		if b.pressed && !pressed {
   116  			b.pressed = false
   117  			b.SetBackground(Style.ButtonBgColor)
   118  		}
   119  		return true, nil
   120  	}
   121  
   122  	b.Lock()
   123  	b.pressed = true
   124  	b.background = color.RGBA{uint8(float64(Style.ButtonBgColor.R) * 0.95), uint8(float64(Style.ButtonBgColor.G) * 0.95), uint8(float64(Style.ButtonBgColor.B) * 0.95), 255}
   125  	onSelected := b.onSelected
   126  	if onSelected == nil {
   127  		b.Unlock()
   128  		return true, nil
   129  	}
   130  	b.Unlock()
   131  
   132  	return true, onSelected()
   133  }
   134  
   135  // Draw draws the button on the screen.
   136  func (b *Button) Draw(screen *ebiten.Image) error {
   137  	r := b.rect
   138  
   139  	// Draw label.
   140  	b.field.Draw(screen)
   141  
   142  	// Draw border.
   143  	if b.borderSize != 0 {
   144  		if !b.pressed {
   145  			screen.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Min.X+b.borderSize, r.Max.Y)).(*ebiten.Image).Fill(b.borderLeft)
   146  			screen.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+b.borderSize)).(*ebiten.Image).Fill(b.borderTop)
   147  			screen.SubImage(image.Rect(r.Max.X-b.borderSize, r.Min.Y, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(b.borderRight)
   148  			screen.SubImage(image.Rect(r.Min.X, r.Max.Y-b.borderSize, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(b.borderBottom)
   149  		} else {
   150  			screen.SubImage(image.Rect(r.Max.X-b.borderSize, r.Min.Y, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(b.borderLeft)
   151  			screen.SubImage(image.Rect(r.Min.X, r.Max.Y-b.borderSize, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(b.borderTop)
   152  			screen.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Min.X+b.borderSize, r.Max.Y)).(*ebiten.Image).Fill(b.borderRight)
   153  			screen.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+b.borderSize)).(*ebiten.Image).Fill(b.borderBottom)
   154  		}
   155  	}
   156  
   157  	return nil
   158  }
   159  

View as plain text