Skip to content
This repository was archived by the owner on Sep 24, 2022. It is now read-only.

Commit e285184

Browse files
authored
Render button on the screen (#67)
* Simplify UI lib APIs * Add Text element for UI lib * Add button element * Remove margin * Fix button width bug
1 parent d104b81 commit e285184

15 files changed

+336
-54
lines changed

ui/background.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package ui
2+
3+
import (
4+
"image/draw"
5+
)
6+
7+
type Background struct {
8+
Color *Color
9+
}
10+
11+
func (b Background) Paint(painter *Painter, destLayer draw.Image) {
12+
if b.Color != nil {
13+
painter.fillColor(destLayer, *b.Color)
14+
}
15+
}

ui/box.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import (
44
"image"
55
"image/draw"
66
"sort"
7-
)
87

9-
type BoxProps struct {
10-
}
8+
"candy/ui/ptr"
9+
)
1110

1211
var _ Component = (*Box)(nil)
1312

1413
type Box struct {
1514
SharedComponent
16-
props BoxProps
15+
}
16+
17+
func (b Box) GetName() string {
18+
return "Box"
1719
}
1820

1921
func (b Box) Paint(painter *Painter, destLayer draw.Image, offset Offset) {
@@ -23,6 +25,9 @@ func (b Box) Paint(painter *Painter, destLayer draw.Image, offset Offset) {
2325
Y: b.size.height,
2426
},
2527
})
28+
if b.style.Background != nil {
29+
b.style.Background.Paint(painter, contentLayer)
30+
}
2631

