1 | Added BAbstractLayout class, which is simillar to BAbstractLayoutItem.
|
---|
2 | It has only one member, fExplicitData, of the type BAbstractLayout::Proxy. This
|
---|
3 | is a pointer to an object which implements most of the necessary code for
|
---|
4 | each method BAbstractLayout provides. This way, when a BAbstractLayout has a
|
---|
5 | view, its fExplicitData object forwards methods to its view. When
|
---|
6 | BAbstractLayout does not have a view, its fExplicitData object actually holds
|
---|
7 | real data. I implemented archiving for this class while I was at it.
|
---|
8 |
|
---|
9 | Added BLayout::OwnerChanged(BView* was) hook, which is called in
|
---|
10 | BLayout::SetOwner(). I used this hook in BAbstractLayout, to change the proxy
|
---|
11 | type of its fExplicitData member.
|
---|
12 |
|
---|
13 | Added BLayoutItem::AttachedToLayout()
|
---|
14 | BLayoutItem::DetachedFromLayout(BLayout* was) hooks, which are called in
|
---|
15 | BLayoutItem::SetLayout(). I used these hooks in BLayout to implement view
|
---|
16 | targeting for viewless layouts, but there are other uses I can think of.
|
---|
17 |
|
---|
18 | Added BLayoutItem::AncestorVisibilityChanged(bool shown) hook, to allow for
|
---|
19 | hiding of views which are in a nested layout that has been SetVisible(false)'d.
|
---|
20 | Since BLayout has to remember this anyway, I added a
|
---|
21 | BLayout::AncestorsVisible() method which returns false if any ancestors are
|
---|
22 | hidden. Also to propagate this, I've added a BLayout::VisibilityChanged(bool)
|
---|
23 | method, which derived classes (or BLayout) can call.
|
---|
24 |
|
---|
25 | Added a state tracking int32 to the BLayout class (BLayout::fState), which
|
---|
26 | tracks the following states:
|
---|
27 | *LAYOUT_INVALID this layout has been invalidated, but has not been laid out
|
---|
28 | *LAYOUT_CACHE_INVALID this layout has been invalidate and not re-validated
|
---|
29 | via ResetLayoutInvalidation()
|
---|
30 | *LAYOUT_REQUIRED this layout may be valid, but has had its RequireLayout()
|
---|
31 | perhaps the layout has been moved, but not resized, or something similar.
|
---|
32 | *LAYOUT_IN_PROGRESS : self explanatory
|
---|
33 | *LAYOUT_ALL_CLEAR just a convenient flag == 0.
|
---|
34 |
|
---|
35 | there are also some masks that | some of those fields together for convenience.
|
---|
36 |
|
---|
37 | All in all, layouts work more or less like views in regards to layout
|
---|
38 | invalidation. Because a layout may be viewless, it must be able to function
|
---|
39 | independently as well. BLayout::Invalidate() also takes a bool param for
|
---|
40 | children, like BView::Invalidate().
|
---|
41 |
|
---|
42 | This leads to the next big change which is layout invalidation. My goal here was
|
---|
43 | that no matter how you trigger an invalidation, it should invalidate all the
|
---|
44 | right stuff. This presented a few challenges
|
---|
45 | * invalidating a view must invalidate its layout, and vice-versa.
|
---|
46 | * invalidating a view that is in a nested layout must invalidate not only
|
---|
47 | the view's Parent()'s layout, but also those layouts in between.
|
---|
48 | this can be accomplished two ways:
|
---|
49 | *through the BLayout::InvalidateLayoutsForView(), which would be called
|
---|
50 | with the view's Parent()'s layout as a param.
|
---|
51 | *by the view's layout, which will hopefully have been added as a
|
---|
52 | BLayoutItem (instead of using a BViewLayoutItem), and will know
|
---|
53 | the layout that view resides in, so invalidation can proceed as
|
---|
54 | normal. This is the prefferred method.
|
---|
55 | When possible, the layouts propagates the invalidation upwards, and those that
|
---|
56 | have views invalidate their views along the way. For views w/o layouts, the
|
---|
57 | view propagates the invalidation upwards until it either gets to the top, or
|
---|
58 | gets to a view with a layout, at which time it again becomes the layout's
|
---|
59 | responsibility. Also, with all this invalidating, we try to avoid Invalidating
|
---|
60 | layouts/views that have already been, since their derived implementation may
|
---|
61 | proceed blindly and do who knows what!
|
---|
62 |
|
---|
63 | I also added a private method to BView, _InvalidateParentLayout(), which is
|
---|
64 | called, for instance when a view is Hidden or Shown, it is also used in
|
---|
65 | BView::InvalidateLayout().
|
---|
66 |
|
---|
67 | Also new is that BLayouts hold a BLayoutContext, and can create one as well.
|
---|
68 | BLayout's LayoutItems() method does this, much like BView's Layout() method.
|
---|
69 |
|
---|
70 | BLayout has four layouting related methods:
|
---|
71 | LayoutItems() : new, creates a layout context and performs a
|
---|
72 | layout if required.
|
---|
73 | Relayout(bool immediate) : new, triggers a layout if there is not
|
---|
74 | one coming up, or if immediate == true.
|
---|
75 | _LayoutWithinContext(bool force, BLayoutContext*) : new
|
---|
76 | Handles the calling of fOwner->_Layout() and DerivedLayoutItems(), as
|
---|
77 | well as calling _LayoutWithinContext() on any nested layouts that need
|
---|
78 | it.
|
---|
79 | DerivedLayoutItems() : formerly LayoutView()
|
---|
80 |
|
---|
81 | If LayoutItems() is called on a BLayout w/ a view, it will ask its view to do a
|
---|
82 | layout, and be triggered that way, if not, it will do its own layout. We also
|
---|
83 | layout all nested layouts (that need it) in our layout.
|
---|
84 |
|
---|
85 | BLayout::Relayout(), is actually an implementation of the new
|
---|
86 | BLayoutItem::Relayout() virtual method, which is called in BSplitLayout,
|
---|
87 | for instance, when you wish to have an item layout now, assuming conditions are
|
---|
88 | right. This replaces the spot where BSplitLayout did this:
|
---|
89 | if (becameVisible) {
|
---|
90 | if (BView* itemView = item->View())
|
---|
91 | itemView->Layout(false);
|
---|
92 | }
|
---|
93 | with:
|
---|
94 | if (becameVisible)
|
---|
95 | item->Relayout(true);
|
---|
96 | which allows compatibility with nested (viewless) layouts.
|
---|
97 |
|
---|
98 | One of my goals was that adding a BLayout w/ a view to another layout will
|
---|
99 | result in pretty much equivalent beahaviour to what we currently expect from
|
---|
100 | BViewLayoutItem. To this end, when adding a BView to a layout, we check if the
|
---|
101 | view has a layout, and if so add that as an item, if not, we create a
|
---|
102 | BViewLayoutItem for the view. This helps us avoid calling
|
---|
103 | InvalidateLayoutsForView(), and save us a memory allocation too.
|
---|
104 |
|
---|
105 | Another method I've added to the BLayout class is LayoutArea(), which returns
|
---|
106 | a rect which represents the area this layout has been given for its items.
|
---|
107 | Without a view, LayoutArea() == Frame(), with a view,
|
---|
108 | LayoutArea() == Frame().OffsetToSelf(B_ORIGIN).
|
---|
109 |
|
---|
110 | BLayouts now have fOwner and fTarget BView* fields, if the layout has a view,
|
---|
111 | then fOwner == fTarget. For any nested layouts,
|
---|
112 | fTarget == Layout()->TargetView(). For now these are in two separate fields,
|
---|
113 | but they could be combined into one by adding a field to fState, I suppose.
|
---|
114 |
|
---|
115 | I have also added a BView::Private class for access to BView::fShowLevel in
|
---|
116 | BViewLayoutItem and BAbstractLayout.
|
---|
117 |
|
---|
118 | I also added a BView::_LayoutLeft method, since a layout may be deleted either
|
---|
119 | by its parent layout, or its 'owner' view, we need to avoid double frees.
|
---|
120 |
|
---|
121 | These are all the big changes, and I've also updated the existing layout
|
---|
122 | classes to reflect them.
|
---|
123 |
|
---|