-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstyle.go
More file actions
221 lines (192 loc) · 6.93 KB
/
Copy pathstyle.go
File metadata and controls
221 lines (192 loc) · 6.93 KB
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package wui
// Color is a color value. In TUI it may be a hex string ("#ff0000"), a
// named ANSI color, or an ANSI index ("9"). In WASM it is passed through
// as CSS, with ANSI indices 0-15 translated to hex.
type Color string
// Fill, given as Style.Width or Style.Height, sizes an element to the
// full available space: the terminal in the TUI (minus the status bar
// row), the viewport in the browser. Intended for top-level layout
// containers — see Fullscreen, AppShell, Centered.
const Fill = -1
// Style holds presentation properties shared by both renderers.
// Width/Height are terminal cells in TUI and pixels in WASM.
//
// The zero Style is "no styling". Build styles by composition rather
// than by filling the struct literal by hand:
//
// wui.NewStyle().Bold().FG("6").Pad(1, 2)
type Style struct {
FG Color
BG Color
Bold bool
Italic bool
Underline bool
Faint bool
Strike bool
Padding [4]int // top, right, bottom, left
Margin [4]int // top, right, bottom, left
Width int // 0 = auto, Fill = all available width
Height int // 0 = auto, Fill = all available height
Border bool
BorderColor Color
Align Align // text alignment within Width; AlignStart = left
// Grow is the element's flex-grow share when it is a direct child
// of a Box: leftover space along the Box's axis is split between
// growing children in proportion to their Grow values. 0 = fixed.
Grow int
// MinWidth floors the element's width in cells. With Grow it sets
// the smallest acceptable size; in a wrapping Box it is the
// threshold below which the row collapses to a column.
MinWidth int
// MaxWidth caps the element's width in cells, so a Fill layout
// stops growing once it reaches its intended size instead of
// stretching across a very wide terminal. It also caps the width
// children see, so everything inside lays out against the cap
// rather than the screen. 0 = uncapped.
//
// Pair it with Align to place the capped block in the leftover
// space; Constrain is the ready-made centered version.
MaxWidth int
// MaxHeight caps the element's height in rows: the vertical
// counterpart of MaxWidth. 0 = uncapped.
MaxHeight int
// PlaceX positions a MaxWidth-capped element within the space it
// was given but did not use. It is distinct from Align, which
// positions content *inside* the element: a block can be centered
// on screen while its own text stays left-aligned. Ignored without
// MaxWidth. AlignStart (the default) keeps the block flush left.
PlaceX Align
}
// NewStyle returns the zero Style, as the head of a builder chain.
func NewStyle() Style { return Style{} }
// Bold returns a copy with bold set.
func (s Style) SetBold(v bool) Style { s.Bold = v; return s }
// Italic returns a copy with italic set.
func (s Style) SetItalic(v bool) Style { s.Italic = v; return s }
// Underline returns a copy with underline set.
func (s Style) SetUnderline(v bool) Style { s.Underline = v; return s }
// Faint returns a copy with faint (dim) set.
func (s Style) SetFaint(v bool) Style { s.Faint = v; return s }
// Strike returns a copy with strikethrough set.
func (s Style) SetStrike(v bool) Style { s.Strike = v; return s }
// Fg returns a copy with the foreground color set.
func (s Style) Fg(c Color) Style { s.FG = c; return s }
// Bg returns a copy with the background color set.
func (s Style) Bg(c Color) Style { s.BG = c; return s }
// Pad returns a copy with padding set CSS-style: one value applies to
// all sides, two are vertical/horizontal, three are top/horizontal/
// bottom, four are top/right/bottom/left. Other counts are ignored.
func (s Style) Pad(v ...int) Style {
if box, ok := boxValues(v); ok {
s.Padding = box
}
return s
}
// Mar returns a copy with margin set, using the same shorthand rules as
// Pad.
func (s Style) Mar(v ...int) Style {
if box, ok := boxValues(v); ok {
s.Margin = box
}
return s
}
// W returns a copy with the width set. Pass Fill for all available
// width.
func (s Style) W(n int) Style { s.Width = n; return s }
// H returns a copy with the height set. Pass Fill for all available
// height.
func (s Style) H(n int) Style { s.Height = n; return s }
// Grown returns a copy with the flex-grow share set. It only has an
// effect on direct children of a Box.
func (s Style) Grown(n int) Style { s.Grow = n; return s }
// MinW returns a copy with the minimum width set.
func (s Style) MinW(n int) Style { s.MinWidth = n; return s }
// MaxW returns a copy with the maximum width set: the element stops
// growing at n cells however wide the terminal is.
func (s Style) MaxW(n int) Style { s.MaxWidth = n; return s }
// MaxH returns a copy with the maximum height set.
func (s Style) MaxH(n int) Style { s.MaxHeight = n; return s }
// PlacedX returns a copy with the placement of a MaxWidth-capped
// element within its leftover space set.
func (s Style) PlacedX(a Align) Style { s.PlaceX = a; return s }
// Bordered returns a copy with a border in the given color. Pass "" to
// use the current foreground color.
func (s Style) Bordered(c Color) Style {
s.Border = true
s.BorderColor = c
return s
}
// Aligned returns a copy with text alignment set. It positions content
// inside the style's Width, so it has no visible effect without one.
func (s Style) Aligned(a Align) Style { s.Align = a; return s }
// Merge returns a copy of s with every non-zero field of other applied
// on top. Use it to layer a variant over a base style:
//
// danger := base.Merge(wui.Style{FG: "9", Bold: true})
//
// Boolean attributes are additive — Merge can set them but never clears
// one already set in s.
func (s Style) Merge(other Style) Style {
if other.FG != "" {
s.FG = other.FG
}
if other.BG != "" {
s.BG = other.BG
}
s.Bold = s.Bold || other.Bold
s.Italic = s.Italic || other.Italic
s.Underline = s.Underline || other.Underline
s.Faint = s.Faint || other.Faint
s.Strike = s.Strike || other.Strike
if other.Padding != [4]int{} {
s.Padding = other.Padding
}
if other.Margin != [4]int{} {
s.Margin = other.Margin
}
if other.Width != 0 {
s.Width = other.Width
}
if other.Height != 0 {
s.Height = other.Height
}
if other.Border {
s.Border = true
}
if other.BorderColor != "" {
s.BorderColor = other.BorderColor
}
if other.Align != AlignStart {
s.Align = other.Align
}
if other.Grow != 0 {
s.Grow = other.Grow
}
if other.MinWidth != 0 {
s.MinWidth = other.MinWidth
}
if other.MaxWidth != 0 {
s.MaxWidth = other.MaxWidth
}
if other.MaxHeight != 0 {
s.MaxHeight = other.MaxHeight
}
if other.PlaceX != AlignStart {
s.PlaceX = other.PlaceX
}
return s
}
// boxValues expands CSS-style shorthand into top/right/bottom/left.
func boxValues(v []int) ([4]int, bool) {
switch len(v) {
case 1:
return [4]int{v[0], v[0], v[0], v[0]}, true
case 2:
return [4]int{v[0], v[1], v[0], v[1]}, true
case 3:
return [4]int{v[0], v[1], v[2], v[1]}, true
case 4:
return [4]int{v[0], v[1], v[2], v[3]}, true
}
return [4]int{}, false
}