-
Notifications
You must be signed in to change notification settings - Fork 0
/
group.go
107 lines (98 loc) · 2.44 KB
/
group.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
package uidoc
import (
"fmt"
"github.com/andlabs/ui"
)
type layout struct {
e Element
x, y, w, h float64
path *ui.Path
}
type Group struct {
layouts []layout
ElementBase
}
func NewGroup(elements []Element) *Group {
g := &Group{layouts: make([]layout, len(elements))}
for i, e := range elements {
g.layouts[i] = layout{e: e}
}
return g
}
func max(a, b float64) float64 {
if a > b {
return a
}
return b
}
func (g *Group) Layout(width float64) (w float64, h float64) {
groupLeft := g.MarginLeft + g.PaddingLeft
groupRight := width - g.MarginRight - g.PaddingRight
x := groupLeft
y := g.MarginTop + g.PaddingTop
lineHeight := 0.0
for i, l := range g.layouts {
mTop, mRight, mBottom, mLeft := l.e.Margins()
pTop, pRight, pBottom, pLeft := l.e.Padding()
l.y = y + mTop + pTop
l.x = x + mLeft + pLeft
l.w, l.h = l.e.Layout(groupRight - x - mRight - pRight)
lineHeight = max(lineHeight, l.h+mBottom+pBottom+mTop+pTop)
w = max(w, x+l.w+mRight+pRight)
switch l.e.Mode() {
case LayoutBlock:
x = groupLeft
y += lineHeight
lineHeight = 0
case LayoutInline:
eleWidth := l.w + mRight + pRight + mLeft + mRight
if x+eleWidth > groupRight {
// It's overflowing, reflow it below
x = groupLeft
y += lineHeight
lineHeight = 0
l.y = y + mTop + pTop
l.x = x + mLeft + pLeft
l.w, l.h = l.e.Layout(groupRight - x - mRight - pRight)
lineHeight = max(lineHeight, l.h+mBottom+pBottom+mTop+pTop)
w = max(w, x+l.w+mRight+pRight)
eleWidth = l.w + mRight + pRight + mLeft + mRight
x += eleWidth
} else {
x += eleWidth
}
default:
panic(fmt.Errorf("Invlalid LayoutMode %v", l.e.Mode()))
}
g.layouts[i] = l
}
h = y + lineHeight
return
}
func (g *Group) Render(dp *ui.AreaDrawParams, x, y float64) {
for _, l := range g.layouts {
if b := l.e.Fill(); b != nil {
l.path = ui.NewPath(ui.Winding)
pTop, pRight, pBottom, pLeft := l.e.Padding()
l.path.AddRectangle(x+l.x-pLeft, y+l.y-pTop, l.w+pLeft+pRight, l.h+pTop+pBottom)
l.path.End()
dp.Context.Fill(l.path, l.e.Fill())
if stroke, thickness := l.e.Stroke(); stroke != nil {
dp.Context.Stroke(l.path, stroke, &ui.StrokeParams{Thickness: thickness})
}
}
l.e.Render(dp, x+l.x, y+l.y)
}
}
func (g *Group) Free() {
for _, l := range g.layouts {
if l.path != nil {
l.path.Free()
}
l.e.Free()
}
g.layouts = nil
}
func (g *Group) Append(e Element) {
g.layouts = append(g.layouts, layout{e: e})
}