summary refs log tree commit diff stats
path: root/ui/grid.go
diff options
context:
space:
mode:
Diffstat (limited to 'ui/grid.go')
-rw-r--r--ui/grid.go70
1 files changed, 55 insertions, 15 deletions
diff --git a/ui/grid.go b/ui/grid.go
index 2183a55..2091fc5 100644
--- a/ui/grid.go
+++ b/ui/grid.go
@@ -1,6 +1,9 @@
 package ui
 
-import "fmt"
+import (
+	"fmt"
+	"math"
+)
 
 type Grid struct {
 	Rows         []DimSpec
@@ -42,6 +45,22 @@ type GridCell struct {
 	invalid bool
 }
 
+func NewGrid() *Grid {
+	return &Grid{invalid: true}
+}
+
+func (cell *GridCell) At(row, col int) *GridCell {
+	cell.Row = row
+	cell.Column = col
+	return cell
+}
+
+func (cell *GridCell) Span(rows, cols int) *GridCell {
+	cell.RowSpan = rows
+	cell.ColSpan = cols
+	return cell
+}
+
 func (grid *Grid) Draw(ctx *Context) {
 	invalid := grid.invalid
 	if invalid {
@@ -51,17 +70,17 @@ func (grid *Grid) Draw(ctx *Context) {
 		if !cell.invalid && !invalid {
 			continue
 		}
-		rows := grid.rowLayout[cell.Row:cell.RowSpan]
-		cols := grid.columnLayout[cell.Column:cell.ColSpan]
+		rows := grid.rowLayout[cell.Row : cell.Row+cell.RowSpan]
+		cols := grid.columnLayout[cell.Column : 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
+			width += col.Size
+		}
+		for _, row := range rows {
+			height += row.Size
 		}
 		subctx := ctx.Subcontext(x, y, width, height)
 		cell.Content.Draw(subctx)
@@ -74,10 +93,12 @@ func (grid *Grid) reflow(ctx *Context) {
 	flow := func(specs *[]DimSpec, layouts *[]dimLayout, extent int) {
 		exact := 0
 		weight := 0
+		nweights := 0
 		for _, dim := range *specs {
 			if dim.Strategy == SIZE_EXACT {
 				exact += dim.Size
 			} else if dim.Strategy == SIZE_WEIGHT {
+				nweights += 1
 				weight += dim.Size
 			}
 		}
@@ -87,30 +108,49 @@ func (grid *Grid) reflow(ctx *Context) {
 			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)
+				size := float64(dim.Size) / float64(weight)
+				size *= float64(extent - exact)
+				layout.Size = int(math.Floor(size))
 			}
+			offset += layout.Size
 			*layouts = append(*layouts, layout)
 		}
 	}
-	flow(&grid.Rows, &grid.rowLayout, ctx.Width())
-	flow(&grid.Columns, &grid.columnLayout, ctx.Height())
+	flow(&grid.Rows, &grid.rowLayout, ctx.Height())
+	flow(&grid.Columns, &grid.columnLayout, ctx.Width())
 	grid.invalid = false
 }
 
-func (grid *Grid) InvalidateLayout() {
+func (grid *Grid) invalidateLayout() {
 	grid.invalid = true
+	if grid.onInvalidate != nil {
+		grid.onInvalidate(grid)
+	}
+}
+
+func (grid *Grid) Invalidate() {
+	grid.invalidateLayout()
+	for _, cell := range grid.Cells {
+		cell.Content.Invalidate()
+	}
 }
 
 func (grid *Grid) OnInvalidate(onInvalidate func(d Drawable)) {
 	grid.onInvalidate = onInvalidate
 }
 
-func (grid *Grid) AddChild(cell *GridCell) {
+func (grid *Grid) AddChild(content Drawable) *GridCell {
+	cell := &GridCell{
+		RowSpan: 1,
+		ColSpan: 1,
+		Content: content,
+		invalid: true,
+	}
 	grid.Cells = append(grid.Cells, cell)
 	cell.Content.OnInvalidate(grid.cellInvalidated)
 	cell.invalid = true
-	grid.InvalidateLayout()
+	grid.invalidateLayout()
+	return cell
 }
 
 func (grid *Grid) RemoveChild(cell *GridCell) {
@@ -120,7 +160,7 @@ func (grid *Grid) RemoveChild(cell *GridCell) {
 			break
 		}
 	}
-	grid.InvalidateLayout()
+	grid.invalidateLayout()
 }
 
 func (grid *Grid) cellInvalidated(drawable Drawable) {