aerc

Working clone of aerc-mail.org
git clone git://git.danielmoch.com/aerc.git
Log | Files | Refs | README | LICENSE

commit f0791d4ba720c4cfa1d3f90c99296584aa878cd9
parent 7f67162f43374188f619e571c6d614626a24127a
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 17 Feb 2018 20:11:58 -0500

Add borders widget

Diffstat:
Mcmd/aerc/main.go | 33+++++++++++++++++----------------
Aui/borders.go | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mui/grid.go | 56+++++++++++++++++++++++++++++++++-----------------------
3 files changed, 123 insertions(+), 39 deletions(-)

diff --git a/cmd/aerc/main.go b/cmd/aerc/main.go @@ -52,22 +52,23 @@ func main() { tabs.Add(fill('★'), "白い星") tabs.Add(fill('☆'), "empty stars") - grid := ui.NewGrid() - grid.Rows = []ui.DimSpec{ - ui.DimSpec{ui.SIZE_EXACT, 1}, - ui.DimSpec{ui.SIZE_WEIGHT, 1}, - ui.DimSpec{ui.SIZE_WEIGHT, 1}, - ui.DimSpec{ui.SIZE_EXACT, 1}, - } - grid.Columns = []ui.DimSpec{ - ui.DimSpec{ui.SIZE_WEIGHT, 3}, - ui.DimSpec{ui.SIZE_WEIGHT, 2}, - } - grid.AddChild(tabs.TabStrip).At(0, 0).Span(1, 2) - grid.AddChild(tabs.TabContent).At(1, 0).Span(1, 2) - grid.AddChild(fill('.')).At(2, 0).Span(1, 2) - grid.AddChild(fill('•')).At(2, 1).Span(1, 1) - grid.AddChild(fill('+')).At(3, 0).Span(1, 2) + grid := ui.NewGrid().Rows([]ui.GridSpec{ + ui.GridSpec{ui.SIZE_EXACT, 1}, + ui.GridSpec{ui.SIZE_WEIGHT, 1}, + ui.GridSpec{ui.SIZE_EXACT, 1}, + }).Columns([]ui.GridSpec{ + ui.GridSpec{ui.SIZE_EXACT, 20}, + ui.GridSpec{ui.SIZE_WEIGHT, 1}, + }) + + // TODO: move sidebar into tab content, probably + // sidebar placeholder: + grid.AddChild(ui.NewBordered( + fill('.'), ui.BORDER_RIGHT)).At(1, 0).Span(2, 1) + grid.AddChild(tabs.TabStrip).At(0, 1) + grid.AddChild(tabs.TabContent).At(1, 1) + // ex line placeholder: + grid.AddChild(fill('+')).At(2, 1) _ui, err := ui.Initialize(conf, grid) if err != nil { diff --git a/ui/borders.go 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 @@ -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 }