TIP 37: Uniform Rows and Columns in Grid

Bounty program for improvements to Tcl and certain Tcl packages.
Author:         Peter Spjuth <peter.spjuth@space.se>
Author:         Kevin Kenny <kennykb@acm.org>
State:          Final
Type:           Project
Vote:           Done
Created:        19-Jun-2001
Tcl-Version:    8.4


This TIP proposes to add a -uniform option to grid rowconfigure and grid columnconfigure so as to make it easier to create layouts where cells are constrained to have identical dimensions.


The geometry managers in Tk are very powerful and can do most things needed to layout a GUI. One thing that is tricky to do though is to put widgets in rows or columns of the same width. This would be useful for example to layout a row of buttons symmetrically. This could easily be done with the grid manager if an additional option is added.


Anywhere column is used below, the same applies to row too.

A new option, -uniform, is added to grid columnconfigure. The option takes an arbitrary string, the default value being the empty string. Any column with a non-empty value will be grouped with other columns with the same value. Each column in a group will get the size k*-weight (in this aspect a -weight value of 0 is used as 1) , where k is set so that no column becomes smaller. E.g., if all columns in a group have the same -weight they will all get the size of the largest member.

In the grid algorithm -uniform and -weight will be used as specified above in the calculation of the requested size (the first step in the description of the grid algorithm in grid(n)), but for the distribution of extra size (second step) only -weight will be considered. This means that the second step is not altered at all by this.


Getting symmetry in a layout today is possible but even for a simple case it gets tricky if you want more than a half decent result. Message catalogs changing strings and options databases changing appearances can make a GUI very dynamic and normally you never need to count pixels since geometry managers do that for you. For symmetry though you suddenly have to handle pixel details yourself, details that are handled so much better by a geometry manager. With a -uniform option, grid can do symmetry for you in a simple way that takes care of all the details.

To only consider -weight in the extra size distribution is mainly a matter of simplicity. It gives a simpler algorithm that is both easier to explain to the user and to code.

To uphold the uniform property it would be needed to force any zero -weight value in a group where any non-zero -weight exists to be set to one before doing the resize calculations. A bit complicated and the only benefit for the user would be to only have to specify -weight for one column in a group. But in practice this is hardly no gain at all since a typical usage looks like this:

grid columnconfigure . {0 1 2} -uniform a -weight 1

I'm not sure if someone would have a use for the effect you would get by mixing zero and non-zero weights in a group but this leaves you the freedom to do so.


To clarify how -uniform affects a grid here are some examples.

button .b1 -text a
button .b2 -text b
button .b3 -text example
button .b4 -text xyzzy
grid .b1 .b2 .b3 .b4 -sticky news
grid columnconfigure . {0 1 2 3} -uniform a -weight 1

Initially all columns will be equal and if resized, all columns will change equally.

Initial: |[   a   ]|[   b   ]|[example]|[ xyzzy ]|
Shrunk:  |[  a  ]|[  b  ]|[xampl]|[xyzzy]|

Another example. Instead we do:

grid columnconfigure . {0 2} -uniform a -weight 1
grid columnconfigure . {2}   -weight 2
grid columnconfigure . {1 3} -uniform b -weight 0
grid columnconfigure . {1}   -weight 1

Initially column 0 will be half the size of column 2, columns 1 and 3 will be equal. Resizing will affect colums 0 and 1 half of how column 2 is affected. Column 3 is static.

Initial:  |[ a ]|[  b  ]|[example]|[xyzzy]|
Shrunk:   |[a]|[ b ]|[amp]|[xyzzy]|
Expanded: |[  a  ]|[   b   ]|[  example  ]|[xyzzy]|


A quick try shows that this is fairly straightforward to implement. If the option is not used the memory cost is a Tk_Uid field (or similar if some other mechanism than Tk_Uid is used) in the column slot structure to hold the option, and the CPU overhead is small.

Summary of Objections

  • Kevin Kenny raised the issue that the proposed implementation uses a Tk_Uid for the "uniform" key, leading to potential resource leaks. Subsequent discussion has convinced him that the potential for trouble is small; in any case, it need not block approval. The ensuing discussion veered off into a long thread about reclaiming the memory used for Tcl_Obj structures; the thread is not pertinent to this TIP.

  • George Howlett questioned the need for this feature, citing the lack of compelling examples. The original author replied with the example of a dialog holding multiple buttons containing text of different widths, and showed how the Tcl code to manage such a dialog is clumsy.

  • George Howlett raised the issue of a detailed specification of the behavior of -uniform when insufficient space is available to satisfy the request. The original author added clarification in the "Examples" section, and supplied additional examples in discussions on the mailing list http://www.geocrawler.com/archives/3/7375/2001/7/50/6211900/ .

  • George Howlett also asserted that the desired semantics can be achieved with Tcl code that either lays out a fixed configuration of the widget (with, for example, the -minsize option of grid columnconfigure) or responds to the event. Probably the best summary of the ensuing discussion is that we need to strike a balance between richness of the API and simplicity of the implementation.


This document has been placed in the public domain.