~pierrec/giox

ref: c164e218831e giox/widgetx/icons.go -rw-r--r-- 2.8 KiB
c164e218Pierre Curto cm/iconx: update the set of icons 9 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package widgetx

import (
	"image"
	"image/color"

	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/unit"
	"gioui.org/widget"

	"git.sr.ht/~pierrec/giox/internal/bitmap"
)

// Icons represents a toolbar made of icons.
type Icons struct {
	Hover Hover
	// Color is the icon color when not hovered.
	Color  color.NRGBA
	Size   unit.Value
	Icons  []widget.Icon
	status []widget.Bool
	hidden bitmap.Bitmap
	List   layout.List
}

func (s *Icons) init() {
	in := len(s.Icons)
	if sn := len(s.status); in > sn {
		s.status = append(s.status, make([]widget.Bool, in-sn)...)
	}
	s.status = s.status[:in]
}

func (s *Icons) Layout(gtx layout.Context, onClick, onPress func(gtx layout.Context, idx int)) layout.Dimensions {
	s.init()
	if onClick != nil {
		for idx := range s.Icons {
			if s.status[idx].Changed() {
				onClick(gtx, idx)
				op.InvalidateOp{}.Add(gtx.Ops)
				break
			}
		}
	}
	if onPress != nil {
		for idx := range s.Icons {
			if s.status[idx].Pressed() {
				onPress(gtx, idx)
				op.InvalidateOp{}.Add(gtx.Ops)
				break
			}
		}
	}
	return s.List.Layout(gtx, len(s.Icons), func(gtx layout.Context, idx int) layout.Dimensions {
		ic := &s.Icons[idx]
		if s.Hidden(idx) {
			return layout.Dimensions{}
		}
		hovered := s.status[idx].Hovered()
		col := s.Color
		if hovered || s.status[idx].Value {
			col = s.Hover.Foreground
		}
		return layout.Stack{}.Layout(gtx,
			layout.Expanded(func(gtx layout.Context) layout.Dimensions {
				return s.Hover.Layout(gtx, hovered)
			}),
			layout.Stacked(func(gtx layout.Context) layout.Dimensions {
				return s.status[idx].Layout(gtx, func(gtx layout.Context) layout.Dimensions {
					gtx.Constraints.Min = image.Pt(gtx.Metric.Px(s.Size), 0)
					return ic.Layout(gtx, col)
				})
			}),
		)
	})
}

func (s *Icons) Click(idx int) {
	s.init()
	s.status[idx].Value = !s.status[idx].Value
}

func (s *Icons) Hovered(idx int) bool {
	s.init()
	return s.status[idx].Hovered()
}

func (s *Icons) Status(idx int) bool {
	s.init()
	return s.status[idx].Value
}

func (s *Icons) SetStatus(idx int, status bool) {
	s.init()
	s.status[idx].Value = status
}

// Hide temporarily removes the icon at indexes from the menu.
func (s *Icons) Hide(indexes ...int) {
	s.init()
	for _, idx := range indexes {
		s.hidden.Set(idx)
	}
}

func (s *Icons) Hidden(idx int) bool {
	return s.hidden.Has(idx)
}

// Show restores the icon at indexes in the menu.
func (s *Icons) Show(indexes ...int) {
	s.init()
	for _, idx := range indexes {
		s.hidden.Unset(idx)
	}
}

// LoadIcons returns a slice of icons from their data.
func LoadIcons(data ...[]byte) []widget.Icon {
	s := make([]widget.Icon, len(data))
	for i, d := range data {
		ic, _ := widget.NewIcon(d)
		s[i] = *ic
	}
	return s
}

// LoadIcon loads an icon from its data.
func LoadIcon(data []byte) widget.Icon {
	ic, _ := widget.NewIcon(data)
	return *ic
}