Constraint layout: more details

By default, windows do not have a wxLayoutConstraints object. In this case, much layout must be done explicitly, by performing calculations in OnSize members, except for the case of frames that have exactly one subwindow (not counting toolbar and statusbar which are also positioned by the frame automatically), where wxFrame::OnSize takes care of resizing the child to always fill the frame.

To avoid the need for these rather awkward calculations, the user can create a wxLayoutConstraints object and associate it with a window with wxWindow::SetConstraints. This object contains a constraint for each of the window edges, two for the centre point, and two for the window size. By setting some or all of these constraints appropriately, the user can achieve quite complex layout by defining relationships between windows.

In wxWidgets, each window can be constrained relative to either its siblings on the same window, or the parent. The layout algorithm therefore operates in a top-down manner, finding the correct layout for the children of a window, then the layout for the grandchildren, and so on. Note that this differs markedly from native Motif layout, where constraints can ripple upwards and can eventually change the frame window or dialog box size. We assume in wxWidgets that the user is always `boss' and specifies the size of the outer window, to which subwindows must conform. Obviously, this might be a limitation in some circumstances, but it suffices for most situations, and the simplification avoids some of the nightmarish problems associated with programming Motif.

When the user sets constraints, many of the constraints for windows edges and dimensions remain unconstrained. For a given window, the wxWindow::Layout algorithm first resets all constraints in all children to have unknown edge or dimension values, and then iterates through the constraints, evaluating them. For unconstrained edges and dimensions, it tries to find the value using known relationships that always hold. For example, an unconstrained width may be calculated from the left and right edges, if both are currently known. For edges and dimensions with user-supplied constraints, these constraints are evaluated if the inputs of the constraint are known.

The algorithm stops when all child edges and dimension are known (success), or there are unknown edges or dimensions but there has been no change in this cycle (failure).

It then sets all the window positions and sizes according to the values it has found.

Because the algorithm is iterative, the order in which constraints are considered is irrelevant, however you may reduce the number of iterations (and thus speed up the layout calculations) by creating the controls in such order that as many constraints as possible can be calculated during the first iteration. For example, if you have 2 buttons which you'd like to position in the lower right corner, it is slightly more efficient to first create the second button and specify that its right border IsSameAs(parent, wxRight) and then create the first one by specifying that it should be LeftOf() the second one than to do in a more natural left-to-right order.

ymasuda 平成17年11月19日