Added BAbstractLayout class, which is simillar to BAbstractLayoutItem. It has only one member, fExplicitData, of the type BAbstractLayout::Proxy. This is a pointer to an object which implements most of the necessary code for each method BAbstractLayout provides. This way, when a BAbstractLayout has a view, its fExplicitData object forwards methods to its view. When BAbstractLayout does not have a view, its fExplicitData object actually holds real data. I implemented archiving for this class while I was at it. Added BLayout::OwnerChanged(BView* was) hook, which is called in BLayout::SetOwner(). I used this hook in BAbstractLayout, to change the proxy type of its fExplicitData member. Added BLayoutItem::AttachedToLayout() BLayoutItem::DetachedFromLayout(BLayout* was) hooks, which are called in BLayoutItem::SetLayout(). I used these hooks in BLayout to implement view targeting for viewless layouts, but there are other uses I can think of. Added BLayoutItem::AncestorVisibilityChanged(bool shown) hook, to allow for hiding of views which are in a nested layout that has been SetVisible(false)'d. Since BLayout has to remember this anyway, I added a BLayout::AncestorsVisible() method which returns false if any ancestors are hidden. Also to propagate this, I've added a BLayout::VisibilityChanged(bool) method, which derived classes (or BLayout) can call. Added a state tracking int32 to the BLayout class (BLayout::fState), which tracks the following states: *LAYOUT_INVALID this layout has been invalidated, but has not been laid out *LAYOUT_CACHE_INVALID this layout has been invalidate and not re-validated via ResetLayoutInvalidation() *LAYOUT_REQUIRED this layout may be valid, but has had its RequireLayout() perhaps the layout has been moved, but not resized, or something similar. *LAYOUT_IN_PROGRESS : self explanatory *LAYOUT_ALL_CLEAR just a convenient flag == 0. there are also some masks that | some of those fields together for convenience. All in all, layouts work more or less like views in regards to layout invalidation. Because a layout may be viewless, it must be able to function independently as well. BLayout::Invalidate() also takes a bool param for children, like BView::Invalidate(). This leads to the next big change which is layout invalidation. My goal here was that no matter how you trigger an invalidation, it should invalidate all the right stuff. This presented a few challenges * invalidating a view must invalidate its layout, and vice-versa. * invalidating a view that is in a nested layout must invalidate not only the view's Parent()'s layout, but also those layouts in between. this can be accomplished two ways: *through the BLayout::InvalidateLayoutsForView(), which would be called with the view's Parent()'s layout as a param. *by the view's layout, which will hopefully have been added as a BLayoutItem (instead of using a BViewLayoutItem), and will know the layout that view resides in, so invalidation can proceed as normal. This is the prefferred method. When possible, the layouts propagates the invalidation upwards, and those that have views invalidate their views along the way. For views w/o layouts, the view propagates the invalidation upwards until it either gets to the top, or gets to a view with a layout, at which time it again becomes the layout's responsibility. Also, with all this invalidating, we try to avoid Invalidating layouts/views that have already been, since their derived implementation may proceed blindly and do who knows what! I also added a private method to BView, _InvalidateParentLayout(), which is called, for instance when a view is Hidden or Shown, it is also used in BView::InvalidateLayout(). Also new is that BLayouts hold a BLayoutContext, and can create one as well. BLayout's LayoutItems() method does this, much like BView's Layout() method. BLayout has four layouting related methods: LayoutItems() : new, creates a layout context and performs a layout if required. Relayout(bool immediate) : new, triggers a layout if there is not one coming up, or if immediate == true. _LayoutWithinContext(bool force, BLayoutContext*) : new Handles the calling of fOwner->_Layout() and DerivedLayoutItems(), as well as calling _LayoutWithinContext() on any nested layouts that need it. DerivedLayoutItems() : formerly LayoutView() If LayoutItems() is called on a BLayout w/ a view, it will ask its view to do a layout, and be triggered that way, if not, it will do its own layout. We also layout all nested layouts (that need it) in our layout. BLayout::Relayout(), is actually an implementation of the new BLayoutItem::Relayout() virtual method, which is called in BSplitLayout, for instance, when you wish to have an item layout now, assuming conditions are right. This replaces the spot where BSplitLayout did this: if (becameVisible) { if (BView* itemView = item->View()) itemView->Layout(false); } with: if (becameVisible) item->Relayout(true); which allows compatibility with nested (viewless) layouts. One of my goals was that adding a BLayout w/ a view to another layout will result in pretty much equivalent beahaviour to what we currently expect from BViewLayoutItem. To this end, when adding a BView to a layout, we check if the view has a layout, and if so add that as an item, if not, we create a BViewLayoutItem for the view. This helps us avoid calling InvalidateLayoutsForView(), and save us a memory allocation too. Another method I've added to the BLayout class is LayoutArea(), which returns a rect which represents the area this layout has been given for its items. Without a view, LayoutArea() == Frame(), with a view, LayoutArea() == Frame().OffsetToSelf(B_ORIGIN). BLayouts now have fOwner and fTarget BView* fields, if the layout has a view, then fOwner == fTarget. For any nested layouts, fTarget == Layout()->TargetView(). For now these are in two separate fields, but they could be combined into one by adding a field to fState, I suppose. I have also added a BView::Private class for access to BView::fShowLevel in BViewLayoutItem and BAbstractLayout. I also added a BView::_LayoutLeft method, since a layout may be deleted either by its parent layout, or its 'owner' view, we need to avoid double frees. These are all the big changes, and I've also updated the existing layout classes to reflect them.