1
1
package widget
2
2
3
3
import (
4
+ "math"
4
5
"strings"
5
6
6
7
"fyne.io/fyne/v2"
@@ -15,6 +16,7 @@ import (
15
16
type CheckGroup struct {
16
17
DisableableWidget
17
18
Horizontal bool
19
+ numColumns int
18
20
Required bool
19
21
OnChanged func ([]string ) `json:"-"`
20
22
Options []string
@@ -38,6 +40,10 @@ func NewCheckGroup(options []string, changed func([]string)) *CheckGroup {
38
40
return r
39
41
}
40
42
43
+ func (r * CheckGroup ) SetColumns (columns int ) {
44
+ r .numColumns = columns
45
+ }
46
+
41
47
// Append adds a new option to the end of a CheckGroup widget.
42
48
func (r * CheckGroup ) Append (option string ) {
43
49
r .Options = append (r .Options , option )
@@ -179,54 +185,87 @@ type checkGroupRenderer struct {
179
185
checks * CheckGroup
180
186
}
181
187
188
+ func (r * CheckGroup ) countColumns () int {
189
+ if r .numColumns < 1 {
190
+ r .numColumns = 1
191
+ }
192
+ return r .numColumns
193
+ }
194
+
195
+ func (r * CheckGroup ) countRows () int {
196
+ return int (math .Ceil (float64 (len (r .items )) / float64 (r .countColumns ())))
197
+ }
198
+
199
+ func getLeading (size float64 , offset int ) float32 {
200
+ return float32 (size * float64 (offset ))
201
+ }
202
+
203
+ func getTrailing (size float64 , offset int ) float32 {
204
+ return getLeading (size , offset + 1 )
205
+ }
206
+
182
207
// Layout the components of the checks widget
183
208
func (r * checkGroupRenderer ) Layout (_ fyne.Size ) {
184
- count := 1
185
- if len (r .items ) > 0 {
186
- count = len (r .items )
187
- }
188
- var itemHeight , itemWidth float32
189
- minSize := r .checks .MinSize ()
209
+ cols := r .checks .countColumns ()
210
+
211
+ primaryObjects := cols
212
+ secondaryObjects := r .checks .countRows ()
190
213
if r .checks .Horizontal {
191
- itemHeight = minSize .Height
192
- itemWidth = minSize .Width / float32 (count )
193
- } else {
194
- itemHeight = minSize .Height / float32 (count )
195
- itemWidth = minSize .Width
214
+ primaryObjects , secondaryObjects = secondaryObjects , primaryObjects
196
215
}
197
216
198
- itemSize := fyne .NewSize (itemWidth , itemHeight )
199
- x , y := float32 (0 ), float32 (0 )
200
- for _ , item := range r .items {
201
- item .Resize (itemSize )
202
- item .Move (fyne .NewPos (x , y ))
217
+ size := r .checks .MinSize ()
218
+ cellWidth := float64 (size .Width ) / float64 (primaryObjects )
219
+ cellHeight := float64 (size .Height ) / float64 (secondaryObjects )
220
+
221
+ row , col := 0 , 0
222
+ i := 0
223
+ for _ , child := range r .items {
224
+ x1 := getLeading (cellWidth , col )
225
+ y1 := getLeading (cellHeight , row )
226
+ x2 := getTrailing (cellWidth , col )
227
+ y2 := getTrailing (cellHeight , row )
228
+
229
+ child .Move (fyne .NewPos (x1 , y1 ))
230
+ child .Resize (fyne .NewSize (x2 - x1 , y2 - y1 ))
231
+
203
232
if r .checks .Horizontal {
204
- x += itemWidth
233
+ if (i + 1 )% cols == 0 {
234
+ col ++
235
+ row = 0
236
+ } else {
237
+ row ++
238
+ }
205
239
} else {
206
- y += itemHeight
240
+ if (i + 1 )% cols == 0 {
241
+ row ++
242
+ col = 0
243
+ } else {
244
+ col ++
245
+ }
207
246
}
247
+ i ++
208
248
}
209
249
}
210
250
211
251
// MinSize calculates the minimum size of a checks item.
212
252
// This is based on the contained text, the checks icon and a standard amount of padding
213
253
// between each item.
214
254
func (r * checkGroupRenderer ) MinSize () fyne.Size {
215
- width := float32 (0 )
216
- height := float32 (0 )
217
- for _ , item := range r .items {
218
- itemMin := item .MinSize ()
219
-
220
- width = fyne .Max (width , itemMin .Width )
221
- height = fyne .Max (height , itemMin .Height )
255
+ minSize := fyne .NewSize (0 , 0 )
256
+ for _ , child := range r .items {
257
+ minSize = minSize .Max (child .MinSize ())
222
258
}
223
259
260
+ primaryObjects := r .checks .countColumns ()
261
+ secondaryObjects := r .checks .countRows ()
224
262
if r .checks .Horizontal {
225
- width = width * float32 (len (r .items ))
226
- } else {
227
- height = height * float32 (len (r .items ))
263
+ primaryObjects , secondaryObjects = secondaryObjects , primaryObjects
228
264
}
229
265
266
+ width := minSize .Width * float32 (primaryObjects )
267
+ height := minSize .Height * float32 (secondaryObjects )
268
+
230
269
return fyne .NewSize (width , height )
231
270
}
232
271
@@ -245,7 +284,7 @@ func (r *checkGroupRenderer) updateItems() {
245
284
r .SetObjects (append (r .Objects (), item ))
246
285
r .items = append (r .items , item )
247
286
}
248
- r .Layout (r .checks .Size ())
287
+ r .Layout (r .checks .Size ()) // argument is ignored
249
288
} else if len (r .items ) > len (r .checks .Options ) {
250
289
total := len (r .checks .Options )
251
290
r .items = r .items [:total ]
0 commit comments