gim: refactor positioning and drawing code to take advantage of terminal buffers more

This commit is contained in:
Brian Picciano 2018-06-07 03:25:40 +00:00
parent b906697151
commit a6d540f1fb
3 changed files with 21 additions and 63 deletions

View File

@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"strings"
"github.com/mediocregopher/ginger/gg" "github.com/mediocregopher/ginger/gg"
"github.com/mediocregopher/ginger/gim/geo" "github.com/mediocregopher/ginger/gim/geo"
@ -13,7 +12,7 @@ type box struct {
topLeft geo.XY topLeft geo.XY
flowDir geo.XY flowDir geo.XY
numIn, numOut int numIn, numOut int
body string bodyBuf *terminal.Buffer
transparent bool transparent bool
} }
@ -25,37 +24,16 @@ func boxFromVertex(v *gg.Vertex, flowDir geo.XY) box {
numOut: len(v.Out), numOut: len(v.Out),
} }
if v.VertexType == gg.ValueVertex { if v.VertexType == gg.ValueVertex {
b.body = v.Value.V.(string) b.bodyBuf = terminal.NewBuffer()
b.bodyBuf.WriteString(v.Value.V.(string))
} }
return b 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 { func (b box) rect() geo.Rect {
bodyRect := geo.Rect{ var bodyRect geo.Rect
Size: b.bodySize().Add(geo.XY{2, 2}), if b.bodyBuf != nil {
bodyRect.Size = b.bodyBuf.Size().Add(geo.XY{2, 2})
} }
var edgesRect geo.Rect var edgesRect geo.Rect
@ -80,19 +58,13 @@ func (b box) rect() geo.Rect {
return bodyRect.Union(edgesRect).Translate(b.topLeft) 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) { func (b box) draw(buf *terminal.Buffer) {
bodyBuf := terminal.NewBuffer()
bodyBuf.WriteString(b.body)
bodyBufRect := geo.Rect{Size: bodyBuf.Size()}
rect := b.rect() rect := b.rect()
buf.DrawRect(rect, terminal.SingleLine) buf.DrawRect(rect, terminal.SingleLine)
if b.bodyBuf != nil {
center := rect.Center(rounder) center := rect.Center(rounder)
buf.DrawBuffer(bodyBufRect.Centered(center, rounder).TopLeft, bodyBuf) bodyBufRect := geo.Rect{Size: b.bodyBuf.Size()}
buf.DrawBuffer(bodyBufRect.Centered(center, rounder).TopLeft, b.bodyBuf)
}
} }

View File

@ -81,6 +81,7 @@ func main() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
term := terminal.New() term := terminal.New()
wSize := term.WindowSize() wSize := term.WindowSize()
center := geo.Zero.Midpoint(wSize, rounder)
g, start := mkGraph() g, start := mkGraph()
v := view{ v := view{
@ -88,11 +89,14 @@ func main() {
primFlowDir: geo.Right, primFlowDir: geo.Right,
secFlowDir: geo.Down, secFlowDir: geo.Down,
start: start, 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() term.Clear()
v.draw(term) term.WriteBuffer(bufRect.TopLeft, buf)
term.SetPos(wSize.Add(geo.XY{0, -1})) term.SetPos(wSize.Add(geo.XY{0, -1}))
term.Draw() term.Draw()
} }

View File

@ -86,28 +86,13 @@ func posSolve(g *gg.Graph) ([][]*gg.Vertex, map[string]int, map[string]int) {
return out, prim, sec 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 { type view struct {
g *gg.Graph g *gg.Graph
primFlowDir, secFlowDir geo.XY primFlowDir, secFlowDir geo.XY
start gg.Value 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) relPos, _, secSol := posSolve(view.g)
// create boxes // create boxes
@ -142,7 +127,9 @@ func (view *view) draw(term *terminal.Terminal) {
} }
secPos += secBoxLen + secPadding 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 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 // actually draw the boxes and lines
buf := terminal.NewBuffer()
for _, b := range boxes { for _, b := range boxes {
b.draw(buf) b.draw(buf)
} }
for _, line := range lines { for _, line := range lines {
line.draw(buf, view.primFlowDir, view.secFlowDir) line.draw(buf, view.primFlowDir, view.secFlowDir)
} }
term.WriteBuffer(geo.Zero, buf)
} }