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