forked from google/gxui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
table_layout.go
123 lines (98 loc) · 2.29 KB
/
table_layout.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package mixins
import (
"github.com/google/gxui"
"github.com/google/gxui/math"
"github.com/google/gxui/mixins/base"
)
type Cell struct {
x, y, w, h int
}
func (c Cell) AtColumn(x int) bool {
return c.x <= x && c.x+c.w >= x
}
func (c Cell) AtRow(y int) bool {
return c.y <= y && c.y+c.h >= y
}
type TableLayoutOuter interface {
base.ContainerOuter
}
type TableLayout struct {
base.Container
outer TableLayoutOuter
grid map[gxui.Control]Cell
rows int
columns int
}
func (l *TableLayout) Init(outer TableLayoutOuter, theme gxui.Theme) {
l.Container.Init(outer, theme)
l.outer = outer
l.grid = make(map[gxui.Control]Cell)
// Interface compliance test
_ = gxui.TableLayout(l)
}
func (l *TableLayout) LayoutChildren() {
s := l.outer.Size().Contract(l.outer.Padding())
o := l.outer.Padding().LT()
cw, ch := s.W/l.columns, s.H/l.rows
var cr math.Rect
for _, c := range l.outer.Children() {
cm := c.Control.Margin()
cell := l.grid[c.Control]
x, y := cell.x*cw, cell.y*ch
w, h := x+cell.w*cw, y+cell.h*ch
cr = math.CreateRect(x+cm.L, y+cm.T, w-cm.R, h-cm.B)
c.Layout(cr.Offset(o).Canon())
}
}
func (l *TableLayout) DesiredSize(min, max math.Size) math.Size {
return max
}
func (l *TableLayout) SetGrid(columns, rows int) {
if l.columns != columns {
if l.columns > columns {
for c := l.columns; c > columns; c-- {
for _, cell := range l.grid {
if cell.AtColumn(c) {
panic("Can't remove column with cells")
}
}
l.columns--
}
} else {
l.columns = columns
}
}
if l.rows != rows {
if l.rows > rows {
for r := l.rows; r > rows; r-- {
for _, cell := range l.grid {
if cell.AtRow(r) {
panic("Can't remove row with cells")
}
}
l.rows--
}
} else {
l.rows = rows
}
}
if l.rows != rows || l.columns != columns {
l.LayoutChildren()
}
}
func (l *TableLayout) SetChildAt(x, y, w, h int, child gxui.Control) *gxui.Child {
if x+w > l.columns || y+h > l.rows {
panic("Cell is out of grid")
}
for _, c := range l.grid {
if c.x+c.w > x && c.x < x+w && c.y+c.h > y && c.y < y+h {
panic("Cell already has a child")
}
}
l.grid[child] = Cell{x, y, w, h}
return l.Container.AddChild(child)
}
func (l *TableLayout) RemoveChild(child gxui.Control) {
delete(l.grid, child)
l.Container.RemoveChild(child)
}