gim: refactor positioning and drawing code to take advantage of terminal buffers more
This commit is contained in:
parent
b906697151
commit
a6d540f1fb
50
gim/box.go
50
gim/box.go
@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mediocregopher/ginger/gg"
|
||||
"github.com/mediocregopher/ginger/gim/geo"
|
||||
@ -13,7 +12,7 @@ type box struct {
|
||||
topLeft geo.XY
|
||||
flowDir geo.XY
|
||||
numIn, numOut int
|
||||
body string
|
||||
bodyBuf *terminal.Buffer
|
||||
|
||||
transparent bool
|
||||
}
|
||||
@ -25,37 +24,16 @@ func boxFromVertex(v *gg.Vertex, flowDir geo.XY) box {
|
||||
numOut: len(v.Out),
|
||||
}
|
||||
if v.VertexType == gg.ValueVertex {
|
||||
b.body = v.Value.V.(string)
|
||||
b.bodyBuf = terminal.NewBuffer()
|
||||
b.bodyBuf.WriteString(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 bodyRect geo.Rect
|
||||
if b.bodyBuf != nil {
|
||||
bodyRect.Size = b.bodyBuf.Size().Add(geo.XY{2, 2})
|
||||
}
|
||||
|
||||
var edgesRect geo.Rect
|
||||
@ -80,19 +58,13 @@ func (b box) rect() geo.Rect {
|
||||
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)
|
||||
if b.bodyBuf != nil {
|
||||
center := rect.Center(rounder)
|
||||
bodyBufRect := geo.Rect{Size: b.bodyBuf.Size()}
|
||||
buf.DrawBuffer(bodyBufRect.Centered(center, rounder).TopLeft, b.bodyBuf)
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ func main() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
term := terminal.New()
|
||||
wSize := term.WindowSize()
|
||||
center := geo.Zero.Midpoint(wSize, rounder)
|
||||
|
||||
g, start := mkGraph()
|
||||
v := view{
|
||||
@ -88,11 +89,14 @@ func main() {
|
||||
primFlowDir: geo.Right,
|
||||
secFlowDir: geo.Down,
|
||||
start: start,
|
||||
center: geo.Zero.Midpoint(wSize, rounder),
|
||||
}
|
||||
|
||||
buf := terminal.NewBuffer()
|
||||
v.draw(buf)
|
||||
bufRect := geo.Rect{Size: buf.Size()}.Centered(center, rounder)
|
||||
|
||||
term.Clear()
|
||||
v.draw(term)
|
||||
term.WriteBuffer(bufRect.TopLeft, buf)
|
||||
term.SetPos(wSize.Add(geo.XY{0, -1}))
|
||||
term.Draw()
|
||||
}
|
||||
|
26
gim/view.go
26
gim/view.go
@ -86,28 +86,13 @@ func posSolve(g *gg.Graph) ([][]*gg.Vertex, map[string]int, map[string]int) {
|
||||
return out, prim, sec
|
||||
}
|
||||
|
||||
// mutates the boxes to be centered around the given point, keeping their
|
||||
// relative position to each other
|
||||
func centerBoxes(boxes []*box, around geo.XY) {
|
||||
var graphRect geo.Rect
|
||||
for _, b := range boxes {
|
||||
graphRect = graphRect.Union(b.rect())
|
||||
}
|
||||
graphMid := graphRect.Center(rounder)
|
||||
delta := around.Sub(graphMid)
|
||||
for _, b := range boxes {
|
||||
b.topLeft = b.topLeft.Add(delta)
|
||||
}
|
||||
}
|
||||
|
||||
type view struct {
|
||||
g *gg.Graph
|
||||
primFlowDir, secFlowDir geo.XY
|
||||
start gg.Value
|
||||
center geo.XY // TODO this shouldnt be needed
|
||||
}
|
||||
|
||||
func (view *view) draw(term *terminal.Terminal) {
|
||||
func (view *view) draw(buf *terminal.Buffer) {
|
||||
relPos, _, secSol := posSolve(view.g)
|
||||
|
||||
// create boxes
|
||||
@ -142,7 +127,9 @@ func (view *view) draw(term *terminal.Terminal) {
|
||||
}
|
||||
secPos += secBoxLen + secPadding
|
||||
}
|
||||
centerBoxes(primBoxes, view.primFlowDir.Scale(primPos))
|
||||
for _, b := range primBoxes {
|
||||
b.topLeft = b.topLeft.Add(view.primFlowDir.Scale(primPos))
|
||||
}
|
||||
primPos += maxPrim + primPadding
|
||||
}
|
||||
|
||||
@ -186,16 +173,11 @@ func (view *view) draw(term *terminal.Terminal) {
|
||||
}
|
||||
}
|
||||
|
||||
// translate all boxes so the graph is centered around v.center
|
||||
centerBoxes(boxes, view.center)
|
||||
|
||||
// actually draw the boxes and lines
|
||||
buf := terminal.NewBuffer()
|
||||
for _, b := range boxes {
|
||||
b.draw(buf)
|
||||
}
|
||||
for _, line := range lines {
|
||||
line.draw(buf, view.primFlowDir, view.secFlowDir)
|
||||
}
|
||||
term.WriteBuffer(geo.Zero, buf)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user