1 Theory of Operation
2 Interface
table-panel%
get-dimensions
set-dimensions
get-major-axis
set-major-axis
get-column-stretchability
set-column-stretchability
get-row-stretchability
set-row-stretchability
3 Example Table Panel
4 Issues and To Do

Table Panel

M. Douglas Williams <m.douglas.williams@gmail.com>

This library provides a table-panel% that specializes the MrEd panel% class to provide a panel that aligns its children to a grid. A simple demonstration program is also provided.

This is partially based on the Simple Grid Layout recipe by Danny Yoo on the Schematics Cookbook web site.

Everything in this library is exported by a single module:

 (require (planet williams/table-panel/table-panel))

    1 Theory of Operation

    2 Interface

    3 Example Table Panel

    4 Issues and To Do

1 Theory of Operation

+This section assumes you are familiar with the panel% class.

A table panel provides a panel that aligns its children on a grid. This is implemented by a new class table-panel% that specializes the panel% class.

Currently, the absolute dimensions of the grid are specified, as well as the major axis.

There is a fair amount of flexibility provided in terms of specifying how column widths and row heights can be adjusted (stretched) in response to resizing of the panel. This can be specified absolutely – that is, columns (or rows) can always be stretched or never be stretched, or based on the characteristics of the cells – that is, columns (or rows) can be stretched if any, or all, or its cells can be stretched.

The table panel’s behavior is specified by the container-size and place-children methods. The container-size method computes the size of the grid based on the minimum sizes of each of the grids columns and rows (as well as any border and spacing specified). The place-children method computes the column widths and row heights based on the actual space available, adjusting them as necessary, and places each child in the grid based on the alignment option of the grid, the child’s location (row and column) in the grid, and the child’s stretchability (horizontal and vertical).

2 Interface

table-panel% : class?

  superclass: panel%

A table-panel% object is a specialized panel% object that aligns its children on a grid.
Most of the following description is from the GUI: PLT Graphics Toolkit reference manual with additions as noted for table-panel%. Changes that are specific to the table-panel% class are in bold face.

(new table-panel% 
  [parent parent] 
  [[style style] 
  [vert-margin vert-margin] 
  [horiz-margin horiz-margin] 
  [border border] 
  [spacing spacing] 
  [alignment alignment] 
  [min-width min-width] 
  [min-height min-height] 
  [stretchable-width stretchable-width] 
  [stretchable-height stretchable-height] 
  [dimensions dimensions] 
  [major-axis major-axis] 
  [column-stretchability column-stretchability] 
  [row-stretchability row-stretchability]]) 
  (is-a?/c table-panel%)
  parent : 
(or/c (is-a?/c frame%) (is-a?/c dialog%)
      (is-a?/c panel%) (is-a?/c pane%))
  style : (listof (one-of/c 'border 'deleted)) = null
  vert-margin : (integer-in 0 10000) = 0
  horiz-margin : (integer-in 0 10000) = 0
  border : (integer-in 0 10000) = 0
  spacing : (integer-in 0 10000) = 0
  alignment : 
