Add grid rendering, probably
This commit is contained in:
parent
8c8c21f3ff
commit
1892d73161
2 changed files with 76 additions and 9 deletions
|
@ -2,7 +2,7 @@ package ui
|
||||||
|
|
||||||
type Drawable interface {
|
type Drawable interface {
|
||||||
// Called when this renderable should draw itself
|
// Called when this renderable should draw itself
|
||||||
Draw(ctx Context)
|
Draw(ctx *Context)
|
||||||
// Specifies a function to call when this cell needs to be redrawn
|
// Specifies a function to call when this cell needs to be redrawn
|
||||||
OnInvalidate(callback func(d Drawable))
|
OnInvalidate(callback func(d Drawable))
|
||||||
}
|
}
|
||||||
|
|
83
ui/grid.go
83
ui/grid.go
|
@ -4,9 +4,12 @@ import "fmt"
|
||||||
|
|
||||||
type Grid struct {
|
type Grid struct {
|
||||||
Rows []DimSpec
|
Rows []DimSpec
|
||||||
|
rowLayout []dimLayout
|
||||||
Columns []DimSpec
|
Columns []DimSpec
|
||||||
|
columnLayout []dimLayout
|
||||||
Cells []*GridCell
|
Cells []*GridCell
|
||||||
onInvalidate func(d Drawable)
|
onInvalidate func(d Drawable)
|
||||||
|
invalid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -17,24 +20,86 @@ const (
|
||||||
// Specifies the layout of a single row or column
|
// Specifies the layout of a single row or column
|
||||||
type DimSpec struct {
|
type DimSpec struct {
|
||||||
// One of SIZE_EXACT or SIZE_WEIGHT
|
// One of SIZE_EXACT or SIZE_WEIGHT
|
||||||
Strategy uint
|
Strategy int
|
||||||
// If Strategy = SIZE_EXACT, this is the number of cells this dim shall
|
// If Strategy = SIZE_EXACT, this is the number of cells this dim shall
|
||||||
// occupy. If SIZE_WEIGHT, the space left after all exact dims are measured
|
// occupy. If SIZE_WEIGHT, the space left after all exact dims are measured
|
||||||
// is distributed amonst the remaining dims weighted by this value.
|
// is distributed amonst the remaining dims weighted by this value.
|
||||||
Size *uint
|
Size int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to cache layout of each row/column
|
||||||
|
type dimLayout struct {
|
||||||
|
Offset int
|
||||||
|
Size int
|
||||||
}
|
}
|
||||||
|
|
||||||
type GridCell struct {
|
type GridCell struct {
|
||||||
Row uint
|
Row int
|
||||||
Column uint
|
Column int
|
||||||
RowSpan uint
|
RowSpan int
|
||||||
ColSpan uint
|
ColSpan int
|
||||||
Content Drawable
|
Content Drawable
|
||||||
invalid bool
|
invalid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (grid *Grid) Draw(ctx Context) {
|
func (grid *Grid) Draw(ctx *Context) {
|
||||||
// TODO
|
invalid := grid.invalid
|
||||||
|
if invalid {
|
||||||
|
grid.reflow(ctx)
|
||||||
|
}
|
||||||
|
for _, cell := range grid.Cells {
|
||||||
|
if !cell.invalid && !invalid {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rows := grid.rowLayout[cell.Row:cell.RowSpan]
|
||||||
|
cols := grid.columnLayout[cell.Column:cell.ColSpan]
|
||||||
|
x := cols[0].Offset
|
||||||
|
y := rows[0].Offset
|
||||||
|
width := 0
|
||||||
|
height := 0
|
||||||
|
for _, row := range rows {
|
||||||
|
width += row.Size
|
||||||
|
}
|
||||||
|
for _, col := range cols {
|
||||||
|
height += col.Size
|
||||||
|
}
|
||||||
|
subctx := ctx.Subcontext(x, y, width, height)
|
||||||
|
cell.Content.Draw(subctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (grid *Grid) reflow(ctx *Context) {
|
||||||
|
grid.rowLayout = nil
|
||||||
|
grid.columnLayout = nil
|
||||||
|
flow := func(specs *[]DimSpec, layouts *[]dimLayout, extent int) {
|
||||||
|
exact := 0
|
||||||
|
weight := 0
|
||||||
|
for _, dim := range *specs {
|
||||||
|
if dim.Strategy == SIZE_EXACT {
|
||||||
|
exact += dim.Size
|
||||||
|
} else if dim.Strategy == SIZE_WEIGHT {
|
||||||
|
weight += dim.Size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset := 0
|
||||||
|
for _, dim := range *specs {
|
||||||
|
layout := dimLayout{Offset: offset}
|
||||||
|
if dim.Strategy == SIZE_EXACT {
|
||||||
|
layout.Size = dim.Size
|
||||||
|
} else if dim.Strategy == SIZE_WEIGHT {
|
||||||
|
size := float64(dim.Size) / float64(weight) * float64(extent)
|
||||||
|
layout.Size = int(size)
|
||||||
|
}
|
||||||
|
*layouts = append(*layouts, layout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flow(&grid.Rows, &grid.rowLayout, ctx.Width())
|
||||||
|
flow(&grid.Columns, &grid.columnLayout, ctx.Height())
|
||||||
|
grid.invalid = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (grid *Grid) InvalidateLayout() {
|
||||||
|
grid.invalid = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (grid *Grid) OnInvalidate(onInvalidate func(d Drawable)) {
|
func (grid *Grid) OnInvalidate(onInvalidate func(d Drawable)) {
|
||||||
|
@ -45,6 +110,7 @@ func (grid *Grid) AddChild(cell *GridCell) {
|
||||||
grid.Cells = append(grid.Cells, cell)
|
grid.Cells = append(grid.Cells, cell)
|
||||||
cell.Content.OnInvalidate(grid.cellInvalidated)
|
cell.Content.OnInvalidate(grid.cellInvalidated)
|
||||||
cell.invalid = true
|
cell.invalid = true
|
||||||
|
grid.InvalidateLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (grid *Grid) RemoveChild(cell *GridCell) {
|
func (grid *Grid) RemoveChild(cell *GridCell) {
|
||||||
|
@ -54,6 +120,7 @@ func (grid *Grid) RemoveChild(cell *GridCell) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
grid.InvalidateLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (grid *Grid) cellInvalidated(drawable Drawable) {
|
func (grid *Grid) cellInvalidated(drawable Drawable) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue