Window rendering upgraded to use blocks

This commit is contained in:
Kevin Cotugno 2017-12-30 13:42:13 -08:00
parent 7bc56f967d
commit 166245fccd
7 changed files with 186 additions and 95 deletions

View File

@ -16,6 +16,10 @@ func NewBlock(originx, originy, sizex, sizey int) Block {
return b return b
} }
func (b Block) Size() image.Point {
return b.Rect.Size()
}
func (b *Block) SetSize(p image.Point) { func (b *Block) SetSize(p image.Point) {
dx := b.Rect.Min.X dx := b.Rect.Min.X
dy := b.Rect.Min.Y dy := b.Rect.Min.Y
@ -23,6 +27,10 @@ func (b *Block) SetSize(p image.Point) {
b.Rect.Max.Y = p.Y + dy b.Rect.Max.Y = p.Y + dy
} }
func (b Block) Origin() image.Point {
return b.Rect.Min
}
func (b *Block) SetOrigin(p image.Point) { func (b *Block) SetOrigin(p image.Point) {
d := p.Sub(b.Rect.Min) d := p.Sub(b.Rect.Min)
b.Rect = b.Rect.Add(d) b.Rect = b.Rect.Add(d)

View File

@ -1,5 +1,9 @@
package exhibit package exhibit
import (
"image"
)
const ( const (
Thick = Style(iota) Thick = Style(iota)
Thin Thin
@ -22,6 +26,13 @@ const (
Intersect Intersect
) )
type Border struct {
Style
Box
Attributes
Visible bool
}
type Style int type Style int
type Box int type Box int
@ -51,3 +62,34 @@ func BorderRune(c Box, s Style) rune {
return ' ' return ' '
} }
} }
func (b Border) Cell(p image.Point, r image.Rectangle) (Cell, bool) {
c := Cell{}
if !b.Visible {
return c, false
}
c.Attrs = b.Attributes
if p.X != r.Min.X && p.X != r.Max.X-1 &&
p.Y != r.Min.Y && p.Y != r.Max.Y-1 {
return c, false
}
if p.X == r.Min.X && p.Y == r.Min.Y {
c.Value = BorderRune(TopLeft, b.Style)
} else if p.X == r.Max.X-1 && p.Y == r.Min.Y {
c.Value = BorderRune(TopRight, b.Style)
} else if p.X == r.Min.X && p.Y == r.Max.Y-1 {
c.Value = BorderRune(BottomLeft, b.Style)
} else if p.X == r.Max.X-1 && p.Y == r.Max.Y-1 {
c.Value = BorderRune(BottomRight, b.Style)
} else if p.X == r.Min.X || p.X == r.Max.X-1 {
c.Value = BorderRune(Vertical, b.Style)
} else if p.Y == r.Min.Y || p.Y == r.Max.Y-1 {
c.Value = BorderRune(Horizontal, b.Style)
}
return c, true
}

View File

@ -11,16 +11,17 @@ type ListEntry interface {
} }
type ListWidget struct { type ListWidget struct {
Style Style
blockLock sync.Mutex blockLock sync.Mutex
block Block block Block
attributesLock sync.Mutex attributesLock sync.Mutex
attributes Attributes attributes Attributes
rightAlign bool rightAlignLock sync.Mutex
border bool rightAlign bool
borderLock sync.Mutex
border Border
listLock sync.Mutex listLock sync.Mutex
list [][]Cell list [][]Cell
@ -115,22 +116,39 @@ func (l *ListWidget) Commit() {
l.recalculateCells() l.recalculateCells()
} }
func (l *ListWidget) SetBorder(b bool) { func (l *ListWidget) Border() Border {
l.borderLock.Lock()
defer l.borderLock.Unlock()
return l.border
}
func (l *ListWidget) SetBorder(b Border) {
l.borderLock.Lock()
if l.border == b { if l.border == b {
return return
} }
l.border = b l.border = b
l.borderLock.Unlock()
l.recalculateCells() l.recalculateCells()
} }
func (l *ListWidget) RightAlign() bool {
l.rightAlignLock.Lock()
defer l.rightAlignLock.Unlock()
return l.rightAlign
}
func (l *ListWidget) SetRightAlign(b bool) { func (l *ListWidget) SetRightAlign(b bool) {
l.rightAlignLock.Lock()
if l.rightAlign == b { if l.rightAlign == b {
return return
} }
l.rightAlign = b l.rightAlign = b
l.rightAlignLock.Unlock()
l.recalculateCells() l.recalculateCells()
} }
@ -140,14 +158,20 @@ func (l *ListWidget) recalculateCells() {
defer l.listLock.Unlock() defer l.listLock.Unlock()
l.blockLock.Lock() l.blockLock.Lock()
origin := l.block.Rect.Min rect := l.block.Rect
size := l.block.Rect.Size()
l.blockLock.Unlock() l.blockLock.Unlock()
origin := rect.Min
size := rect.Size()
rightAlign := l.RightAlign()
border := l.Border()
cells := make(map[image.Point]Cell) cells := make(map[image.Point]Cell)
var i, bx, by int var i, bx, by int
if l.border { if border.Visible {
size = size.Add(image.Point{2, 2}) size = size.Add(image.Point{2, 2})
bx = 1 bx = 1
by = 1 by = 1
@ -158,18 +182,16 @@ func (l *ListWidget) recalculateCells() {
c := Cell{Value: ' '} c := Cell{Value: ' '}
point := image.Pt(x, y).Add(origin) point := image.Pt(x, y).Add(origin)
if l.border { cell, ok := border.Cell(point, rect)
cell, ok := l.borderCell(image.Pt(x, y), size) if ok {
if ok { cells[point] = cell
cells[point] = cell continue
continue
}
} }
if y < len(l.list)+by { if y < len(l.list)+by {
length := len(l.list[y-by]) length := len(l.list[y-by])
if l.rightAlign { if rightAlign {
i = (size.X - x - length - bx) * -1 i = (size.X - x - length - bx) * -1
} else { } else {
i = x - bx i = x - bx
@ -188,28 +210,3 @@ func (l *ListWidget) recalculateCells() {
l.block.Cells = cells l.block.Cells = cells
l.blockLock.Unlock() l.blockLock.Unlock()
} }
func (l *ListWidget) borderCell(p image.Point, size image.Point) (Cell, bool) {
c := Cell{}
c.Attrs = l.Attributes()
if p.X != 0 && p.X != size.X-1 && p.Y != 0 && p.Y != size.Y-1 {
return c, false
}
if p.X == 0 && p.Y == 0 {
c.Value = BorderRune(TopLeft, l.Style)
} else if p.X == size.X-1 && p.Y == 0 {
c.Value = BorderRune(TopRight, l.Style)
} else if p.X == 0 && p.Y == size.Y-1 {
c.Value = BorderRune(BottomLeft, l.Style)
} else if p.X == size.X-1 && p.Y == size.Y-1 {
c.Value = BorderRune(BottomRight, l.Style)
} else if p.X == 0 || p.X == size.X-1 {
c.Value = BorderRune(Vertical, l.Style)
} else if p.Y == 0 || p.Y == size.Y-1 {
c.Value = BorderRune(Horizontal, l.Style)
}
return c, true
}

View File

@ -11,6 +11,7 @@ type Scene struct {
func (s *Scene) Render() { func (s *Scene) Render() {
s.Window.SetSize(s.Terminal.Size()) s.Window.SetSize(s.Terminal.Size())
s.Window.SetOrigin(image.Point{})
c := make([]Cell, 0) c := make([]Cell, 0)

View File

@ -4,17 +4,12 @@ import (
"image" "image"
) )
type Border struct {
Top bool
Bottom bool
Left bool
Right bool
}
type Widget interface { type Widget interface {
Render(image.Point) Block Render(image.Point) Block
Size() image.Point Size() image.Point
SetSize(image.Point) SetSize(image.Point)
Origin() image.Point
SetOrigin(image.Point)
Attributes() Attributes Attributes() Attributes
SetAttributes(Attributes) SetAttributes(Attributes)
} }

View File

@ -2,16 +2,28 @@ package exhibit
import ( import (
"image" "image"
"sync"
) )
type WindowWidget struct { type WindowWidget struct {
block Block Style Style
attributes Attributes blockLock sync.Mutex
block Block
attributesLock sync.Mutex
attributes Attributes
borderLock sync.Mutex
border Border border Border
widgetLock sync.Mutex
widgets []Widget widgets []Widget
} }
func (w *WindowWidget) AddWidget(widget Widget) { func (w *WindowWidget) AddWidget(widget Widget) {
w.widgetLock.Lock()
defer w.widgetLock.Unlock()
if w.widgets == nil { if w.widgets == nil {
w.widgets = make([]Widget, 0) w.widgets = make([]Widget, 0)
} }
@ -20,10 +32,16 @@ func (w *WindowWidget) AddWidget(widget Widget) {
} }
func (w WindowWidget) Attributes() Attributes { func (w WindowWidget) Attributes() Attributes {
w.attributesLock.Lock()
defer w.attributesLock.Unlock()
return w.attributes return w.attributes
} }
func (w *WindowWidget) SetAttributes(a Attributes) { func (w *WindowWidget) SetAttributes(a Attributes) {
w.attributesLock.Lock()
defer w.attributesLock.Unlock()
w.attributes = a w.attributes = a
} }
@ -35,46 +53,78 @@ func (w *WindowWidget) SetSize(p image.Point) {
w.block.SetSize(p) w.block.SetSize(p)
} }
func (w *WindowWidget) Render() Block { func (w *WindowWidget) Origin() image.Point {
w.blockLock.Lock()
defer w.blockLock.Unlock()
return w.block.Rect.Min
}
func (w *WindowWidget) SetOrigin(p image.Point) {
w.blockLock.Lock()
defer w.blockLock.Unlock()
w.block.SetOrigin(p)
}
func (w *WindowWidget) Border() Border {
w.borderLock.Lock()
defer w.borderLock.Unlock()
return w.border
}
func (w *WindowWidget) SetBorder(b Border) {
w.borderLock.Lock()
defer w.borderLock.Unlock()
w.border = b
}
func (w *WindowWidget) Render(origin image.Point) Block {
if w.block.Rect.Size().X == 0 || w.block.Rect.Size().Y == 0 { if w.block.Rect.Size().X == 0 || w.block.Rect.Size().Y == 0 {
return w.renderContent() return NewBlock(0, 0, 0, 0)
} else {
return w.renderSize()
} }
}
w.widgetLock.Lock()
func (w *WindowWidget) renderContent() Block { defer w.widgetLock.Unlock()
// c := make([][]Cell, 0)
w.blockLock.Lock()
// var y int defer w.blockLock.Unlock()
// for _, w := range w.widgets { var borderAdj image.Point
// for _, row := range w.Render() { border := w.Border()
if border.Visible {
// t := make([]Cell, len(row)) borderAdj = image.Pt(1, 1)
// c = append(c, t) }
// for j, col := range row { block := NewBlock(0, 0, 0, 0)
// col.Pos.Y = y block.SetSize(w.block.Rect.Size())
// c[y][j] = col block.SetOrigin(origin.Add(w.block.Origin()))
// }
for _, widget := range w.widgets {
// y++ cells := widget.Render(block.Origin().Add(borderAdj)).Cells
// }
// } for k, v := range cells {
if !k.In(block.Rect) {
return Block{} continue
} }
func (w *WindowWidget) renderSize() Block { block.Cells[k] = v
// c := make([][]Cell, w.size.Y) }
}
// for y := 0; y < w.size.Y; y++ {
// for x := 0; x < w.size.X; x++ { if border.Visible {
// c[y][x] = Cell{Pos: Position{X: x, Y: y}} for x := 0; x < block.Size().X; x++ {
// } for y := 0; y < block.Size().Y; y++ {
// } point := image.Pt(x, y).Add(block.Origin())
c, ok := border.Cell(point, block.Rect)
// return c if ok {
return Block{} block.Cells[point] = c
}
}
}
}
return block
} }

View File

@ -77,27 +77,25 @@ func main() {
defer terminal.Shutdown() defer terminal.Shutdown()
terminal.HideCursor() terminal.HideCursor()
// window = &exhibit.WindowWidget{} window = &exhibit.WindowWidget{}
window.SetBorder(exhibit.Border{Visible: true})
topAsks = &exhibit.ListWidget{} topAsks = &exhibit.ListWidget{}
// topAsks.SetSize(image.Point{100, 100}) // topAsks.SetSize(image.Point{100, 100})
topAsks.SetBorder(true)
topAsks.SetRightAlign(true) topAsks.SetRightAlign(true)
topAsks.SetAttributes(exhibit.Attributes{ForegroundColor: exhibit.FGCyan}) topAsks.SetAttributes(exhibit.Attributes{ForegroundColor: exhibit.FGCyan})
topBids = &exhibit.ListWidget{} topBids = &exhibit.ListWidget{}
// topBids.SetBorder(true)
// topBids.SetRightAlign(true) // topBids.SetRightAlign(true)
// topBids.SetAttributes(exhibit.Attributes{ForegroundColor: exhibit.FGGreen}) // topBids.SetAttributes(exhibit.Attributes{ForegroundColor: exhibit.FGGreen})
midPrice = &exhibit.ListWidget{} midPrice = &exhibit.ListWidget{}
// midPrice.SetRightAlign(true) // midPrice.SetRightAlign(true)
// window.AddWidget(topAsks) window.AddWidget(topAsks)
// window.AddWidget(midPrice) // window.AddWidget(midPrice)
// window.AddWidget(topBids) // window.AddWidget(topBids)
// scene := exhibit.Scene{terminal, window} scene := exhibit.Scene{terminal, window}
scene := exhibit.Scene{terminal, topAsks}
conn, _, err := websocket.DefaultDialer.Dial("wss://ws-feed.gdax.com", nil) conn, _, err := websocket.DefaultDialer.Dial("wss://ws-feed.gdax.com", nil)
if err != nil { if err != nil {