checkable.go raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 package material
4
5 import (
6 "image"
7 "image/color"
8
9 "github.com/p9c/p9/pkg/gel/gio/f32"
10 "github.com/p9c/p9/pkg/gel/gio/internal/f32color"
11 "github.com/p9c/p9/pkg/gel/gio/io/pointer"
12 "github.com/p9c/p9/pkg/gel/gio/layout"
13 "github.com/p9c/p9/pkg/gel/gio/op/clip"
14 "github.com/p9c/p9/pkg/gel/gio/op/paint"
15 "github.com/p9c/p9/pkg/gel/gio/text"
16 "github.com/p9c/p9/pkg/gel/gio/unit"
17 "github.com/p9c/p9/pkg/gel/gio/widget"
18 )
19
20 type checkable struct {
21 Label string
22 Color color.NRGBA
23 Font text.Font
24 TextSize unit.Value
25 IconColor color.NRGBA
26 Size unit.Value
27 shaper text.Shaper
28 checkedStateIcon *widget.Icon
29 uncheckedStateIcon *widget.Icon
30 }
31
32 func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dimensions {
33 var icon *widget.Icon
34 if checked {
35 icon = c.checkedStateIcon
36 } else {
37 icon = c.uncheckedStateIcon
38 }
39
40 dims := layout.Flex{Alignment: layout.Middle}.Layout(gtx,
41 layout.Rigid(func(gtx layout.Context) layout.Dimensions {
42 return layout.Stack{Alignment: layout.Center}.Layout(gtx,
43 layout.Stacked(func(gtx layout.Context) layout.Dimensions {
44 size := gtx.Px(c.Size) * 4 / 3
45 dims := layout.Dimensions{
46 Size: image.Point{X: size, Y: size},
47 }
48 if !hovered {
49 return dims
50 }
51
52 background := f32color.MulAlpha(c.IconColor, 70)
53
54 radius := float32(size) / 2
55 paint.FillShape(gtx.Ops, background,
56 clip.Circle{
57 Center: f32.Point{X: radius, Y: radius},
58 Radius: radius,
59 }.Op(gtx.Ops))
60
61 return dims
62 }),
63 layout.Stacked(func(gtx layout.Context) layout.Dimensions {
64 return layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
65 size := gtx.Px(c.Size)
66 icon.Color = c.IconColor
67 if gtx.Queue == nil {
68 icon.Color = f32color.Disabled(icon.Color)
69 }
70 icon.Layout(gtx, unit.Px(float32(size)))
71 return layout.Dimensions{
72 Size: image.Point{X: size, Y: size},
73 }
74 })
75 }),
76 )
77 }),
78
79 layout.Rigid(func(gtx layout.Context) layout.Dimensions {
80 return layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
81 paint.ColorOp{Color: c.Color}.Add(gtx.Ops)
82 return widget.Label{}.Layout(gtx, c.shaper, c.Font, c.TextSize, c.Label)
83 })
84 }),
85 )
86 pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops)
87 return dims
88 }
89