-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathframe_place.go
111 lines (97 loc) · 2.79 KB
/
frame_place.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
package ui
import (
"git.kirsle.net/go/render"
)
// Place provides configuration fields for Frame.Place().
type Place struct {
// X and Y coordinates for explicit location of widget within its parent.
// This placement option trumps all others.
Point render.Point
// Place relative to an edge of the window. The widget will stick to the
// edge of the window even as it resizes. Options are ignored if Point
// is set.
Top int
Left int
Right int
Bottom int
Center bool
Middle bool
}
// Strategy returns the placement strategy for a Place config struct.
// Returns 'Point' if a render.Point is used (even if zero, zero)
// Returns 'Side' if the side values are set.
func (p Place) Strategy() string {
if p.Top != 0 || p.Left != 0 || p.Right != 0 || p.Bottom != 0 || p.Center || p.Middle {
return "Side"
}
return "Point"
}
// placedWidget holds the data for a widget placed in a frame.
type placedWidget struct {
widget Widget
place Place
}
// Place a widget into the frame. You may call Place on a widget multiple times to update its configuration.
func (w *Frame) Place(child Widget, config Place) {
// Update an already placed widget.
for _, current := range w.placed {
if current.widget == child {
current.place = config
return
}
}
// Append it.
w.placed = append(w.placed, &placedWidget{
widget: child,
place: config,
})
w.Add(child)
// Adopt the child widget so it can access the Frame.
child.SetParent(w)
}
// computePlaced processes all the Place layout widgets in the Frame,
// determining their X,Y location and whether they need to change.
func (w *Frame) computePlaced(e render.Engine) {
var (
frameSize = w.BoxSize()
// maxWidth int
// maxHeight int
)
for _, row := range w.placed {
// X,Y placement takes priority.
switch row.place.Strategy() {
case "Point":
row.widget.MoveTo(row.place.Point)
row.widget.Compute(e)
case "Side":
var moveTo render.Point
// Compute the initial X,Y based on Top, Left, Right, Bottom.
if row.place.Left > 0 {
moveTo.X = row.place.Left
}
if row.place.Top > 0 {
moveTo.Y = row.place.Top
}
if row.place.Right > 0 {
moveTo.X = frameSize.W - row.widget.Size().W - row.place.Right
}
if row.place.Bottom > 0 {
moveTo.Y = frameSize.H - row.widget.Size().H - row.place.Bottom
}
// Center and Middle aligned values override Left/Right, Top/Bottom
// settings respectively.
if row.place.Center {
moveTo.X = frameSize.W - (w.Size().W / 2) - (row.widget.Size().W / 2)
}
if row.place.Middle {
moveTo.Y = frameSize.H - (w.Size().H / 2) - (row.widget.Size().H / 2)
}
row.widget.MoveTo(moveTo)
row.widget.Compute(e)
}
// If this widget itself has placed widgets, call its function too.
if frame, ok := row.widget.(*Frame); ok {
frame.computePlaced(e)
}
}
}