repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

pico / pkg / tui
Antonio Mika  ·  2025-03-12

border.go

  1package tui
  2
  3import (
  4	"fmt"
  5
  6	"git.sr.ht/~rockorager/vaxis"
  7	"git.sr.ht/~rockorager/vaxis/vxfw"
  8)
  9
 10var (
 11	horizontal  = vaxis.Character{Grapheme: "─", Width: 1}
 12	vertical    = vaxis.Character{Grapheme: "│", Width: 1}
 13	topLeft     = vaxis.Character{Grapheme: "╭", Width: 1}
 14	topRight    = vaxis.Character{Grapheme: "╮", Width: 1}
 15	bottomRight = vaxis.Character{Grapheme: "╯", Width: 1}
 16	bottomLeft  = vaxis.Character{Grapheme: "╰", Width: 1}
 17)
 18
 19func border(label string, surf vxfw.Surface, style vaxis.Style) vxfw.Surface {
 20	finlabel := fmt.Sprintf(" %s ", label)
 21	w := surf.Size.Width
 22	h := surf.Size.Height
 23	surf.WriteCell(0, 0, vaxis.Cell{
 24		Character: topLeft,
 25		Style:     style,
 26	})
 27	surf.WriteCell(0, h-1, vaxis.Cell{
 28		Character: bottomLeft,
 29		Style:     style,
 30	})
 31	surf.WriteCell(w-1, 0, vaxis.Cell{
 32		Character: topRight,
 33		Style:     style,
 34	})
 35	surf.WriteCell(w-1, h-1, vaxis.Cell{
 36		Character: bottomRight,
 37		Style:     style,
 38	})
 39	idx := 0
 40	for j := 1; j < (int(w) - 1); j += 1 {
 41		i := uint16(j)
 42		// apply label
 43		char := horizontal
 44		if label != "" && j >= 2 && len(finlabel)+1 >= j {
 45			char = vaxis.Character{Grapheme: string(finlabel[idx]), Width: 1}
 46			idx += 1
 47		}
 48		surf.WriteCell(i, 0, vaxis.Cell{
 49			Character: char,
 50			Style:     style,
 51		})
 52		surf.WriteCell(i, h-1, vaxis.Cell{
 53			Character: horizontal,
 54			Style:     style,
 55		})
 56	}
 57	for j := 1; j < (int(h) - 1); j += 1 {
 58		i := uint16(j)
 59		surf.WriteCell(0, i, vaxis.Cell{
 60			Character: vertical,
 61			Style:     style,
 62		})
 63		surf.WriteCell(w-1, i, vaxis.Cell{
 64			Character: vertical,
 65			Style:     style,
 66		})
 67	}
 68
 69	return surf
 70}
 71
 72type Border struct {
 73	w      vxfw.Widget
 74	Style  vaxis.Style
 75	Label  string
 76	Width  uint16
 77	Height uint16
 78}
 79
 80func NewBorder(w vxfw.Widget) *Border {
 81	return &Border{
 82		w:     w,
 83		Style: vaxis.Style{Foreground: purp},
 84		Label: "",
 85	}
 86}
 87
 88func (b *Border) HandleEvent(vaxis.Event, vxfw.EventPhase) (vxfw.Command, error) {
 89	return nil, nil
 90}
 91
 92func (b *Border) Draw(ctx vxfw.DrawContext) (vxfw.Surface, error) {
 93	surf, _ := b.w.Draw(vxfw.DrawContext{
 94		Characters: ctx.Characters,
 95		Max: vxfw.Size{
 96			Width:  ctx.Max.Width - 2,
 97			Height: ctx.Max.Height - 3,
 98		},
 99	})
100
101	w := surf.Size.Width + 2
102	if b.Width > 0 {
103		w = b.Width - 2
104	}
105
106	h := surf.Size.Height + 2
107	if b.Height > 0 {
108		h = b.Height - 2
109	}
110
111	root := border(
112		b.Label,
113		vxfw.NewSurface(w, h, b),
114		b.Style,
115	)
116	root.AddChild(1, 1, surf)
117	return root, nil
118}