views:

124

answers:

1

I've noticed that Android, WPF, and Silverlight all follow a two-pass layout pattern. There's a recursive Measure() method that gets called to size the element, possibly multiple times. Then a recursive Layout/Arrange() method is called which lays out the exact positions of children in their parent control, and will also set the final size of the control.

My question: why is this split into two passes, especially when, for some types of controls, Measure() can't compute the actual size of a control without actually laying out the positions of the children? Is there some type of layout minority case that is made possible by this?

I'm trying to create my own UI toolkit, and I'm currently leaning toward a one-pass Layout() pattern, but I'd like to be convinced whether this is wise or not.

Thanks for reading this :)

Sean

+4  A: 

The reason for the two passes is that any element in the structure can influence the remaining available space of the others.

Some element wish to take the largest possible space while others have fixed dimensions. You can also have elements with only a max width set. It creates an equation that can not be solved in one pass.

The different panels in the hierarchy ask the elements what size they need in the first pass, then distribute the space among them according to each panel's nature, and finally informs each element of its allocated space.

EDIT: Some more explanations

The main drawback of a single pass layout is that you are handling each element sequentially. A first element takes a certain amount of space and the others take the rest. Why is this element the first? Try your algorithm with different element order, and you will have different resulting layouts.

A two pass layout simulates a parallel behavior where each element influences the whole layout.

Mart
It's the last bit, "finally informs each element of its allocated space", that is the important part. The widget manager doesn't let the controls size themselves, it just lets them make hints.
mos
Hmm.. I get how children can be greedy about the size they get allocated, and then it's up to the parent to dole out the right amount of space. But, you can achieve this in a single-pass algorithm by doing a measure() of each child, and then a final layout() for each child, all under the parent's layout() call. This would still be a single recursion of the tree, but with two passes for each set of children. Am I right in thinking that this achieves the same end as the two-pass approach, but it's just less efficient?
Sean
From the grandparent's perspective, the parent is just another child it wants to measure() and layout(). ;)
Bubblewrap
Ok, now I understand. Thanks, Mart!
Sean