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
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
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
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
64 func (b *Button) SetBorderSize(size int) {
65 b.Lock()
66 defer b.Unlock()
67
68 b.borderSize = size
69 }
70
71
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
83 func (b *Button) Text() string {
84 b.Lock()
85 defer b.Unlock()
86
87 return b.field.Text()
88 }
89
90
91 func (b *Button) SetText(text string) {
92 b.Lock()
93 defer b.Unlock()
94
95 b.field.SetText(text)
96 }
97
98
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
107 func (b *Button) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
108 return false, nil
109 }
110
111
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
137 func (b *Button) Draw(screen *ebiten.Image) error {
138 r := b.rect
139
140
141 b.field.Draw(screen)
142
143
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