-
Notifications
You must be signed in to change notification settings - Fork 1
/
label.go
148 lines (125 loc) · 3.03 KB
/
label.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package ui
import (
"fmt"
"strings"
"git.kirsle.net/go/render"
"git.kirsle.net/go/ui/style"
)
// DefaultFont is the default font settings used for a Label.
var DefaultFont = render.Text{
Size: 12,
Color: render.Black,
}
// Label is a simple text label widget.
type Label struct {
BaseWidget
// Configurable fields for the constructor.
Text string
TextVariable *string
IntVariable *int
Font render.Text
style *style.Label
width int
height int
lineHeight int
}
// NewLabel creates a new label.
func NewLabel(c Label) *Label {
w := &Label{
Text: c.Text,
TextVariable: c.TextVariable,
IntVariable: c.IntVariable,
Font: DefaultFont,
}
w.SetStyle(Theme.Label)
if !c.Font.IsZero() {
w.Font = c.Font
}
w.IDFunc(func() string {
return fmt.Sprintf(`Label<"%s">`, w.text().Text)
})
return w
}
// SetStyle sets the label's default style.
func (w *Label) SetStyle(v *style.Label) {
if v == nil {
v = &style.DefaultLabel
}
w.style = v
w.SetBackground(w.style.Background)
w.Font.Color = w.style.Foreground
}
// text returns the label's displayed text, coming from the TextVariable if
// available or else the Text attribute instead.
func (w *Label) text() render.Text {
if w.TextVariable != nil {
w.Font.Text = *w.TextVariable
return w.Font
} else if w.IntVariable != nil {
w.Font.Text = fmt.Sprintf("%d", *w.IntVariable)
return w.Font
}
w.Font.Text = w.Text
return w.Font
}
// Value returns the current text value displayed in the widget, whether it was
// the hardcoded value or a TextVariable.
func (w *Label) Value() string {
return w.text().Text
}
// Compute the size of the label widget.
func (w *Label) Compute(e render.Engine) {
text := w.text()
lines := strings.Split(text.Text, "\n")
// Max rect to encompass all lines of text.
var maxRect = render.Rect{}
for _, line := range lines {
if line == "" {
line = "<empty>"
}
text.Text = line // only this line at this time.
rect, err := e.ComputeTextRect(text)
if err != nil {
panic(fmt.Sprintf("%s: failed to compute text rect: %s", w, err)) // TODO return an error
}
if rect.W > maxRect.W {
maxRect.W = rect.W
}
maxRect.H += rect.H
w.lineHeight = int(rect.H)
}
var (
padX = w.Font.Padding + w.Font.PadX
padY = w.Font.Padding + w.Font.PadY
)
if !w.FixedSize() {
w.ResizeAuto(render.Rect{
W: maxRect.W + (padX * 2),
H: maxRect.H + (padY * 2),
})
}
// Call the BaseWidget Compute in case we have subscribers.
w.BaseWidget.Compute(e)
}
// Present the label widget.
func (w *Label) Present(e render.Engine, P render.Point) {
if w.Hidden() {
return
}
border := w.BoxThickness(1)
var (
text = w.text()
padX = w.Font.Padding + w.Font.PadX
padY = w.Font.Padding + w.Font.PadY
)
w.DrawBox(e, P)
for i, line := range strings.Split(text.Text, "\n") {
text.Text = line
e.DrawText(text, render.Point{
X: P.X + border + padX,
Y: P.Y + border + padY + (i * w.lineHeight),
})
}
// Call the BaseWidget Present in case we have subscribers.
w.BaseWidget.Present(e, P)
}