Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

box.gno

2.23 Kb · 69 lines
 1package art
 2
 3// BoxStyle is the six runes a rectangular border needs.
 4type BoxStyle struct {
 5	TL, TR, BL, BR rune
 6	H, V           rune
 7}
 8
 9// The border styles worth having. ASCII is the one that survives a consumer
10// with no Unicode: everything else here is box-drawing, which is fine in a
11// terminal and in a markdown code fence but not in, say, a plain-ASCII log.
12var (
13	Light  = BoxStyle{TL: '┌', TR: '┐', BL: '└', BR: '┘', H: '─', V: '│'}
14	Heavy  = BoxStyle{TL: '┏', TR: '┓', BL: '┗', BR: '┛', H: '━', V: '┃'}
15	Double = BoxStyle{TL: '╔', TR: '╗', BL: '╚', BR: '╝', H: '═', V: '║'}
16	Round  = BoxStyle{TL: '╭', TR: '╮', BL: '╰', BR: '╯', H: '─', V: '│'}
17	ASCII  = BoxStyle{TL: '+', TR: '+', BL: '+', BR: '+', H: '-', V: '|'}
18)
19
20// Box draws a w by h border in the pen's colours, leaving the interior
21// untouched. w or h under 2 draws nothing: there is no border with no inside.
22func (c *Canvas) Box(x, y, w, h int, s BoxStyle) {
23	if w < 2 || h < 2 {
24		return
25	}
26	c.HLine(x+1, y, w-2, s.H)
27	c.HLine(x+1, y+h-1, w-2, s.H)
28	c.VLine(x, y+1, h-2, s.V)
29	c.VLine(x+w-1, y+1, h-2, s.V)
30	c.Put(x, y, s.TL)
31	c.Put(x+w-1, y, s.TR)
32	c.Put(x, y+h-1, s.BL)
33	c.Put(x+w-1, y+h-1, s.BR)
34}
35
36// Frame returns a NEW canvas two cells wider and taller than c, with c blitted
37// into the middle and a border around it. A non-empty title is written into the
38// top edge starting two cells in, and is truncated rather than allowed to run
39// over the corner.
40//
41// It returns a new canvas rather than growing this one because a Canvas has a
42// fixed size by design: every index in this package is computed from W, and a
43// resize in place would invalidate any offset a caller was holding.
44func (c *Canvas) Frame(title string, s BoxStyle) *Canvas {
45	out := NewCanvas(c.W+2, c.H+2)
46	out.FG, out.BG = c.FG, c.BG
47	out.Box(0, 0, out.W, out.H, s)
48	out.Blit(1, 1, c)
49	if title != "" {
50		// The top edge has W-2 usable cells and the title starts at x=2, so it
51		// gets W-4 of them. Anything less than one cell means no room at all.
52		room := out.W - 4
53		if room > 0 {
54			out.Write(2, 0, truncRunes(title, room))
55		}
56	}
57	return out
58}
59
60func truncRunes(s string, n int) string {
61	i := 0
62	for idx := range s {
63		if i == n {
64			return s[:idx]
65		}
66		i++
67	}
68	return s
69}