-
Notifications
You must be signed in to change notification settings - Fork 21
/
clickable_list.go
106 lines (93 loc) · 2.77 KB
/
clickable_list.go
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
package cryptomaterial
import (
"gioui.org/layout"
"gioui.org/unit"
)
type ClickableInset struct {
Right unit.Dp
Bottom unit.Dp
}
type ClickableList struct {
layout.List
theme *Theme
clickables []*Clickable
Radius CornerRadius // this radius is used by the clickable
selectedItem int
DividerHeight unit.Dp
IsShadowEnabled bool
IsHoverable bool
CompleteRadius bool // used to control where to apply the Radius field.
ClickableInset ClickableInset // Used to restrict hover layout
}
func (t *Theme) NewClickableList(axis layout.Axis) *ClickableList {
click := &ClickableList{
theme: t,
selectedItem: -1,
List: layout.List{
Axis: axis,
},
IsHoverable: true,
}
return click
}
func (cl *ClickableList) ItemClicked() (bool, int) {
defer func() {
cl.selectedItem = -1
}()
return cl.selectedItem != -1, cl.selectedItem
}
func (cl *ClickableList) handleClickables(count int) {
if len(cl.clickables) != count {
cl.clickables = make([]*Clickable, count)
for i := 0; i < count; i++ {
clickable := cl.theme.NewClickable(cl.IsHoverable)
cl.clickables[i] = clickable
}
}
for index, clickable := range cl.clickables {
for clickable.Clicked() {
cl.selectedItem = index
}
}
}
func (cl *ClickableList) Layout(gtx layout.Context, count int, w layout.ListElement) layout.Dimensions {
cl.handleClickables(count)
return cl.List.Layout(gtx, count, func(gtx C, i int) D {
if cl.IsShadowEnabled && cl.clickables[i].button.Hovered() {
shadow := cl.theme.Shadow()
shadow.SetShadowRadius(14)
shadow.SetShadowElevation(5)
return shadow.Layout(gtx, func(gtx C) D {
return cl.row(gtx, count, i, w)
})
}
return cl.row(gtx, count, i, w)
})
}
func (cl *ClickableList) row(gtx layout.Context, count int, i int, w layout.ListElement) layout.Dimensions {
if cl.CompleteRadius { // all round
cl.clickables[i].Radius = cl.Radius
} else if i == 0 { // first item
cl.clickables[i].Radius.TopLeft = cl.Radius.TopLeft
cl.clickables[i].Radius.TopRight = cl.Radius.TopRight
} else if i == count-1 { // last item
cl.clickables[i].Radius.BottomLeft = cl.Radius.BottomLeft
cl.clickables[i].Radius.BottomRight = cl.Radius.BottomRight
}
row := cl.clickables[i].LayoutWithInset(gtx, func(gtx layout.Context) layout.Dimensions {
return w(gtx, i)
}, cl.ClickableInset.Right, cl.ClickableInset.Bottom)
// add divider to all rows except last
if i < (count-1) && cl.DividerHeight > 0 {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return row
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
gtx.Constraints.Min.Y += gtx.Dp(cl.DividerHeight)
return layout.Dimensions{Size: gtx.Constraints.Min}
}),
)
}
return row
}