From f0791d4ba720c4cfa1d3f90c99296584aa878cd9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 17 Feb 2018 20:11:58 -0500 Subject: Add borders widget --- ui/borders.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ui/grid.go | 56 ++++++++++++++++++++++++++------------------- 2 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 ui/borders.go (limited to 'ui') diff --git a/ui/borders.go b/ui/borders.go new file mode 100644 index 0000000..08071ad --- /dev/null +++ b/ui/borders.go @@ -0,0 +1,73 @@ +package ui + +import ( + tb "github.com/nsf/termbox-go" +) + +const ( + BORDER_LEFT = 1 << iota + BORDER_TOP = 1 << iota + BORDER_RIGHT = 1 << iota + BORDER_BOTTOM = 1 << iota +) + +type Bordered struct { + borders uint + content Drawable + onInvalidate func(d Drawable) +} + +func NewBordered(content Drawable, borders uint) *Bordered { + b := &Bordered{ + borders: borders, + content: content, + } + content.OnInvalidate(b.contentInvalidated) + return b +} + +func (bordered *Bordered) contentInvalidated(d Drawable) { + bordered.Invalidate() +} + +func (bordered *Bordered) Invalidate() { + if bordered.onInvalidate != nil { + bordered.onInvalidate(bordered) + } +} + +func (bordered *Bordered) OnInvalidate(onInvalidate func(d Drawable)) { + bordered.onInvalidate = onInvalidate +} + +func (bordered *Bordered) Draw(ctx *Context) { + x := 0 + y := 0 + width := ctx.Width() + height := ctx.Height() + cell := tb.Cell{ + Ch: ' ', + Fg: tb.ColorBlack, + Bg: tb.ColorWhite, + } + if bordered.borders&BORDER_LEFT != 0 { + ctx.Fill(0, 0, 1, ctx.Height(), cell) + x += 1 + width -= 1 + } + if bordered.borders&BORDER_TOP != 0 { + ctx.Fill(0, 0, ctx.Width(), 1, cell) + y += 1 + height -= 1 + } + if bordered.borders&BORDER_RIGHT != 0 { + ctx.Fill(ctx.Width()-1, 0, 1, ctx.Height(), cell) + width -= 1 + } + if bordered.borders&BORDER_BOTTOM != 0 { + ctx.Fill(0, ctx.Height()-1, ctx.Width(), 1, cell) + height -= 1 + } + subctx := ctx.Subcontext(x, y, width, height) + bordered.content.Draw(subctx) +} diff --git a/ui/grid.go b/ui/grid.go index 2091fc5..ede7d0c 100644 --- a/ui/grid.go +++ b/ui/grid.go @@ -6,10 +6,10 @@ import ( ) type Grid struct { - Rows []DimSpec - rowLayout []dimLayout - Columns []DimSpec - columnLayout []dimLayout + rows []GridSpec + rowLayout []gridLayout + columns []GridSpec + columnLayout []gridLayout Cells []*GridCell onInvalidate func(d Drawable) invalid bool @@ -21,17 +21,17 @@ const ( ) // Specifies the layout of a single row or column -type DimSpec struct { +type GridSpec struct { // One of SIZE_EXACT or SIZE_WEIGHT Strategy int - // 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 - // is distributed amonst the remaining dims weighted by this value. + // If Strategy = SIZE_EXACT, this is the number of cells this row/col shall + // occupy. If SIZE_WEIGHT, the space left after all exact rows/cols are + // measured is distributed amonst the remainder weighted by this value. Size int } // Used to cache layout of each row/column -type dimLayout struct { +type gridLayout struct { Offset int Size int } @@ -61,6 +61,16 @@ func (cell *GridCell) Span(rows, cols int) *GridCell { return cell } +func (grid *Grid) Rows(spec []GridSpec) *Grid { + grid.rows = spec + return grid +} + +func (grid *Grid) Columns(spec []GridSpec) *Grid { + grid.columns = spec + return grid +} + func (grid *Grid) Draw(ctx *Context) { invalid := grid.invalid if invalid { @@ -90,25 +100,25 @@ func (grid *Grid) Draw(ctx *Context) { func (grid *Grid) reflow(ctx *Context) { grid.rowLayout = nil grid.columnLayout = nil - flow := func(specs *[]DimSpec, layouts *[]dimLayout, extent int) { + flow := func(specs *[]GridSpec, layouts *[]gridLayout, 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 { + for _, spec := range *specs { + if spec.Strategy == SIZE_EXACT { + exact += spec.Size + } else if spec.Strategy == SIZE_WEIGHT { nweights += 1 - weight += dim.Size + weight += spec.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) + for _, spec := range *specs { + layout := gridLayout{Offset: offset} + if spec.Strategy == SIZE_EXACT { + layout.Size = spec.Size + } else if spec.Strategy == SIZE_WEIGHT { + size := float64(spec.Size) / float64(weight) size *= float64(extent - exact) layout.Size = int(math.Floor(size)) } @@ -116,8 +126,8 @@ func (grid *Grid) reflow(ctx *Context) { *layouts = append(*layouts, layout) } } - flow(&grid.Rows, &grid.rowLayout, ctx.Height()) - flow(&grid.Columns, &grid.columnLayout, ctx.Width()) + flow(&grid.rows, &grid.rowLayout, ctx.Height()) + flow(&grid.columns, &grid.columnLayout, ctx.Width()) grid.invalid = false } -- cgit v1.2.3