(list/c (one-of/c 'left 'center 'right)
        (one-of/c 'top 'center 'bottom))
   = '(center center)
  min-width : (integer-in 0 10000) = graphical-minimum-width
  min-height : (integer-in 0 10000) = graphical-minimum-height
  stretchable-width : any/c = #t
  stretchable-height : any/c = #t
  dimensions : 
(list/c exact-positive-integer?
        exact-positive-integer?)
 = '(1 1)
  major-axis : (one-of/c 'row 'column) = 'row
  column-stretchability : (one-of/c #t 'any 'every #f) = 'any
  row-stretchability : (one-of/c #t 'any 'every #f) = 'any
If the 'border style is specified, the window is created with a thin border (only in this case, the client size of the panel may be less than its total size). If style includes 'deleted, then the panel is created as hidden, and it does not affect its parent’s geometry; the panel can be made active later by calling parent’s add-child method.

For information about the enabled argument, see window<%>. For information about the horiz-margin and vert-margin arguments, see subarea<%>. For information about the border, spacing, and alignment arguments, see area-container<%>. For information about the min-width, min-height, stretchable-width, and stretchable-height arguments, see area<%>.

The dimensions argument specifies the number of rows and columns in the grid. There should be rows × columns children of the panel. The default is '(1 1).

The major-axis argument specifies the major axis for in the grid. This specifies the order in which the children are placed in the grid. If major-axis is 'row, then all of the columns in a row are placed before moving to the next row. If major-axis is 'column, then all of the rows for a column are placed before moving to the next column. The default is 'row.

For example, if dimensions is '(2 2), then there should be four children, say, child0, child1, child2, and child3. If major-axis is 'row, then child0 is placed in row0 column0 – the upper left cell, child1 is placed in row0 column1 – the upper right cell, child2 is placed in row1 column0 – the lower left cell, and child2 is placed in row1 column1 – the lower right cell. If major-axis is 'column, then child0 is placed in row0 column0 – the upper left cell, child1 is placed in row1 column0 – the lower left cell, child2 is placed in row0 column1 – the upper right cell, and child2 is placed in row1 column1 – the lower right cell.

The column-stretchability and row-stretchability arguments specify how column widths and row heights can be adjusted when additional space (above the minimum sizes) is available:

  • #t – Column widths (or row heights) are always stretchable.

  • 'any – The width of a column (or the height of a row) is stretchable if any of its rows is stretchable horizontally (or any of its columns are stretchable vertically). That is, a column or row can stretch if any of its cells can take advantage of the extra space.

  • 'every – The width of a column (or the height of a row) is stretchable if all of its rows is stretchable horizontally (or all of its columns are stretchable vertically). That is, a column or row can stretch if all of its cells can take advantage of the extra space.

  • #f – Column widths (or row heights) are never stretchable.

(send a-table-panel get-dimensions)  
exact-positive-integer?
exact-positive-integer?
Returns the dimensions of the table panel object as two values, the number of rows and the number of columns.

(send a-table-panel set-dimensions n-rows    
  n-columns)  any
  n-rows : exact-positive-integer
  n-columns : exact-positive-integer
Sets the dimensions of the table panel object to n-rows and n-columns.

(send a-table-panel get-major-axis)  (one-of/c 'row 'column)
Returns the major axis for the table panel object.

(send a-table-panel set-major-axis major-axis)  any
  major-axis : (one-of/c 'row 'column)
Sets the major axis for the table panel object to major-axis.

(send a-table-panel get-column-stretchability)
  (one-of/c #t 'any 'every #f)
Returns the column stretchability for the table panel object.

(send a-table-panel set-column-stretchability stretchability)
  any
  stretchability : (one-of/c #t 'any 'every #f)
Sets the column stretchability for the table panel object to stretchability.

(send a-table-panel get-row-stretchability)
  (one-of/c #t 'any 'every #f)
Returns the row stretchability for the table panel object.

(send a-table-panel set-row-stretchability stretchability)
  any
  stretchability : (one-of/c #t 'any 'every #f)
Sets the row stretchability for the table panel object to stretchability.

3 Example Table Panel

This section contains an example that uses table panel examples.

  #lang scheme/gui
  
  ;  Table panel example.
  ;  This example displays a table panel containing four more
  ;  table panels anddemonstrates some column and row stretch-
  ;  ability options.
  
  (require (planet williams/table-panel/table-panel))
  
  ;  The top-level frame
  (define frame
    (instantiate frame%
      ("Test")))
  
  ;  A 2 x 2 table panel
  (define table-panel
    (instantiate table-panel%
      (frame)
      (alignment '(center center))
      (dimensions '(2 2))))
  
  ;  Fill each cell with a table panel displaying a simulated keypad.
  (for ((i (in-range 4)))
    (let ((child (instantiate table-panel%
                   (table-panel)
                   (style '(border))
                   (dimensions '(4 3))
                   (column-stretchability (if (memq i '(0 1)) #t #f))
                   (row-stretchability (if (memq i '(0 2)) #t #f)))))
      (for ((j '(1 2 3
                 4 5 6
                 7 8 9
                 * 0 |#|)))
        (instantiate button%
          ((format "~a" j) child)
          (stretchable-width #t)
          (stretchable-height #t)
          (callback
           (lambda (button event)
             (printf "~a~n" (send button get-label))))))))
  
  ;  Show the top-level frame.
  (send frame show #t)

The following image shows the output as originally sized by PLT Scheme based on the minimum sizes of the elements.

The next image shows the output after resizing the frame. The upper left panel specifies both row and column stretchability, the upper right panel specifies only column stretchability, the lower left panel specifies only row stretchability, and the lower right panel specified neither column nor row stretchability.

Note that the outer 2 × 2 table panel specifies the default column and row stretchability of 'any, which, in this case, allows its columns and rows to stretch because (at least one of) each of its columns and rows can stretch.

4 Issues and To Do

It isn’t really necessary to specify both the number of rows and the number of columns. All we need to know is the major axis and the dimensionality of the minor axis. The dimensionality of the major axis can be determined using the number of children and the dimensionality of the minor axis – (ceiling (/ (length children) n-minor-axis)). We could allow one of the dimensions to be specified by a placeholder. For example, (dimensions (* 3)) would specify a row major table with each row having three columns. Similar changes would have to be made for get-dimensions and set-dimensions. We would also have to add some error checking to make sure the major axis is compatible with the dimensions.