Layout is the process of determining the locations of figures in a drawing. This two step process includes marking figures as invalid (needing layout), and then validating the "branches" of figures that are invalid. Multiple updates to a drawing can result in multiple figures becoming invalid. To prevent intermediate states from being displayed to the user, Draw2d provides a deferred update strategy which integrates layout with native paint requests as well as figures requesting repaints. The result is that layouts occur all at once, after which the results are painted.
Figure delegates the task of placing children to their
LayoutManager. This allows layouts to be swapped and is also just
good separation of concerns. Layouts cannot be shared because they may cache
information about their owner.
Validation is almost synonymous with layout. A figure that needs to layout is
marked as invalid. All figures start in the invalid state when
constructed. At some point later when
is called, they mark themselves as valid and perform their layout. After layout,
the figure will then validate its children. Draw2d only uses validate to perform
layouts, but in theory it could be extended to perform any sort of potentially
expensive calculation that needs to be integrated with the update manager.
Most layouts need to query the children for their size constraints. IFigure provides methods for querying the minimum, preferred, and maximum sizes. A figure such as Label will have a preferred size based on its text or icon being displayed. If a figure contains other figures, then its preferred size will be based on how it would like to arrange its children. In this case, the size requests are forwarded to the layout manager.
Hints can be used when querying preferred and minimum size. For example, if the amount of available width is known, this width can be passed to a figure which may be wrapping a paragraph of text. The figure would then return the height and width necessary to wrap the paragraph to the given amount of space.
When a figure is changed in a way that affects its preferred size or layout,
revalidate(). Revalidation is the process of marking
yourself as invalid and requesting revalidate on your parent figure. This
process continues up the parent chain until the root figure (or some validation
root) adds itself to the update managers list of invalid figures. At a later
time, the update manager will go through its collection of invalid figures and
call validate() on them. In some situations, invalid figures may be added or
re-added during validation. This is fine as long as the dependencies do not
result in a never-ending cycle. The following image shows the chain of events:
|A changes happens to Fig 4 that affects its preferred size. It calls revalidate(), which walks up the parent chain marking figures as invalid until a "root" is reached which is reported to the update manager.||The update manager validates the invalid branches. Layout happens top-down. Note the Fig 5 was not invalid, but if Fig 2 changes its size as a result of laying out, the Fig 5 will mark itself as invalid and get validated as part of the same pass.|
In the above example, Fig 5 may have its size changed when Fig 2 performs its layout.
Normally figures layout in a top-down fashion. This means that figure has its bounds set before it lays out its children. Also, after it places its children, it then calls validate() on them in case their size changed, making them invalid. This is the same way that Composites work in SWT.
In some cases, the top-down process is modified. A common example is figures whose bounds must wrap around the bounds of their children. Connections
The other special layout case is found in the text package. Text figures must layout in two steps. First, they contribute fragments into paragraphs or blocks. These fragments may get reordered for bidirectional text. Also, their baselines and the overall alignment of each line may also be adjusted. The end of a line or block may only occur after a figure has finished its layout. So, the second layout pass is simply a finalization step in which the figures are told to now update their bounds based on their final fragment locations. Understanding this layout is no necessary for using the text package, but it does help in appreciating some of the problems solved by Draw2d's approach to layouts and coordinate systems.