1package uv
2
3// NormalBorder returns a standard-type border with a normal weight and 90
4// degree corners.
5func NormalBorder() Border {
6 return Border{
7 Top: Side{Content: "─"},
8 Bottom: Side{Content: "─"},
9 Left: Side{Content: "│"},
10 Right: Side{Content: "│"},
11 TopLeft: Side{Content: "┌"},
12 TopRight: Side{Content: "┐"},
13 BottomLeft: Side{Content: "└"},
14 BottomRight: Side{Content: "┘"},
15 }
16}
17
18// RoundedBorder returns a border with rounded corners.
19func RoundedBorder() Border {
20 return Border{
21 Top: Side{Content: "─"},
22 Bottom: Side{Content: "─"},
23 Left: Side{Content: "│"},
24 Right: Side{Content: "│"},
25 TopLeft: Side{Content: "╭"},
26 TopRight: Side{Content: "╮"},
27 BottomLeft: Side{Content: "╰"},
28 BottomRight: Side{Content: "╯"},
29 }
30}
31
32// BlockBorder returns a border that takes the whole block.
33func BlockBorder() Border {
34 return Border{
35 Top: Side{Content: "█"},
36 Bottom: Side{Content: "█"},
37 Left: Side{Content: "█"},
38 Right: Side{Content: "█"},
39 TopLeft: Side{Content: "█"},
40 TopRight: Side{Content: "█"},
41 BottomLeft: Side{Content: "█"},
42 BottomRight: Side{Content: "█"},
43 }
44}
45
46// OuterHalfBlockBorder returns a half-block border that sits outside the frame.
47func OuterHalfBlockBorder() Border {
48 return Border{
49 Top: Side{Content: "▀"},
50 Bottom: Side{Content: "▄"},
51 Left: Side{Content: "▌"},
52 Right: Side{Content: "▐"},
53 TopLeft: Side{Content: "▛"},
54 TopRight: Side{Content: "▜"},
55 BottomLeft: Side{Content: "▙"},
56 BottomRight: Side{Content: "▟"},
57 }
58}
59
60// InnerHalfBlockBorder returns a half-block border that sits inside the frame.
61func InnerHalfBlockBorder() Border {
62 return Border{
63 Top: Side{Content: "▄"},
64 Bottom: Side{Content: "▀"},
65 Left: Side{Content: "▐"},
66 Right: Side{Content: "▌"},
67 TopLeft: Side{Content: "▗"},
68 TopRight: Side{Content: "▖"},
69 BottomLeft: Side{Content: "▝"},
70 BottomRight: Side{Content: "▘"},
71 }
72}
73
74// ThickBorder returns a border that's thicker than the one returned by
75// NormalBorder.
76func ThickBorder() Border {
77 return Border{
78 Top: Side{Content: "━"},
79 Bottom: Side{Content: "━"},
80 Left: Side{Content: "┃"},
81 Right: Side{Content: "┃"},
82 TopLeft: Side{Content: "┏"},
83 TopRight: Side{Content: "┓"},
84 BottomLeft: Side{Content: "┗"},
85 BottomRight: Side{Content: "┛"},
86 }
87}
88
89// DoubleBorder returns a border comprised of two thin strokes.
90func DoubleBorder() Border {
91 return Border{
92 Top: Side{Content: "═"},
93 Bottom: Side{Content: "═"},
94 Left: Side{Content: "║"},
95 Right: Side{Content: "║"},
96 TopLeft: Side{Content: "╔"},
97 TopRight: Side{Content: "╗"},
98 BottomLeft: Side{Content: "╚"},
99 BottomRight: Side{Content: "╝"},
100 }
101}
102
103// HiddenBorder returns a border that renders as a series of single-cell
104// spaces. It's useful for cases when you want to remove a standard border but
105// maintain layout positioning. This said, you can still apply a background
106// color to a hidden border.
107func HiddenBorder() Border {
108 return Border{
109 Top: Side{Content: " "},
110 Bottom: Side{Content: " "},
111 Left: Side{Content: " "},
112 Right: Side{Content: " "},
113 TopLeft: Side{Content: " "},
114 TopRight: Side{Content: " "},
115 BottomLeft: Side{Content: " "},
116 BottomRight: Side{Content: " "},
117 }
118}
119
120// MarkdownBorder return a table border in markdown style.
121func MarkdownBorder() Border {
122 return Border{
123 Left: Side{Content: "|"},
124 Right: Side{Content: "|"},
125 TopLeft: Side{Content: "|"},
126 TopRight: Side{Content: "|"},
127 BottomLeft: Side{Content: "|"},
128 BottomRight: Side{Content: "|"},
129 }
130}
131
132// ASCIIBorder returns a table border with ASCII characters.
133func ASCIIBorder() Border {
134 return Border{
135 Top: Side{Content: "-"},
136 Bottom: Side{Content: "-"},
137 Left: Side{Content: "|"},
138 Right: Side{Content: "|"},
139 TopLeft: Side{Content: "+"},
140 TopRight: Side{Content: "+"},
141 BottomLeft: Side{Content: "+"},
142 BottomRight: Side{Content: "+"},
143 }
144}
145
146// Side represents a single border side with its properties.
147type Side struct {
148 Content string
149 Style
150 Link
151}
152
153// Border represents a border with its properties.
154type Border struct {
155 Top Side
156 Bottom Side
157 Left Side
158 Right Side
159 TopLeft Side
160 TopRight Side
161 BottomLeft Side
162 BottomRight Side
163}
164
165// Style returns a new [Border] with the given style applied to all [Side]s.
166func (b Border) Style(style Style) Border {
167 b.Top.Style = style
168 b.Bottom.Style = style
169 b.Left.Style = style
170 b.Right.Style = style
171 b.TopLeft.Style = style
172 b.TopRight.Style = style
173 b.BottomLeft.Style = style
174 b.BottomRight.Style = style
175 return b
176}
177
178// Link returns a new [Border] with the given link applied to all [Side]s.
179func (b Border) Link(link Link) Border {
180 b.Top.Link = link
181 b.Bottom.Link = link
182 b.Left.Link = link
183 b.Right.Link = link
184 b.TopLeft.Link = link
185 b.TopRight.Link = link
186 b.BottomLeft.Link = link
187 b.BottomRight.Link = link
188 return b
189}
190
191// Draw draws the border around the given component.
192func (b *Border) Draw(scr Screen, area Rectangle) {
193 for y := area.Min.Y; y < area.Max.Y; y++ {
194 for x := area.Min.X; x < area.Max.X; x++ {
195 var cell *Cell
196 switch {
197 case y == area.Min.Y && x == area.Min.X:
198 cell = borderCell(scr, &b.TopLeft)
199 case y == area.Min.Y && x == area.Max.X-1:
200 cell = borderCell(scr, &b.TopRight)
201 case y == area.Max.Y-1 && x == area.Min.X:
202 cell = borderCell(scr, &b.BottomLeft)
203 case y == area.Max.Y-1 && x == area.Max.X-1:
204 cell = borderCell(scr, &b.BottomRight)
205 case y == area.Min.Y:
206 cell = borderCell(scr, &b.Top)
207 case y == area.Max.Y-1:
208 cell = borderCell(scr, &b.Bottom)
209 case x == area.Min.X:
210 cell = borderCell(scr, &b.Left)
211 case x == area.Max.X-1:
212 cell = borderCell(scr, &b.Right)
213 default:
214 continue
215 }
216 if cell == nil {
217 continue
218 }
219 scr.SetCell(x, y, cell)
220 }
221 }
222}
223
224func borderCell(scr Screen, b *Side) *Cell {
225 c := NewCell(scr.WidthMethod(), b.Content)
226 if c != nil {
227 c.Style = b.Style
228 c.Link = b.Link
229 }
230 return c
231}