ginger/gim/box.go

99 lines
2.0 KiB
Go

package main
import (
"fmt"
"strings"
"github.com/mediocregopher/ginger/gg"
"github.com/mediocregopher/ginger/gim/geo"
"github.com/mediocregopher/ginger/gim/terminal"
)
type box struct {
topLeft geo.XY
flowDir geo.XY
numIn, numOut int
body string
transparent bool
}
func boxFromVertex(v *gg.Vertex, flowDir geo.XY) box {
b := box{
flowDir: flowDir,
numIn: len(v.In),
numOut: len(v.Out),
}
if v.VertexType == gg.ValueVertex {
b.body = v.Value.V.(string)
}
return b
}
func (b box) bodyLines() []string {
lines := strings.Split(b.body, "\n")
// if the last line is empty don't include it, it means there was a trailing
// newline (or the whole string is empty)
if lines[len(lines)-1] == "" {
lines = lines[:len(lines)-1]
}
return lines
}
// TODO this is utterly broken, the terminal.Buffer should be used for this
func (b box) bodySize() geo.XY {
var size geo.XY
for _, line := range b.bodyLines() {
size[1]++
if l := len(line); l > size[0] {
size[0] = l
}
}
return size
}
func (b box) rect() geo.Rect {
bodyRect := geo.Rect{
Size: b.bodySize().Add(geo.XY{2, 2}),
}
var edgesRect geo.Rect
{
var neededByEdges int
if b.numIn > b.numOut {
neededByEdges = b.numIn*2 + 1
} else {
neededByEdges = b.numOut*2 + 1
}
switch b.flowDir {
case geo.Left, geo.Right:
edgesRect.Size = geo.XY{2, neededByEdges}
case geo.Up, geo.Down:
edgesRect.Size = geo.XY{neededByEdges, 2}
default:
panic(fmt.Sprintf("unknown flowDir: %#v", b.flowDir))
}
}
return bodyRect.Union(edgesRect).Translate(b.topLeft)
}
func (b box) bodyRect() geo.Rect {
center := b.rect().Center(rounder)
return geo.Rect{Size: b.bodySize()}.Centered(center, rounder)
}
func (b box) draw(buf *terminal.Buffer) {
bodyBuf := terminal.NewBuffer()
bodyBuf.WriteString(b.body)
bodyBufRect := geo.Rect{Size: bodyBuf.Size()}
rect := b.rect()
buf.DrawRect(rect, terminal.SingleLine)
center := rect.Center(rounder)
buf.DrawBuffer(bodyBufRect.Centered(center, rounder).TopLeft, bodyBuf)
}