...

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

View as plain text