...
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.BorderColorBottom,
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 func (c *Checkbox) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
92 return false, nil
93 }
94
95
96 func (c *Checkbox) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
97 if !clicked {
98 return true, nil
99 }
100
101 c.selected = !c.selected
102 c.updateImage()
103
104 c.Lock()
105 onSelect := c.onSelect
106 if onSelect == nil {
107 c.Unlock()
108 return true, nil
109 }
110 c.Unlock()
111
112 return true, onSelect()
113 }
114
115 func (c *Checkbox) updateImage() {
116 r := c.Rect()
117 if r.Empty() {
118 c.img = nil
119 return
120 }
121
122 bounds := r.Bounds()
123 newSize := bounds.Dx()
124 var initializeImg bool
125 if c.img == nil {
126 initializeImg = true
127 } else {
128 imgBounds := c.img.Bounds()
129 imgSize := imgBounds.Dx()
130 if imgSize != newSize {
131 initializeImg = true
132 }
133 }
134 if initializeImg {
135 c.baseImg = image.NewRGBA(rectAtOrigin(r))
136 c.img = ebiten.NewImage(newSize, newSize)
137 }
138
139
140 c.img.Fill(c.borderColor)
141 c.img.SubImage(rectAtOrigin(r).Inset(c.borderSize)).(*ebiten.Image).Fill(color.RGBA64{0, 0, 0, 0})
142
143
144 if !c.selected {
145 return
146 }
147 gc := draw2dimg.NewGraphicContext(c.baseImg)
148 gc.SetStrokeColor(c.checkColor)
149 gc.SetLineWidth(float64(c.borderSize))
150 gc.MoveTo(0, 0)
151 gc.LineTo(float64(r.Dx()), float64(r.Dy()))
152 gc.MoveTo(0, float64(r.Dy()))
153 gc.LineTo(float64(r.Dx()), 0)
154 gc.Stroke()
155 c.img.DrawImage(ebiten.NewImageFromImage(c.baseImg), nil)
156
157 }
158
159
160 func (c *Checkbox) Draw(screen *ebiten.Image) error {
161 if c.img == nil {
162 return nil
163 }
164
165 op := &ebiten.DrawImageOptions{}
166 op.GeoM.Translate(float64(c.rect.Min.X), float64(c.rect.Min.Y))
167 screen.DrawImage(c.img, op)
168 return nil
169 }
170
View as plain text