See: Description
Interface | Description |
---|---|
LayoutComponent |
The LayoutComponent interface takes the component role in the composition
pattern.
|
Class | Description |
---|---|
LayoutBuilder |
The LayoutBuilder is a variant of the builder pattern.
|
LayoutGap |
Gaps are represented as JPanels with their preferred size set
to the required gap size.
|
LayoutLeaf |
A LayoutLeaf wraps a single UI component that can
span multiple rows and columns and be resizable.
|
LayoutPanel |
A LayoutPanel contains a grid of LayoutComponents, each of which
can occupy a rectangle of cells.
|
LayoutRow |
A LayoutRow is a list of LayoutComponents.
|
The column layout package simplifies programmatic layout construction. It uses a grid paradigm, with a known number of fixed or resizable rows and columns. In this grid, a component occupies a rectangle of cells and is only resizable if at least one of the rows or columns it occupies is resizable. This is similar to GridBagLayout, however the aim is to abstract the underlying layout engine from the creation of the layout rather than providing a new layout manager.
A useful usability heuristic is to minimise the number of columns presented to the user. Thus controls should be aligned horizontally. Some layouts, for example GridBagLayout, have sufficient power to represent this. However, the associated complexity of the constraints means that nested panels are frequently used as an easier solution. For example:
A: | multi-line text field | B: | text field | |
C: | text field |
might be represented as:
A: | multi-line text field |
|
Unfortunately, aligning across panels is hard but the above is is useful because the rowspans of each component are implicit.
To get the best of both using nested panels and minimising the number of columns the column layout package introduces the classes LayoutPanel, LayoutLeaf and LayoutGap. These implement the LayoutComponent interface, a composite pattern, and allow us to abstract the layout from the UI components. LayoutLeaves wrap UI components allowing them to be added to LayoutPanels. Adding works in a 'typewriter' fashion: left to right with a newline operation. Thus pseudocode for the above example is:
rootPanel = new LayoutPanel(); rootPanel.add(new LayoutLeaf(A:)); rootPanel.add(new LayoutLeaf(multi-line text field)); rootPanel.add(new LayoutGap(HORIZONTAL)); subPanel = new LayoutPanel(); subPanel.add(new LayoutLeaf(B:)); subPanel.add(new LayoutLeaf(text field)); subPanel.nl(); subPanel.add(new LayoutLeaf(C:)); subPanel.add(new LayoutLeaf(text field)); rootPanel.add(subPanel);
Although the LayoutComponent implementations abstract layout creation, clients still need to do a lot of work and instantiate layout classes. To make life easier the builder pattern is used. However with the emphasis on multiple classes taking the director role rather than the builder role, the latter is not an interface. The example layout becomes:
lb = new LayoutBuilder(); lb.add(A:); lb.add(multi-line text field); lb.addHGap(); lb.pushPanel(); lb.add(B:); lb.add(text field); lb.nl(); lb.add(C:); lb.add(text field); lb.popPanel();
Layout building becomes a language of operations.
Once the layout is fully defined it can be flattened to a grid and UI constraints determined. The major steps are:
panel = new JPanel(); lb.addToPanel(panel);