...
1 package etk
2
3 import (
4 "image"
5 "image/color"
6
7 "github.com/hajimehoshi/ebiten/v2"
8 "github.com/llgcode/draw2d/draw2dimg"
9 )
10
11
12 type Checkbox struct {
13 *Box
14
15 selected bool
16 checkColor color.RGBA
17 borderSize int
18 borderColor color.RGBA
19 baseImg *image.RGBA
20 img *ebiten.Image
21 onSelect func() error
22 }
23
24
25 func NewCheckbox(onSelect func() error) *Checkbox {
26 c := &Checkbox{
27 Box: NewBox(),
28 checkColor: Style.TextColorDark,
29 borderSize: 2,
30 borderColor: Style.ButtonBorderBottom,
31 onSelect: onSelect,
32 }
33 c.SetBackground(Style.CheckboxBgColor)
34 return c
35 }
36
37
38
39 func (c *Checkbox) SetRect(r image.Rectangle) {
40 if c.Box.rect.Eq(r) {
41 return
42 }
43
44 bounds := r.Bounds()
45 newSize := bounds.Dx()
46 if bounds.Dy() < newSize {
47 newSize = bounds.Dy()
48 }
49
50 if r.Dx() != newSize {
51 r.Max.X = r.Min.X + newSize
52 }
53 if r.Dy() != newSize {
54 r.Max.Y = r.Min.Y + newSize
55 }
56 c.Box.rect = r
57
58 c.updateImage()
59
60 for _, w := range c.children {
61 w.SetRect(r)
62 }
63 }
64
65
66 func (c *Checkbox) SetCheckColor(checkColor color.RGBA) {
67 c.checkColor = checkColor
68 c.updateImage()
69 }
70
71
72 func (c *Checkbox) SetBorderColor(borderColor color.RGBA) {
73 c.borderColor = borderColor
74 c.updateImage()
75 }
76
77
78 func (c *Checkbox) Selected() bool {
79 return c.selected
80 }
81
82
83
84 func (c *Checkbox) SetSelected(selected bool) {
85 if c.selected == selected {
86 return
87 }
88 c.selected = selected
89 c.updateImage()
90 }
91
92
93
94 func (c *Checkbox) Cursor() ebiten.CursorShapeType {
95 return ebiten.CursorShapePointer
96 }
97
98
99 func (c *Checkbox) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
100 return false, nil
101 }
102
103
104 func (c *Checkbox) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
105 if !clicked {
106 return true, nil
107 }
108
109 c.selected = !c.selected
110 c.updateImage()
111
112 c.Lock()
113 onSelect := c.onSelect
114 if onSelect == nil {
115 c.Unlock()
116 return true, nil
117 }
118 c.Unlock()
119
120 return true, onSelect()
121 }
122
123 func (c *Checkbox) updateImage() {
124 r := c.Rect()
125 if r.Empty() {
126 c.img = nil
127 return
128 }
129
130 bounds := r.Bounds()
131 newSize := bounds.Dx()
132 var initializeImg bool
133 if c.img == nil {
134 initializeImg = true
135 } else {
136 imgBounds := c.img.Bounds()
137 imgSize := imgBounds.Dx()
138 if imgSize != newSize {
139 initializeImg = true
140 }
141 }
142 if initializeImg {
143 c.baseImg = image.NewRGBA(rectAtOrigin(r))
144 c.img = ebiten.NewImage(newSize, newSize)
145 }
146
147
148 c.img.Fill(c.borderColor)
149 c.img.SubImage(rectAtOrigin(r).Inset(c.borderSize)).(*ebiten.Image).Fill(color.RGBA64{0, 0, 0, 0})
150
151
152 if !c.selected {
153 return
154 }
155 gc := draw2dimg.NewGraphicContext(c.baseImg)
156 gc.SetStrokeColor(c.checkColor)
157 gc.SetLineWidth(float64(c.borderSize))
158 gc.MoveTo(0, 0)
159 gc.LineTo(float64(r.Dx()), float64(r.Dy()))
160 gc.MoveTo(0, float64(r.Dy()))
161 gc.LineTo(float64(r.Dx()), 0)
162 gc.Stroke()
163 c.img.DrawImage(ebiten.NewImageFromImage(c.baseImg), nil)
164
165 }
166
167
168 func (c *Checkbox) Draw(screen *ebiten.Image) error {
169 if c.img == nil {
170 return nil
171 }
172
173 op := &ebiten.DrawImageOptions{}
174 op.GeoM.Translate(float64(c.rect.Min.X), float64(c.rect.Min.Y))
175 screen.DrawImage(c.img, op)
176 return nil
177 }
178
View as plain text