iconbutton.go raw
1 package gel
2
3 import (
4 "image"
5
6 "github.com/p9c/gio/f32"
7 "github.com/p9c/gio/io/pointer"
8 l "github.com/p9c/gio/layout"
9 "github.com/p9c/gio/op/clip"
10 "github.com/p9c/gio/unit"
11 "golang.org/x/exp/shiny/materialdesign/icons"
12
13 "github.com/p9c/gel/f32color"
14 )
15
16 type IconButton struct {
17 *Window
18 background string
19 // Color is the icon color.
20 color string
21 icon *Icon
22 // Size is the icon size.
23 size unit.Value
24 inset *Inset
25 button *Clickable
26 corners int
27 }
28
29 // IconButton creates an icon with a circular *optional non-round corners* background and an icon placed in the centre
30 func (w *Window) IconButton(button *Clickable) *IconButton {
31 return &IconButton{
32 Window: w,
33 background: "Primary",
34 color: "DocBg",
35 size: w.TextSize,
36 inset: w.Inset(0.33, nil),
37 button: button,
38 icon: w.Icon().Src(&icons.AlertError),
39 }
40 }
41
42 // Corners sets the corners that will be circular
43 func (b *IconButton) Corners(corners int) *IconButton {
44 b.corners = corners
45 return b
46 }
47
48 // Background sets the color of the circular background
49 func (b *IconButton) Background(color string) *IconButton {
50 b.background = color
51 return b
52 }
53
54 // Color sets the color of the icon
55 func (b *IconButton) Color(color string) *IconButton {
56 b.color = color
57 return b
58 }
59
60 // Icon sets the icon to display
61 func (b *IconButton) Icon(ic *Icon) *IconButton {
62 b.icon = ic
63 return b
64 }
65
66 // Scale changes the size of the icon as a ratio of the base font size
67 func (b *IconButton) Scale(scale float32) *IconButton {
68 b.size = b.Theme.TextSize.Scale(scale * 0.72)
69 return b
70 }
71
72 // ButtonInset sets the size of inset that goes in between the button background
73 // and the icon
74 func (b *IconButton) ButtonInset(inset float32) *IconButton {
75 b.inset = b.Inset(inset, b.button.Fn)
76 return b
77 }
78
79 // SetClick sets the function to run on click
80 func (b *IconButton) SetClick(fn func()) *IconButton {
81 b.button.SetClick(fn)
82 return b
83 }
84
85 // SetPress sets the function to run on press
86 func (b *IconButton) SetPress(fn func()) *IconButton {
87 b.button.SetPress(fn)
88 return b
89 }
90
91 // SetCancel sets the function to run on cancel (click but release outside)
92 func (b *IconButton) SetCancel(fn func()) *IconButton {
93 b.button.SetCancel(fn)
94 return b
95 }
96
97 // Fn renders the icon button
98 func (b *IconButton) Fn(gtx l.Context) l.Dimensions {
99 return b.Stack().Expanded(
100 func(gtx l.Context) l.Dimensions {
101 sizex, sizey := gtx.Constraints.Min.X, gtx.Constraints.Min.Y
102 sizexf, sizeyf := float32(sizex), float32(sizey)
103 rr := (sizexf + sizeyf) * .25
104 clip.RRect{
105 Rect: f32.Rectangle{Max: f32.Point{X: sizexf, Y: sizeyf}},
106 NE: ifDir(rr, b.corners&NE),
107 NW: ifDir(rr, b.corners&NW),
108 SE: ifDir(rr, b.corners&SE),
109 SW: ifDir(rr, b.corners&SW),
110 }.Add(gtx.Ops)
111 background := b.Theme.Colors.GetNRGBAFromName(b.background)
112 if gtx.Queue == nil {
113 background = f32color.MulAlpha(background, 150)
114 }
115 var dims l.Dimensions
116 if b.background != "" {
117 dims = Fill(gtx, background)
118 }
119 for _, c := range b.button.History() {
120 drawInk(gtx, c)
121 }
122 return dims
123 },
124 ).Stacked(
125 b.inset.Embed(b.icon.Fn).Fn,
126 ).Expanded(
127 func(gtx l.Context) l.Dimensions {
128 pointer.Ellipse(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops)
129 return b.button.Fn(gtx)
130 },
131 ).Fn(gtx)
132 }
133