From d824e549f19059e5801beb1fa30605ce93e3e15c Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Fri, 15 Aug 2014 19:33:53 -0400 Subject: [PATCH] Adjusted Grid to be like new Stack. Automatically made Labels in Grids filling. --- redo/grid.go | 78 +++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/redo/grid.go b/redo/grid.go index b303a2e..ace7ee3 100644 --- a/redo/grid.go +++ b/redo/grid.go @@ -6,8 +6,6 @@ import ( "fmt" ) -// TODO Grids on GTK+ will not respect non-standalone Labels unless SetFilling() - // A Grid arranges Controls in a two-dimensional grid. // The height of each row and the width of each column is the maximum preferred height and width (respectively) of all the controls in that row or column (respectively). // Controls are aligned to the top left corner of each cell. @@ -16,8 +14,23 @@ import ( // One Control can be marked as "stretchy": when the Window containing the Grid is resized, the cell containing that Control resizes to take any remaining space; its row and column are adjusted accordingly (so other filling controls in the same row and column will fill to the new height and width, respectively). // A stretchy Control implicitly fills its cell. // All cooridnates in a Grid are given in (row,column) form with (0,0) being the top-left cell. -type Grid struct { - created bool +// +// As a special rule, to ensure proper appearance, non-standalone Labels are automatically made filling. +type Grid interface { + Control + + // SetFilling marks the given Control of the Grid as filling its cell instead of staying at its preferred size. + // It panics if the given coordinate is invalid. + SetFilling(row int, column int) + + // SetStretchy marks the given Control of the Grid as stretchy. + // Stretchy implies filling. + // Only one control can be stretchy per Grid; calling SetStretchy multiple times merely changes which control is stretchy. + // It panics if the given coordinate is invalid. + SetStretchy(row int, column int) +} + +type grid struct { controls [][]Control filling [][]bool stretchyrow, stretchycol int @@ -33,7 +46,7 @@ type Grid struct { // control00, control01, control02, // control10, control11, control12, // control20, control21, control22) -func NewGrid(nPerRow int, controls ...Control) *Grid { +func NewGrid(nPerRow int, controls ...Control) Grid { if len(controls)%nPerRow != 0 { panic(fmt.Errorf("incomplete grid given to NewGrid() (not enough controls to evenly divide %d controls into rows of %d controls each)", len(controls), nPerRow)) } @@ -50,10 +63,13 @@ func NewGrid(nPerRow int, controls ...Control) *Grid { ch[row] = make([]int, nPerRow) for x := 0; x < nPerRow; x++ { cc[row][x] = controls[i] + if l, ok := controls[i].(Label); ok && !l.isStandalone() { + cf[row][x] = true + } i++ } } - return &Grid{ + return &grid{ controls: cc, filling: cf, stretchyrow: -1, @@ -65,28 +81,14 @@ func NewGrid(nPerRow int, controls ...Control) *Grid { } } -// SetFilling marks the given Control of the Grid as filling its cell instead of staying at its preferred size. -// This function cannot be called after the Window that contains the Grid has been created. -// It panics if the given coordinate is invalid. -func (g *Grid) SetFilling(row int, column int) { - if g.created { - panic(fmt.Errorf("Grid.SetFilling() called after window create")) - } +func (g *grid) SetFilling(row int, column int) { if row < 0 || column < 0 || row > len(g.filling) || column > len(g.filling[row]) { panic(fmt.Errorf("coordinate (%d,%d) out of range passed to Grid.SetFilling()", row, column)) } g.filling[row][column] = true } -// SetStretchy marks the given Control of the Grid as stretchy. -// Stretchy implies filling. -// Only one control can be stretchy per Grid; calling SetStretchy multiple times merely changes which control is stretchy. -// This function cannot be called after the Window that contains the Grid has been created. -// It panics if the given coordinate is invalid. -func (g *Grid) SetStretchy(row int, column int) { - if g.created { - panic(fmt.Errorf("Grid.SetFilling() called after window create")) - } +func (g *grid) SetStretchy(row int, column int) { if row < 0 || column < 0 || row > len(g.filling) || column > len(g.filling[row]) { panic(fmt.Errorf("coordinate (%d,%d) out of range passed to Grid.SetStretchy()", row, column)) } @@ -95,27 +97,15 @@ func (g *Grid) SetStretchy(row int, column int) { // don't set filling here in case we call SetStretchy() multiple times; the filling is committed in make() below } -func (g *Grid) make(window *sysData) error { - // commit filling for the stretchy control now (see SetStretchy() above) - if g.stretchyrow != -1 && g.stretchycol != -1 { - g.filling[g.stretchyrow][g.stretchycol] = true - } else if (g.stretchyrow == -1 && g.stretchycol != -1) || // sanity check - (g.stretchyrow != -1 && g.stretchycol == -1) { - panic(fmt.Errorf("internal inconsistency in Grid: stretchy (%d,%d) impossible (one component, not both, is -1/no stretchy control) in Grid.make()", g.stretchyrow, g.stretchycol)) - } - for row, xcol := range g.controls { - for col, c := range xcol { - err := c.make(window) - if err != nil { - return fmt.Errorf("error adding control (%d,%d) to Grid: %v", row, col, err) - } +func (g *grid) setParent(parent *controlParent) { + for _, col := range s.controls { + for _, c := range col { + c.setParent(parent) } } - g.created = true - return nil } -func (g *Grid) allocate(x int, y int, width int, height int, d *sysSizeData) (allocations []*allocation) { +func (g *grid) allocate(x int, y int, width int, height int, d *sysSizeData) (allocations []*allocation) { max := func(a int, b int) int { if a > b { return a @@ -125,7 +115,9 @@ func (g *Grid) allocate(x int, y int, width int, height int, d *sysSizeData) (al var current *allocation // for neighboring - // TODO return if nControls == 0? + if len(controls) == 0 { + return nil + } // 0) inset the available rect by the needed padding width -= (len(g.colwidths) - 1) * d.xpadding height -= (len(g.rowheights) - 1) * d.ypadding @@ -191,7 +183,7 @@ func (g *Grid) allocate(x int, y int, width int, height int, d *sysSizeData) (al } // filling and stretchy are ignored for preferred size calculation -func (g *Grid) preferredSize(d *sysSizeData) (width int, height int) { +func (g *grid) preferredSize(d *sysSizeData) (width int, height int) { max := func(a int, b int) int { if a > b { return a @@ -228,10 +220,10 @@ func (g *Grid) preferredSize(d *sysSizeData) (width int, height int) { return width, height } -func (g *Grid) commitResize(c *allocation, d *sysSizeData) { +func (g *grid) commitResize(c *allocation, d *sysSizeData) { // this is to satisfy Control; nothing to do here } -func (g *Grid) getAuxResizeInfo(d *sysSizeData) { +func (g *grid) getAuxResizeInfo(d *sysSizeData) { // this is to satisfy Control; nothing to do here }