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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

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}