-
Notifications
You must be signed in to change notification settings - Fork 103
/
box.go
105 lines (92 loc) · 2.17 KB
/
box.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
package render
import (
"image"
"image/color"
"github.com/tidbyt/gg"
)
// A Box is a rectangular widget that can hold a child widget.
//
// Boxes are transparent unless `color` is provided. They expand to
// fill all available space, unless `width` and/or `height` is
// provided. Boxes can have a `child`, which will be centered in the
// box, and the child can be padded (via `padding`).
//
// DOC(Child): Child to center inside box
// DOC(Width): Limits Box width
// DOC(Height): Limits Box height
// DOC(Padding): Padding around the child widget
// DOC(Color): Background color
//
// EXAMPLE BEGIN
// render.Box(
// color="#00f",
// child=render.Box(
// width=20,
// height=10,
// color="#f00",
// )
// )
// EXAMPLE END
type Box struct {
Widget
Child Widget
Width, Height int
Padding int
Color color.Color
}
func (b Box) PaintBounds(bounds image.Rectangle, frameIdx int) image.Rectangle {
w, h := b.Width, b.Height
if w == 0 {
w = bounds.Dx()
}
if h == 0 {
h = bounds.Dy()
}
return image.Rect(0, 0, w, h)
}
func (b Box) Paint(dc *gg.Context, bounds image.Rectangle, frameIdx int) {
w, h := b.Width, b.Height
if w == 0 {
w = bounds.Dx()
}
if h == 0 {
h = bounds.Dy()
}
if b.Color != nil {
dc.SetColor(b.Color)
dc.DrawRectangle(0, 0, float64(w), float64(h))
dc.Fill()
}
if b.Child != nil {
chW := w - b.Padding*2
chH := h - b.Padding*2
if chW < 0 || chH < 0 {
// padding makes the child invisible, no point painting it
} else {
dc.Push()
dc.DrawRectangle(
float64(b.Padding),
float64(b.Padding),
float64(chW),
float64(chH),
)
dc.Clip()
childBounds := b.Child.PaintBounds(image.Rect(0, 0, chW, chH), frameIdx)
// This is a bit convoluted to obtain the same rounding behavior as with the old
// local-context rendering
x := w / 2
y := h / 2
x -= int(0.5 * float64(childBounds.Size().X))
y -= int(0.5 * float64(childBounds.Size().Y))
dc.Translate(float64(x), float64(y))
b.Child.Paint(dc, image.Rect(0, 0, chW, chH), frameIdx)
dc.Pop()
}
}
}
func (b Box) FrameCount() int {
if b.Child != nil {
return b.Child.FrameCount()
}
return 1
}