2732
sortedChildren := Children{
2833
children: b.children,
@@ -45,33 +50,36 @@ func (b Box) Paint(painter *Painter, destLayer draw.Image, offset Offset) {
4550
}
4651

4752
func (b Box) ComputeLeafSize(_ Constraints) Size {
53+
padding := b.style.GetPadding()
54+
4855
width := 0
4956
if b.style.Width != nil {
5057
width = *b.style.Width
5158
}
59+
width += padding.GetLeft() + padding.GetRight()
5260
height := 0
5361
if b.style.Height != nil {
5462
height = *b.style.Height
5563
}
64+
height += padding.GetTop() + padding.GetBottom()
5665
return Size{width: width, height: height}
5766
}
5867

59-
func NewBox(props *BoxProps, children []Component, style *Style) *Box {
60-
if props == nil {
61-
props = &BoxProps{}
62-
}
68+
func NewBox(children []Component, style *Style) *Box {
6369
if style == nil {
6470
style = &Style{
65-
LayoutType: BoxLayoutType,
71+
LayoutType: (*LayoutType)(ptr.Int(int(BoxLayoutType))),
6672
}
6773
}
74+
if style.LayoutType == nil {
75+
style.LayoutType = (*LayoutType)(ptr.Int(int(BoxLayoutType)))
76+
}
6877
if children == nil {
6978
children = make([]Component, 0)
7079
}
7180
return &Box{
72-
props: *props,
7381
SharedComponent: SharedComponent{
74-
layout: newLayout(style.LayoutType),
82+
layout: newLayout(*style.LayoutType),
7583
style: *style,
7684
children: children,
7785
childrenOffset: []Offset{},

ui/box_layout.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,18 @@ type BoxLayout struct {
1111

1212
func (b BoxLayout) applyConstraintsToChildren(parent Component, parentConstraints Constraints) {
1313
parentConstraints.maxHeight = math.MaxInt64
14+
parentConstraints.minWidth = parentConstraints.maxWidth
1415

1516
for _, child := range parent.getChildren() {
1617
applyConstraints(child, parentConstraints)
1718
}
1819
}
1920

2021
func (b BoxLayout) computeChildrenOffset(parent Component) []Offset {
21-
nextX := 0
22-
nextY := 0
22+
padding := parent.getStyle().GetPadding()
23+
24+
nextX := padding.GetLeft()
25+
nextY := padding.GetTop()
2326

2427
offsets := make([]Offset, 0)
2528
for _, child := range parent.getChildren() {

ui/button.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package ui
2+
3+
import (
4+
"image/draw"
5+
6+
"candy/ui/ptr"
7+
)
8+
9+
type ButtonProps struct {
10+
Text *string
11+
}
12+
13+
func (b ButtonProps) getText() string {
14+
if b.Text == nil {
15+
return ""
16+
} else {
17+
return *b.Text
18+
}
19+
}
20+
21+
var _ Component = (*Button)(nil)
22+
23+
type Button struct {
24+
SharedComponent
25+
}
26+
27+
func (b Button) GetName() string {
28+
return "Button"
29+
}
30+
31+
func (b Button) Paint(painter *Painter, destLayer draw.Image, offset Offset) {
32+
b.children[0].Paint(painter, destLayer, offset)
33+
}
34+
35+
func NewButton(props *ButtonProps, style *Style) *Button {
36+
if props == nil {
37+
props = &ButtonProps{}
38+
}
39+
if style == nil {
40+
style = &Style{
41+
LayoutType: (*LayoutType)(ptr.Int(int(InlineLayoutType))),
42+
}
43+
}
44+
if style.LayoutType == nil {
45+
style.LayoutType = (*LayoutType)(ptr.Int(int(InlineLayoutType)))
46+
}
47+
if style.Background == nil {
48+
style.Background = &Background{Color: &Color{
49+
Red: 87,
50+
Green: 37,
51+
Blue: 229,
52+
Alpha: 255,
53+
}}
54+
}
55+
if style.Padding == nil {
56+
style.Padding = &EdgeSpacing{
57+
Top: ptr.Int(6),
58+
Bottom: ptr.Int(6),
59+
Left: ptr.Int(20),
60+
Right: ptr.Int(20),
61+
}
62+
}
63+
return &Button{
64+
SharedComponent: SharedComponent{
65+
layout: newLayout(InlineLayoutType),
66+
children: []Component{
67+
NewBox([]Component{
68+
NewText(&TextProps{Text: props.getText()}, style),
69+
}, style),
70+
},
71+
childrenOffset: make([]Offset, 0),
72+
},
73+
}
74+
}

ui/component.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import (
88
)
99

1010
type Component interface {
11+
GetName() string
1112
HandleInput(in input.Input)
1213
Update(timeElapsed time.Duration)
1314
getLayout() layout
1415
getChildren() []Component
1516
ComputeLeafSize(constraints Constraints) Size
1617
getSize() Size
1718
setSize(size Size)
19+
getStyle() Style
1820
getChildrenOffset() []Offset
1921
setChildrenOffset(childrenOffsets []Offset)
2022
Paint(painter *Painter, destLayer draw.Image, offset Offset)
@@ -39,7 +41,7 @@ type SharedComponent struct {
3941
children []Component
4042
}
4143

42-
func (s SharedComponent) HandleInput(in input.Input) {
44+
func (s SharedComponent) HandleInput(_ input.Input) {
4345
return
4446
}
4547

@@ -69,6 +71,10 @@ func (s *SharedComponent) setSize(size Size) {
6971
s.size = size
7072
}
7173

74+
func (s SharedComponent) getStyle() Style {
75+
return s.style
76+
}
77+
7278
func (s *SharedComponent) setChildrenOffset(childrenOffsets []Offset) {
7379
s.childrenOffset = childrenOffsets
7480
}

ui/constraint.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ func applyConstraints(component Component, constraints Constraints) {
2121
component.setSize(component.ComputeLeafSize(constraints))
2222
return
2323
}
24-
2524
layout := component.getLayout()
2625
layout.applyConstraintsToChildren(component, constraints)
2726
component.setChildrenOffset(layout.computeChildrenOffset(component))

ui/edgespacing.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package ui
2+
3+
type EdgeSpacing struct {
4+
All *int
5+
Top *int
6+
Bottom *int
7+
Left *int
8+
Right *int
9+
}
10+
11+
func (e EdgeSpacing) GetTop() int {
12+
if e.Top != nil {
13+
return *e.Top
14+
} else if e.All != nil {
15+
return *e.All
16+
} else {
17+
return 0
18+
}
19+
}
20+
21+
func (e EdgeSpacing) GetBottom() int {
22+
if e.Bottom != nil {
23+
return *e.Bottom
24+
} else if e.All != nil {
25+
return *e.All
26+
} else {
27+
return 0
28+
}
29+
}
30+
31+
func (e EdgeSpacing) GetLeft() int {
32+
if e.Left != nil {
33+
return *e.Left
34+
} else if e.All != nil {
35+
return *e.All
36+
} else {
37+
return 0
38+
}
39+
}
40+
41+
func (e EdgeSpacing) GetRight() int {
42+
if e.Right != nil {
43+
return *e.Right
44+
} else if e.All != nil {
45+
return *e.All
46+
} else {
47+
return 0
48+
}
49+
}

ui/example/app.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"candy/assets"
55
"candy/ui"
6+
"candy/ui/ptr"
67
)
78

89
var _ ui.Component = (*app)(nil)
@@ -12,7 +13,11 @@ type app struct {
1213
}
1314

1415
func newApp(assets *assets.Assets) *app {
15-
return &app{ui.NewBox(nil, []ui.Component{
16+
return &app{ui.NewBox([]ui.Component{
17+
ui.NewButton(
18+
&ui.ButtonProps{Text: ptr.String("Click")},
19+
nil,
20+
),
1621
ui.NewText(&ui.TextProps{Text: `
1722
I guess we could discuss the implications of the phrase "meant to be."
1823
That is if we wanted to drown ourselves in a sea of backwardly referential
@@ -22,12 +27,12 @@ seems to be, and that none of us is actually meant to be doing anything at all.
2227
But that's my existential underpants underpinnings showing. It's the way the
2328
cookie crumbles. And now I want a cookie.
2429
`}, &ui.Style{FontStyle: ui.FontStyle{
25-
Family: "Source Code Pro",
26-
Weight: "ExtraLight",
27-
Italic: false,
28-
Size: 20,
29-
LineHeight: 24,
30-
Color: ui.Color{
30+
Family: ptr.String("Source Code Pro"),
31+
Weight: ptr.String("ExtraLight"),
32+
Italic: ptr.Bool(false),
33+
Size: ptr.Int(20),
34+
LineHeight: ptr.Int(24),
35+
Color: &ui.Color{
3136
Red: 255,
3237
Green: 255,
3338
Blue: 255,

ui/image.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ type Image struct {
2020
image image.Image
2121
}
2222

23+
func (i *Image) GetName() string {
24+
return "Image"
25+
}
26+
2327
func (i *Image) Paint(painter *Painter, destLayer draw.Image, offset Offset) {
2428
if i.image == nil {
2529
return

ui/inline_layout.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package ui
2+
3+
import (
4+
"math"
5+
)
6+
7+
var _ layout = (*InlineLayout)(nil)
8+
9+
type InlineLayout struct {
10+
BoxLayout
11+
}
12+
13+
func (b InlineLayout) applyConstraintsToChildren(parent Component, parentConstraints Constraints) {
14+
parentConstraints.maxHeight = math.MaxInt64
15+
16+
style := parent.getStyle()
17+
18+
if style.Width != nil {
19+
parentConstraints.maxWidth = *style.Width
20+
}
21+
22+
for _, child := range parent.getChildren() {
23+
applyConstraints(child, parentConstraints)
24+
}
25+
}
26+
27+
func (b InlineLayout) computeParentSize(parent Component, parentConstraints Constraints) Size {
28+
height := 0
29+
children := parent.getChildren()
30+
length := len(children)
31+
32+
if length > 0 {
33+
childrenOffset := parent.getChildrenOffset()
34+
height = childrenOffset[length-1].y + children[length-1].getSize().height
35+
}
36+
style := parent.getStyle()
37+
38+
width := 0.0
39+
if style.Width != nil {
40+
width = float64(*style.Width)
41+
} else {
42+
for _, child := range children {
43+
width = math.Max(width, float64(child.getSize().width))
44+
}
45+
}
46+
padding := parent.getStyle().GetPadding()
47+
fullWidth := int(width) + padding.GetLeft() + padding.GetRight()
48+
fullHeight := height + padding.GetBottom()
49+
return Size{width: fullWidth, height: fullHeight}
50+
}

0 commit comments

Comments
 (0)