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