Motivation and Overview
Layout support Widgets
Motivation and Overview
Because the implementation of the UI Engine can be based on different widget sets, different look-and-feels, and different fonts the layout specification attempts to be visually appealing in different environments. Explicit placement of widgets doesn't work well in this situation because the widget's sizes are not known in advance. Moreover, the precise horizontal and vertical alignment of widgets and the specification of the resize behaviour is a tedious task even with the help of the Composition Editor. This led to the integration of layout management in ULC, based on a hierarchical and high level layout description rather than on the explicit placement of widgets, and which handles resize
The ULC layout widgets employ three basic layout strategies:
Draws a borderline or leaves a margin around a single widget. This layout is used by Border,Shell,and Page.
Aligns widgets in a row/column fashion. This layout is used
by the classesBox,HBox,VBox.
Stacks widgets on top of each other. Only the topmost widget is visible. This layout is used byNotebook and Pagebook.
All widgets using the first two layout strategies have the notion of a "cell" and "cell alignment". A cell is a space which can be empty or can accommodate a single widget. The size of a cell is always equal to or larger than the minimum size of the enclosed widget (if any). If the cell is larger than the minimum size the cell alignment specifies what to do with the extra space. Possible options are to expand the widget until it fills the cell completely or to align the widget within its cell (Figure 1 shows all possible cell alignments).
Figure 1: All 16 cell
alignments for a widget (W) within its cell (dashed box)
Layout support Widgets
The simplest example for a cell is the Border widget (GroupBox widget in Smalltalk) (Figure 2). A Border has a single cell and draws a borderline and title around it. The size of the cell is determined based on the natural size of the enclosed widget. If the Border is made larger the alignment is used to determine how to align the content widget.
Figure 2: Border/GroupBox widget
The Shell and Page widgets use the Border layout to create a margin around their contents areas.
The Box widget lays out cells in a 2 dimensional grid separated by horizontal and vertical gaps (Figure 3). The width of a column is determined by the maximum width of all widgets in the corresponding
column. The height of a row is determined by the maximum height of all widgets in that row.
Figure 3: A 3x2 Box
If the Box is made larger than its minimal size then the extra space is distributed evenly over all expandable rows or columns. A row or column is expandable if at least one cell attribute in that row (or column) is
expand. If no expandable rows or columns exist, the box is centered within its widget bounds.
Box cells can span multiple columns or rows (Figure 4). In this case the cell alignment applies just as for the spanning cell. If the spanning specification results in overlapping cells
the (visual) result is undefined.
Figure 4: a 3x4 Box
with two spanning cells
The Pagebook piles Page widgets on top of each other and shows only the topmost Page (a Page widget is just a margin around another widget). The size of the Pagebook is determined by the maximum size of all Pages. A Pagebook can be used to implement dynamic layout, that is, to switch between different widget sub-trees programmatically.
A Notebook is very similar to a Pagebook but adds a small tab with a title on every page (Figure 5). The tab is used to switch between pages interactively.
Figure 5: A Notebook with 3 pages
Using Layout Widgets
ULC Layout is based on a few fundamental concepts. Combining these layout strategies recursively enables not only sophisticated layouts but also automatic resize behavior. There are many ways to solve a given layout problem and it is not generally intuitively clear which approach is the least complex and the most appropriate. The following paragraphs outline an overall strategy for designing and implementing
a layout using ULC's layout concepts. In addition we provide some guidelines and tips for
cases with several alternative solutions.
ULC's layout paradigm is based on hierarchies of nested Boxes.
You are not able to implement layouts by explicit positioning and resizing of widgets, nor can you base your layouts on the "FormWidget" mechanism from Motif. Instead you have to design and build a tree of one or two dimensional boxes. We believe that Box layout is easier to use and therefore, layouts based on Boxes are much easier to understand and maintain.
Try to plan and design the structure of your layout in advance.
Even when using the Composition Editor layout design is not just painting dialog controls on a drawing surface. For almost every layout a resize strategy has to be defined: which elements should grow if the containing window is enlarged? What happens in a localized version of the layout when a supported language has different string length requirements? Another requirement is esthetics: how do we keep controls nicely grouped and aligned and not spaced too far apart even if everything may resize drastically?
You should have answers for most of these questions before implementing the layout in code or in the Composition Editor.
Figure 6: Nested Boxes or a 2-Dimensional Box?
Start from top to bottom.
Identify the top level elements or groups of elements. Decide whether to use a horizontal, vertical or two-dimensional Box layout. Sometimes this is not as simple as it seems. For example: is the top-level layout of Figure 6 a vertical Box with two rows each containing a
horizontal Box (see Figure 7 right) or is it a 2x2 Box (see Figure 7 left)?
Figure 7: Possible Structures for Example from Figure 6
Sometimes an answer can be found by asking whether elements should be kept aligned across horizontal rows. For example whether the label "Dossier" should line up with the find entry field. If yes a 2x2 Box has to be used. If not - which appears to be more realistic in this case - it is better to nest independent horizontal boxes within one vertical Box.
Avoid deep nesting.
Always try to keep your layout structures simple. The most important way to achieve this goal is by avoiding too deeply nested structures. So using two dimensional Boxes instead of nesting Boxes simplifies the layout. But this goal sometimes conflicts with a pleasing layout because the two dimensional box forces elements into a rigid grid thereby aligning elements which need not or should not align(see example from Figure 14). We describe below how spanning makes the use of 2 dimensional Boxes much more flexible.
With spanning it is possible to merge adjacent cells in order to form larger cells. This is useful if you want to align components with different size requirements within an overall grid. Without spanning, the width and/or height of rows and columns is determined by the widest or tallest element. With spanning, exceptionally large elements can grow into neighboring cells without making their containing rows or columns too wide or tall (see Figure 8).
One way to implement the following example (Figure 8) is to nest a 1x3 Box inside a 3x2 Box. With spanning it is possible to employ a 3x4 Box and avoid nesting altogether.
Figure 8: Using Spanning
Spanning is a very powerful mechanism. You can use a grid layout which improves the overall aesthetics because elements are aligned and their spacing is more uniform. On the other hand you are not forced to make everything the same size because you can span elements across multiple grid cells. In addition grid spanning makes it easy to have elements with different sizes always use multiples of some base cell size
which is visually more appealing than having elements with various unrelated sizes (this concept is called a
Build the nested grid first, fill in the details later.
Because constructing Box hierarchies is simpler than rearranging them, build and verify (test) the complete Box layout before filling in and adjusting the settings of all the non-layout widgets (Labels, Buttons, etc.).