Window rendering upgraded to use blocks
This commit is contained in:
parent
7bc56f967d
commit
166245fccd
@ -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)
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
10
spectator.go
10
spectator.go
@ -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 {
|
||||||
|
Reference in New Issue
Block a user