Index: src/preferences/keymap/KeymapWindow.cpp
===================================================================
--- src/preferences/keymap/KeymapWindow.cpp (revision 38092)
+++ src/preferences/keymap/KeymapWindow.cpp (working copy)
@@ -508,7 +508,8 @@
.Add(new BStringView("system", B_TRANSLATE("System:")))
.Add(systemScroller, 3)
.Add(new BStringView("user", B_TRANSLATE("User:")))
- .Add(userScroller);
+ .Add(userScroller)
+ .TopView();
}
Index: src/preferences/backgrounds/BackgroundsView.cpp
===================================================================
--- src/preferences/backgrounds/BackgroundsView.cpp (revision 38092)
+++ src/preferences/backgrounds/BackgroundsView.cpp (working copy)
@@ -144,7 +144,7 @@
.AddGroup(B_VERTICAL, 20)
.AddGroup(B_HORIZONTAL, 0)
.AddGlue()
- .AddGrid(0, 0)
+ .AddGrid(0, 0, 1)
.Add(fTopLeft, 0, 0)
.Add(fTop, 1, 0)
.Add(fTopRight, 2, 0)
Index: src/libs/alm/BALMLayout.cpp
===================================================================
--- src/libs/alm/BALMLayout.cpp (revision 38092)
+++ src/libs/alm/BALMLayout.cpp (working copy)
@@ -20,7 +20,8 @@
* Creates new layout engine.
*/
BALMLayout::BALMLayout()
- : BLayout(),
+ :
+ BAbstractLayout(),
LinearSpec()
{
fLayoutStyle = FIT_TO_SIZE;
@@ -189,7 +190,7 @@
{
InvalidateLayout();
if (content != NULL)
- View()->AddChild(content);
+ TargetView()->AddChild(content);
Area* area = new Area(this, left, top, right, bottom, content, minContentSize);
fAreas->AddItem(area);
return area;
@@ -211,7 +212,7 @@
{
InvalidateLayout();
if (content != NULL)
- View()->AddChild(content);
+ TargetView()->AddChild(content);
Area* area = new Area(this, row, column, content, minContentSize);
fAreas->AddItem(area);
return area;
@@ -234,7 +235,7 @@
{
InvalidateLayout();
if (content != NULL)
- View()->AddChild(content);
+ TargetView()->AddChild(content);
Area* area = new Area(this, left, top, right, bottom, content, BSize(0, 0));
area->SetDefaultBehavior();
area->SetAutoPreferredContentSize(false);
@@ -256,7 +257,7 @@
{
InvalidateLayout();
if (content != NULL)
- View()->AddChild(content);
+ TargetView()->AddChild(content);
Area* area = new Area(this, row, column, content, BSize(0, 0));
area->SetDefaultBehavior();
area->SetAutoPreferredContentSize(false);
@@ -435,9 +436,10 @@
/**
- * Sets and gets minimum size.
+ * Gets minimum size.
*/
-BSize BALMLayout::MinSize() {
+BSize
+BALMLayout::BaseMinSize() {
if (fMinSize == Area::kUndefinedSize)
fMinSize = CalculateMinSize();
return fMinSize;
@@ -445,10 +447,10 @@
/**
- * Sets and gets maximum size.
+ * Gets maximum size.
*/
BSize
-BALMLayout::MaxSize()
+BALMLayout::BaseMaxSize()
{
if (fMaxSize == Area::kUndefinedSize)
fMaxSize = CalculateMaxSize();
@@ -457,10 +459,10 @@
/**
- * Sets and gets preferred size.
+ * Gets preferred size.
*/
BSize
-BALMLayout::PreferredSize()
+BALMLayout::BasePreferredSize()
{
if (fPreferredSize == Area::kUndefinedSize)
fPreferredSize = CalculatePreferredSize();
@@ -472,7 +474,7 @@
* Gets the alignment.
*/
BAlignment
-BALMLayout::Alignment()
+BALMLayout::BaseAlignment()
{
BAlignment alignment;
alignment.SetHorizontal(B_ALIGN_HORIZONTAL_CENTER);
@@ -492,7 +494,7 @@
/**
- * Sets whether the height of the layout depends on its width.
+ * Gets height constraints for a given width.
*/
void
BALMLayout::GetHeightForWidth(float width, float* min, float* max, float* preferred) {}
@@ -503,8 +505,9 @@
* Resets minimum/maximum/preferred size.
*/
void
-BALMLayout::InvalidateLayout()
+BALMLayout::InvalidateLayout(bool children)
{
+ BLayout::InvalidateLayout(children);
fMinSize = Area::kUndefinedSize;
fMaxSize = Area::kUndefinedSize;
fPreferredSize = Area::kUndefinedSize;
@@ -516,25 +519,28 @@
* If no layout specification is given, a specification is reverse engineered automatically.
*/
void
-BALMLayout::LayoutView()
+BALMLayout::DerivedLayoutItems()
{
+ // TODO: modify to allow for viewlessness
// make sure that layout events occuring during layout are ignored
- // i.e. activated is set to false during layout caluclation
+ // i.e. activated is set to false during layout calculation
if (!fActivated)
return;
fActivated = false;
- if (View() == NULL)
+ if (Owner() == NULL)
return;
// reverse engineer a layout specification if none was given
//~ if (this == NULL) RecoverLayout(View());
// if the layout engine is set to fit the GUI to the given size,
- // then the given size is enforced by setting absolute positions for Right and Bottom
+ // then the given size is enforced by setting absolute positions
+ // for Right and Bottom
if (fLayoutStyle == FIT_TO_SIZE) {
- Right()->SetRange(View()->Bounds().Width(), View()->Bounds().Width());
- Bottom()->SetRange(View()->Bounds().Height(), View()->Bounds().Height());
+ BSize layoutSize(LayoutArea().Size());
+ Right()->SetRange(layoutSize.width, layoutSize.width);
+ Bottom()->SetRange(layoutSize.height, layoutSize.height);
}
SolveLayout();
@@ -554,7 +560,7 @@
// change the size of the GUI according to the calculated size
// if the layout engine was configured to do so
if (fLayoutStyle == ADJUST_SIZE) {
- View()->ResizeTo(floor(Right()->Value() - Left()->Value() + 0.5),
+ Owner()->ResizeTo(floor(Right()->Value() - Left()->Value() + 0.5),
floor(Bottom()->Value() - Top()->Value() + 0.5));
}
Index: src/kits/interface/AbstractLayout.cpp
===================================================================
--- src/kits/interface/AbstractLayout.cpp (revision 0)
+++ src/kits/interface/AbstractLayout.cpp (revision 0)
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2010, Haiku, Inc.
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+
+
+namespace {
+ const char* const kSizesField = "BAbstractLayout:sizes";
+ // kSizesField == {min, max, preferred}
+ const char* const kAlignmentField = "BAbstractLayout:alignment";
+ const char* const kFrameField = "BAbstractLayout:frame";
+ const char* const kVisibleField = "BAbstractLayout:visible";
+
+ enum proxy_type { VIEW_PROXY_TYPE, DATA_PROXY_TYPE };
+}
+
+
+struct BAbstractLayout::Proxy {
+
+ Proxy(proxy_type type)
+ :
+ type(type)
+ {
+ }
+
+ virtual BSize MinSize() const = 0;
+ virtual void SetMinSize(const BSize&) = 0;
+
+ virtual BSize MaxSize() const = 0;
+ virtual void SetMaxSize(const BSize&) = 0;
+
+ virtual BSize PreferredSize() const = 0;
+ virtual void SetPreferredSize(const BSize&) = 0;
+
+ virtual BAlignment Alignment() const = 0;
+ virtual void SetAlignment(const BAlignment&) = 0;
+
+ virtual BRect Frame() const = 0;
+ virtual void SetFrame(const BRect& frame) = 0;
+
+ virtual bool IsVisible(bool ancestorHidden) const = 0;
+ virtual void SetVisible(bool visible) = 0;
+
+ virtual status_t AddDataToArchive(BMessage* archive,
+ bool ancestorHidden) = 0;
+ virtual status_t RestoreDataFromArchive(const BMessage* archive) = 0;
+
+ proxy_type type;
+};
+
+
+struct BAbstractLayout::DataProxy : Proxy {
+
+ DataProxy()
+ :
+ Proxy(DATA_PROXY_TYPE),
+ minSize(),
+ maxSize(),
+ preferredSize(),
+ alignment(),
+ frame(-1, -1, 0, 0),
+ visible(true)
+ {
+ }
+
+ BSize MinSize() const
+ {
+ return minSize;
+ }
+
+ void SetMinSize(const BSize& min)
+ {
+ minSize = min;
+ }
+
+ BSize MaxSize() const
+ {
+ return maxSize;
+ }
+
+ void SetMaxSize(const BSize& max)
+ {
+ maxSize = max;
+ }
+
+ BSize PreferredSize() const
+ {
+ return preferredSize;
+ }
+
+ void SetPreferredSize(const BSize& preferred)
+ {
+ preferredSize = preferred;
+ }
+
+ BAlignment Alignment() const
+ {
+ return this->alignment;
+ }
+
+ void SetAlignment(const BAlignment& align)
+ {
+ this->alignment = align;
+ }
+
+ BRect Frame() const
+ {
+ return frame;
+ }
+
+ void SetFrame(const BRect& frame)
+ {
+ if (frame == this->frame)
+ return;
+ this->frame = frame;
+ }
+
+ bool IsVisible(bool) const
+ {
+ return visible;
+ }
+
+ void SetVisible(bool visible)
+ {
+ this->visible = visible;
+ }
+
+ status_t AddDataToArchive(BMessage* archive, bool ancestorHidden)
+ {
+ status_t err = archive->AddSize(kSizesField, minSize);
+ if (err == B_OK)
+ err = archive->AddSize(kSizesField, maxSize);
+ if (err == B_OK)
+ err = archive->AddSize(kSizesField, preferredSize);
+ if (err == B_OK)
+ err = archive->AddAlignment(kAlignmentField, alignment);
+ if (err == B_OK)
+ err = archive->AddRect(kFrameField, frame);
+ if (err == B_OK)
+ err = archive->AddBool(kVisibleField, visible);
+
+ return err;
+ }
+
+ status_t RestoreDataFromArchive(const BMessage* archive)
+ {
+ status_t err = archive->FindSize(kSizesField, 0, &minSize);
+ if (err == B_OK)
+ err = archive->FindSize(kSizesField, 1, &maxSize);
+ if (err == B_OK)
+ err = archive->FindSize(kSizesField, 2, &preferredSize);
+ if (err == B_OK)
+ err = archive->FindAlignment(kAlignmentField, &alignment);
+ if (err == B_OK)
+ err = archive->FindRect(kFrameField, &frame);
+ if (err == B_OK)
+ err = archive->FindBool(kVisibleField, &visible);
+
+ return err;
+ }
+
+ BSize minSize;
+ BSize maxSize;
+ BSize preferredSize;
+ BAlignment alignment;
+ BRect frame;
+ bool visible;
+};
+
+
+struct BAbstractLayout::ViewProxy : Proxy {
+ ViewProxy(BView* target)
+ :
+ Proxy(VIEW_PROXY_TYPE),
+ view(target)
+ {
+ }
+
+ BSize MinSize() const
+ {
+ return view->ExplicitMinSize();
+ }
+
+ void SetMinSize(const BSize& min)
+ {
+ view->SetExplicitMinSize(min);
+ }
+
+ BSize MaxSize() const
+ {
+ return view->ExplicitMaxSize();
+ }
+
+ void SetMaxSize(const BSize& min)
+ {
+ view->SetExplicitMaxSize(min);
+ }
+
+ BSize PreferredSize() const
+ {
+ return view->ExplicitPreferredSize();
+ }
+
+ void SetPreferredSize(const BSize& preferred)
+ {
+ view->SetExplicitPreferredSize(preferred);
+ }
+
+ BAlignment Alignment() const
+ {
+ return view->ExplicitAlignment();
+ }
+
+ void SetAlignment(const BAlignment& alignment)
+ {
+ view->SetExplicitAlignment(alignment);
+ }
+
+ BRect Frame() const
+ {
+ return view->Frame();
+ }
+
+ void SetFrame(const BRect& frame)
+ {
+ view->MoveTo(frame.LeftTop());
+ view->ResizeTo(frame.Width(), frame.Height());
+ }
+
+ bool IsVisible(bool ancestorsVisible) const
+ {
+ int16 showLevel = BView::Private(view).ShowLevel();
+ return (showLevel - (ancestorsVisible) ? 0 : 1) <= 0;
+ }
+
+ void SetVisible(bool visible)
+ {
+ // No need to check that we are not re-hiding, that is done
+ // for us.
+ if (visible)
+ view->Show();
+ else
+ view->Hide();
+ }
+
+ status_t AddDataToArchive(BMessage* archive, bool ancestorHidden)
+ {
+ return B_OK;
+ }
+
+ status_t RestoreDataFromArchive(const BMessage* archive)
+ {
+ return B_OK;
+ }
+
+ BView* view;
+};
+
+
+BAbstractLayout::BAbstractLayout()
+ :
+ fExplicitData(new BAbstractLayout::DataProxy())
+{
+}
+
+
+BAbstractLayout::BAbstractLayout(BMessage* from)
+ :
+ BLayout(BUnarchiver::PrepareArchive(from)),
+ fExplicitData(new DataProxy())
+{
+ BUnarchiver(from).Finish();
+}
+
+
+BAbstractLayout::~BAbstractLayout()
+{
+ delete fExplicitData;
+}
+
+
+BSize
+BAbstractLayout::MinSize()
+{
+ return BLayoutUtils::ComposeSize(fExplicitData->MinSize(), BaseMinSize());
+}
+
+
+BSize
+BAbstractLayout::MaxSize()
+{
+ return BLayoutUtils::ComposeSize(fExplicitData->MaxSize(), BaseMaxSize());
+}
+
+
+BSize
+BAbstractLayout::PreferredSize()
+{
+ return BLayoutUtils::ComposeSize(fExplicitData->PreferredSize(),
+ BasePreferredSize());
+}
+
+
+BAlignment
+BAbstractLayout::Alignment()
+{
+ return BLayoutUtils::ComposeAlignment(fExplicitData->Alignment(),
+ BaseAlignment());
+}
+
+
+void
+BAbstractLayout::SetExplicitMinSize(BSize size)
+{
+ fExplicitData->SetMinSize(size);
+}
+
+
+void
+BAbstractLayout::SetExplicitMaxSize(BSize size)
+{
+ fExplicitData->SetMaxSize(size);
+}
+
+
+void
+BAbstractLayout::SetExplicitPreferredSize(BSize size)
+{
+ fExplicitData->SetPreferredSize(size);
+}
+
+
+void
+BAbstractLayout::SetExplicitAlignment(BAlignment alignment)
+{
+ fExplicitData->SetAlignment(alignment);
+}
+
+
+BSize
+BAbstractLayout::BaseMinSize()
+{
+ return BSize(0, 0);
+}
+
+
+BSize
+BAbstractLayout::BaseMaxSize()
+{
+ return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
+}
+
+
+BSize
+BAbstractLayout::BasePreferredSize()
+{
+ return BSize(0, 0);
+}
+
+
+BAlignment
+BAbstractLayout::BaseAlignment()
+{
+ return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
+}
+
+
+BRect
+BAbstractLayout::Frame()
+{
+ return fExplicitData->Frame();
+}
+
+
+void
+BAbstractLayout::SetFrame(BRect frame)
+{
+ if (frame != fExplicitData->Frame()) {
+ fExplicitData->SetFrame(frame);
+ if (!Owner())
+ Relayout();
+ }
+}
+
+
+bool
+BAbstractLayout::IsVisible()
+{
+ return fExplicitData->IsVisible(AncestorsVisible());
+}
+
+
+void
+BAbstractLayout::SetVisible(bool visible)
+{
+ if (visible != fExplicitData->IsVisible(AncestorsVisible())) {
+ fExplicitData->SetVisible(visible);
+ if (Layout())
+ Layout()->InvalidateLayout(false);
+ VisibilityChanged(visible);
+ }
+}
+
+
+status_t
+BAbstractLayout::Archive(BMessage* into, bool deep) const
+{
+ BArchiver archiver(into);
+ status_t err = BLayout::Archive(into, deep);
+
+ return archiver.Finish(err);
+}
+
+
+status_t
+BAbstractLayout::AllUnarchived(const BMessage* from)
+{
+ if (Owner()) {
+ ViewProxy* proxy = dynamic_cast(fExplicitData);
+ if (!proxy) {
+ delete fExplicitData;
+ proxy = new ViewProxy(Owner());
+ }
+ proxy->view = Owner();
+ } else {
+ fExplicitData = new DataProxy();
+ return fExplicitData->RestoreDataFromArchive(from);
+ }
+
+ return BLayout::AllUnarchived(from);
+}
+
+
+void
+BAbstractLayout::OwnerChanged(BView* was)
+{
+ if (was) {
+ static_cast(fExplicitData)->view = Owner();
+ return;
+ }
+
+ delete fExplicitData;
+ fExplicitData = new ViewProxy(Owner());
+}
+
+
+void
+BAbstractLayout::AncestorVisibilityChanged(bool shown)
+{
+ if (AncestorsVisible() == shown)
+ return;
+
+ if (BView* owner = Owner()) {
+ if (shown)
+ owner->Show();
+ else
+ owner->Hide();
+ }
+ BLayout::AncestorVisibilityChanged(shown);
+}
+
Index: src/kits/interface/ViewLayoutItem.h
===================================================================
--- src/kits/interface/ViewLayoutItem.h (revision 38092)
+++ src/kits/interface/ViewLayoutItem.h (working copy)
@@ -36,15 +36,20 @@
virtual BView* View();
- virtual void InvalidateLayout();
+ virtual void InvalidateLayout(bool children = false);
+ virtual void Relayout(bool immediate = false);
virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual status_t AllArchived(BMessage* into) const;
virtual status_t AllUnarchived(const BMessage* from);
static BArchivable* Instantiate(BMessage* from);
+protected:
+ virtual void AncestorVisibilityChanged(bool shown);
+
private:
BView* fView;
+ int32 fAncestorsVisible;
};
#endif // _VIEW_LAYOUT_ITEM_H
Index: src/kits/interface/View.cpp
===================================================================
--- src/kits/interface/View.cpp (revision 38092)
+++ src/kits/interface/View.cpp (working copy)
@@ -648,7 +648,7 @@
err = unarchiver.FindObject(kLayoutField, layout);
if (err == B_OK && layout) {
fFlags |= B_SUPPORTS_LAYOUT;
- fLayoutData->fLayout->BLayout::SetView(this);
+ fLayoutData->fLayout->SetOwner(this);
}
}
@@ -997,7 +997,7 @@
fShowLevel++;
if (fShowLevel == 1 && fParent)
- fParent->InvalidateLayout();
+ _InvalidateParentLayout();
}
@@ -1012,7 +1012,7 @@
}
if (fShowLevel == 0 && fParent)
- fParent->InvalidateLayout();
+ _InvalidateParentLayout();
}
@@ -4020,7 +4020,7 @@
BView::RemoveSelf()
{
if (fParent && fParent->fLayoutData->fLayout)
- return fParent->fLayoutData->fLayout->RemoveView(this);
+ return fParent->fLayoutData->fLayout->RemoveViewRecursive(this);
return _RemoveSelf();
}
@@ -4643,18 +4643,21 @@
if (layout == fLayoutData->fLayout)
return;
+ if (layout && layout->Layout())
+ debugger("BView::SetLayout() failed, layout is already in use.");
+
fFlags |= B_SUPPORTS_LAYOUT;
// unset and delete the old layout
if (fLayoutData->fLayout) {
- fLayoutData->fLayout->SetView(NULL);
+ fLayoutData->fLayout->SetOwner(NULL);
delete fLayoutData->fLayout;
}
fLayoutData->fLayout = layout;
if (fLayoutData->fLayout) {
- fLayoutData->fLayout->SetView(this);
+ fLayoutData->fLayout->SetOwner(this);
// add all children
int count = CountChildren();
@@ -4676,23 +4679,29 @@
void
BView::InvalidateLayout(bool descendants)
{
+ // printf("BView(%p)::InvalidateLayout(%i), valid: %i, inProgress: %i\n",
+ // this, descendants, fLayoutData->fLayoutValid,
+ // fLayoutData->fLayoutInProgress);
+
if (fLayoutData->fMinMaxValid && !fLayoutData->fLayoutInProgress
- && fLayoutData->fLayoutInvalidationDisabled == 0) {
- if (fParent && fParent->fLayoutData->fMinMaxValid)
- fParent->InvalidateLayout(false);
+ && fLayoutData->fLayoutInvalidationDisabled == 0) {
fLayoutData->fLayoutValid = false;
fLayoutData->fMinMaxValid = false;
- if (fLayoutData->fLayout)
- fLayoutData->fLayout->InvalidateLayout();
-
if (descendants) {
- int count = CountChildren();
- for (int i = 0; i < count; i++)
- ChildAt(i)->InvalidateLayout(descendants);
+ for (BView* child = fFirstChild;
+ child; child = child->fNextSibling) {
+ child->InvalidateLayout(descendants);
+ }
}
+ if (fLayoutData->fLayout && fLayoutData->fLayout->InvalidationLegal())
+ fLayoutData->fLayout->InvalidateLayout(descendants);
+ else if (!fLayoutData->fLayout && fParent) {
+ _InvalidateParentLayout();
+ }
+
if (fTopLevelView) {
// trigger layout process
if (fOwner)
@@ -4724,15 +4733,12 @@
}
-/*! \brief Service call for BLayout derived classes reenabling
+/*! \brief Service call for BView derived classes reenabling
InvalidateLayout() notifications.
- BView::InvalidateLayout() invokes InvalidateLayout() on its layout the first
- time, but suppresses further calls until Layout()/Relayout() has been
- invoked. This method will reenable the notification for the next call of
- BView::InvalidateLayout().
- If the layout caches internal layout information and updates those
- information also in methods other than LayoutView(), it has to invoke this
+ BLayout & BView will avoid calling InvalidateLayout on views that have
+ already been invalidated, but if the view caches internal layout information
+ which it updates in methds other than DoLayout(), it has to invoke this
method, when it has done so, since otherwise the information might become
obsolete without the layout noticing.
*/
@@ -4763,6 +4769,8 @@
{
if (fLayoutData->fLayoutValid && !fLayoutData->fLayoutInProgress) {
fLayoutData->fNeedsRelayout = true;
+ if (fLayoutData->fLayout)
+ fLayoutData->fLayout->RequireLayout();
// Layout() is recursive, that is if the parent view is currently laid
// out, we don't call layout() on this view, but wait for the parent's
@@ -4777,7 +4785,7 @@
BView::DoLayout()
{
if (fLayoutData->fLayout)
- fLayoutData->fLayout->LayoutView();
+ fLayoutData->fLayout->_LayoutWithinContext(false, LayoutContext());
}
@@ -4881,9 +4889,7 @@
fLayoutData->fNeedsRelayout = false;
// layout children
- int32 childCount = CountChildren();
- for (int32 i = 0; i < childCount; i++) {
- BView* child = ChildAt(i);
+ for(BView* child = fFirstChild; child; child = child->fNextSibling) {
if (!child->IsHidden(child))
child->_Layout(force, context);
}
@@ -4897,6 +4903,34 @@
}
+void
+BView::_LayoutLeft(BLayout* deleted)
+{
+ // If our layout is added to another layout (via BLayout::AddItem())
+ // then we share ownership of our layout. In the event that our layout gets
+ // deleted by the layout it has been added to, this method is called so
+ // that we don't double-delete our layout.
+ if (fLayoutData->fLayout == deleted)
+ fLayoutData->fLayout = NULL;
+ InvalidateLayout();
+}
+
+
+void
+BView::_InvalidateParentLayout()
+{
+ BLayout* layout = fLayoutData->fLayout;
+ BLayout* layoutParent = layout ? layout->Layout() : NULL;
+ if (layoutParent && layoutParent->InvalidationLegal()) {
+ layout->Layout()->InvalidateLayout();
+ } else if (fParent && fParent->fLayoutData->fLayout) {
+ fParent->fLayoutData->fLayout->InvalidateLayoutsForView(this);
+ } else if (fParent) {
+ fParent->InvalidateLayout();
+ }
+}
+
+
// #pragma mark - Private Functions
@@ -5920,3 +5954,13 @@
}
}
}
+
+
+// #pragma mark -
+
+
+bool
+BView::Private::MinMaxValid()
+{
+ return fView->fLayoutData->fMinMaxValid;
+}
Index: src/kits/interface/Layout.cpp
===================================================================
--- src/kits/interface/Layout.cpp (revision 38092)
+++ src/kits/interface/Layout.cpp (working copy)
@@ -7,26 +7,50 @@
#include
+#include
+#include
#include
-#include
+#include
#include
#include
+#include
#include "ViewLayoutItem.h"
using std::nothrow;
+using std::swap;
namespace {
+ // flags for our state
+ const uint32 B_LAYOUT_INVALID = 0x80000000UL; // needs layout
+ const uint32 B_LAYOUT_CACHE_INVALID = 0x40000000UL; // needs recalculation
+ const uint32 B_LAYOUT_REQUIRED = 0x20000000UL; // needs layout
+ const uint32 B_LAYOUT_IN_PROGRESS = 0x10000000UL;
+ const uint32 B_LAYOUT_ALL_CLEAR = 0UL;
+
+ // handy masks to check various states
+ const uint32 B_LAYOUT_INVALIDATION_ILLEGAL
+ = B_LAYOUT_CACHE_INVALID | B_LAYOUT_IN_PROGRESS;
+ const uint32 B_LAYOUT_NECESSARY
+ = B_LAYOUT_INVALID | B_LAYOUT_REQUIRED | B_LAYOUT_CACHE_INVALID;
+ const uint32 B_RELAYOUT_NOT_OK
+ = B_LAYOUT_INVALID | B_LAYOUT_IN_PROGRESS;
+
const char* const kLayoutItemField = "BLayout:items";
}
BLayout::BLayout()
:
- fView(NULL),
+ fState(B_LAYOUT_ALL_CLEAR),
+ fAncestorsVisible(true),
+ fInvalidationDisabled(0),
+ fContext(NULL),
+ fOwner(NULL),
+ fTarget(NULL),
fItems(20)
{
}
@@ -34,8 +58,13 @@
BLayout::BLayout(BMessage* from)
:
- BArchivable(BUnarchiver::PrepareArchive(from)),
- fView(NULL),
+ BLayoutItem(BUnarchiver::PrepareArchive(from)),
+ fState(B_LAYOUT_ALL_CLEAR),
+ fAncestorsVisible(true),
+ fInvalidationDisabled(0),
+ fContext(NULL),
+ fOwner(NULL),
+ fTarget(NULL),
fItems(20)
{
BUnarchiver unarchiver(from);
@@ -48,18 +77,39 @@
BLayout::~BLayout()
{
- // this deletes all items
- SetView(NULL);
+ // in case we have a view, but have been added to a layout as a BLayoutItem
+ // we will get deleted before our view, so we should tell it that we're
+ // going, so that we aren't double-freed.
+ if (fOwner && this == fOwner->GetLayout())
+ fOwner->_LayoutLeft(this);
+
+ // removes and deletes all items
+ if (fTarget)
+ SetTarget(NULL);
}
BView*
-BLayout::View() const
+BLayout::Owner() const
{
- return fView;
+ return fOwner;
}
+BView*
+BLayout::TargetView() const
+{
+ return fTarget;
+}
+
+
+BView*
+BLayout::View()
+{
+ return fOwner;
+}
+
+
BLayoutItem*
BLayout::AddView(BView* child)
{
@@ -70,11 +120,15 @@
BLayoutItem*
BLayout::AddView(int32 index, BView* child)
{
- if (BViewLayoutItem* item = new(nothrow) BViewLayoutItem(child)) {
- if (AddItem(index, item))
- return item;
+ BLayoutItem* item = child->GetLayout();
+ if (!item)
+ item = new(nothrow) BViewLayoutItem(child);
+
+ if (item && AddItem(index, item))
+ return item;
+
+ if (!child->GetLayout())
delete item;
- }
return NULL;
}
@@ -89,15 +143,15 @@
bool
BLayout::AddItem(int32 index, BLayoutItem* item)
{
- if (!fView || !item || fItems.HasItem(item))
+ if (!fTarget || !item || fItems.HasItem(item))
return false;
// if the item refers to a BView, we make sure it is added to the parent
// view
bool addedView = false;
BView* view = item->View();
- if (view && view->fParent != fView
- && !(addedView = fView->_AddChild(view, NULL)))
+ if (view && view->fParent != fTarget
+ && !(addedView = fTarget->_AddChild(view, NULL)))
return false;
// validate the index
@@ -106,6 +160,8 @@
if (fItems.AddItem(item, index) && ItemAdded(item, index)) {
item->SetLayout(this);
+ if (!fAncestorsVisible)
+ item->AncestorVisibilityChanged(fAncestorsVisible);
InvalidateLayout();
return true;
} else {
@@ -160,11 +216,11 @@
// if the item refers to a BView, we make sure, it is removed from the
// parent view
BView* view = item->View();
- if (view && view->fParent == fView)
+ if (view && view->fParent == fTarget)
view->_RemoveSelf();
+ ItemRemoved(item, index);
item->SetLayout(NULL);
- ItemRemoved(item, index);
InvalidateLayout();
return item;
@@ -206,19 +262,158 @@
}
+bool
+BLayout::AncestorsVisible()
+{
+ return fAncestorsVisible;
+}
+
+
void
-BLayout::InvalidateLayout()
+BLayout::InvalidateLayout(bool children)
{
- if (fView)
- fView->InvalidateLayout();
+ // printf("BLayout(%p)::InvalidateLayout(%i) : state %x, disabled %li\n",
+ // this, children, (unsigned int)fState, fInvalidationDisabled);
+
+ if (!InvalidationLegal())
+ return;
+
+ fState |= B_LAYOUT_NECESSARY;
+
+ if (children) {
+ for (int32 i = CountItems() - 1; i >= 0; i--)
+ ItemAt(i)->InvalidateLayout(children);
+ }
+
+ if (fOwner && BView::Private(fOwner).MinMaxValid())
+ fOwner->InvalidateLayout(children);
+
+ if (BLayout* nestedIn = Layout()) {
+ if (nestedIn->InvalidationLegal())
+ nestedIn->InvalidateLayout();
+ } else if (fOwner) {
+ // If we weren't added as a BLayoutItem, we still have to invalidate
+ // whatever layout our owner is in.
+ BView* ownerParent = fOwner->fParent;
+ if (ownerParent) {
+ BLayout* layout = ownerParent->GetLayout();
+ if (layout && layout->fNestedLayouts.CountItems() > 0)
+ layout->InvalidateLayoutsForView(fOwner);
+ else if (BView::Private(ownerParent).MinMaxValid())
+ ownerParent->InvalidateLayout(false);
+ }
+ }
}
+void
+BLayout::RequireLayout()
+{
+ fState |= B_LAYOUT_REQUIRED;
+}
+
+
+bool
+BLayout::IsValid()
+{
+ return (fState & B_LAYOUT_INVALID) == 0;
+}
+
+
+void
+BLayout::DisableLayoutInvalidation()
+{
+ fInvalidationDisabled++;
+}
+
+
+void
+BLayout::EnableLayoutInvalidation()
+{
+ if (fInvalidationDisabled > 0)
+ fInvalidationDisabled--;
+}
+
+
+void
+BLayout::LayoutItems(bool force)
+{
+ if ((fState & B_LAYOUT_NECESSARY) == 0 && !force)
+ return;
+
+ if (Layout() && (Layout()->fState & B_LAYOUT_IN_PROGRESS) != 0)
+ return; // wait for parent layout to lay us out.
+
+ if (fTarget && fTarget->LayoutContext())
+ return;
+
+ BLayoutContext context;
+ _LayoutWithinContext(force, &context);
+}
+
+
+void
+BLayout::Relayout(bool immediate)
+{
+ if ((fState & B_RELAYOUT_NOT_OK) == 0 || immediate) {
+ fState |= B_LAYOUT_REQUIRED;
+ LayoutItems(false);
+ }
+}
+
+
+
+void
+BLayout::_LayoutWithinContext(bool force, BLayoutContext* context)
+{
+// printf("BLayout(%p)::_LayoutWithinContext(%i, %p), state %x, fContext %p\n",
+// this, force, context, (unsigned int)fState, fContext);
+
+ if ((fState & B_LAYOUT_NECESSARY) == 0 && !force)
+ return;
+
+ BLayoutContext* oldContext = fContext;
+ fContext = context;
+
+ if (fOwner && fOwner->LayoutContext() != context) {
+ // in this case, let our owner decide whether or not to have us
+ // do our layout, if they do, we won't end up here again.
+ fOwner->_Layout(force, context);
+ } else {
+ fState |= B_LAYOUT_IN_PROGRESS;
+ DerivedLayoutItems();
+ // we must ensure that all items are laid out, layouts with a view will
+ // have their layout process triggered by their view, but nested
+ // view-less layouts must have their layout triggered here (if it hasn't
+ // already been triggered).
+ int32 nestedLayoutCount = fNestedLayouts.CountItems();
+ for (int32 i = 0; i < nestedLayoutCount; i++) {
+ BLayout* layout = (BLayout*)fNestedLayouts.ItemAt(i);
+ if ((layout->fState & B_LAYOUT_NECESSARY) != 0)
+ layout->_LayoutWithinContext(force, context);
+ }
+ fState = B_LAYOUT_ALL_CLEAR;
+ }
+
+ fContext = oldContext;
+}
+
+
+BRect
+BLayout::LayoutArea()
+{
+ BRect area(Frame());
+ if (fOwner)
+ area.OffsetTo(B_ORIGIN);
+ return area;
+}
+
+
status_t
BLayout::Archive(BMessage* into, bool deep) const
{
BArchiver archiver(into);
- status_t err = BArchivable::Archive(into, deep);
+ status_t err = BLayoutItem::Archive(into, deep);
if (deep) {
int32 count = CountItems();
@@ -242,7 +437,7 @@
BLayout::AllUnarchived(const BMessage* from)
{
BUnarchiver unarchiver(from);
- status_t err = BArchivable::AllUnarchived(from);
+ status_t err = BLayoutItem::AllUnarchived(from);
if (err != B_OK)
return err;
@@ -304,16 +499,138 @@
void
-BLayout::SetView(BView* view)
+BLayout::OwnerChanged(BView* was)
{
- if (view != fView) {
- fView = NULL;
+}
+
+void
+BLayout::AttachedToLayout()
+{
+ if (!fOwner) {
+ Layout()->fNestedLayouts.AddItem(this);
+ SetTarget(Layout()->TargetView());
+ }
+}
+
+
+void
+BLayout::DetachedFromLayout(BLayout* from)
+{
+ if (!fOwner) {
+ from->fNestedLayouts.RemoveItem(this);
+ SetTarget(NULL);
+ }
+}
+
+
+void
+BLayout::AncestorVisibilityChanged(bool shown)
+{
+ if (fAncestorsVisible == shown)
+ return;
+
+ fAncestorsVisible = shown;
+ VisibilityChanged(shown);
+}
+
+
+void
+BLayout::VisibilityChanged(bool show)
+{
+ if (fOwner)
+ return;
+
+ for (int32 i = CountItems() - 1; i >= 0; i--)
+ ItemAt(i)->AncestorVisibilityChanged(show);
+}
+
+
+void
+BLayout::ResetLayoutInvalidation()
+{
+ fState &= ~B_LAYOUT_CACHE_INVALID;
+}
+
+
+BLayoutContext*
+BLayout::LayoutContext()
+{
+ return fContext;
+}
+
+
+bool
+BLayout::RemoveViewRecursive(BView* view)
+{
+ bool removed = RemoveView(view);
+ for (int32 i = fNestedLayouts.CountItems() - 1; i >= 0; i--) {
+ BLayout* nested = (BLayout*)fNestedLayouts.ItemAt(i);
+ removed |= nested->RemoveViewRecursive(view);
+ }
+ return removed;
+}
+
+
+bool
+BLayout::InvalidateLayoutsForView(BView* view)
+{
+ bool found = false;
+ for (int32 i = fNestedLayouts.CountItems() - 1; i >= 0; i--) {
+ BLayout* layout = (BLayout*)fNestedLayouts.ItemAt(i);
+ found |= layout->InvalidateLayoutsForView(view);
+ }
+
+ if (found)
+ return found;
+
+ if (!InvalidationLegal())
+ return false;
+
+ for (int32 i = CountItems() - 1; i >= 0; i--) {
+ if (ItemAt(i)->View() == view) {
+ InvalidateLayout();
+ return true;
+ }
+ }
+ return found;
+}
+
+
+bool
+BLayout::InvalidationLegal()
+{
+ return fInvalidationDisabled <= 0
+ && (fState & B_LAYOUT_INVALIDATION_ILLEGAL) == 0;
+}
+
+
+void
+BLayout::SetOwner(BView* owner)
+{
+ if (fOwner == owner)
+ return;
+
+ SetTarget(owner);
+ swap(fOwner, owner);
+
+ OwnerChanged(owner);
+ // call hook
+}
+
+
+void
+BLayout::SetTarget(BView* target)
+{
+ if (fTarget != target) {
+ fTarget = NULL;
+ // only remove items, not views
+
// remove and delete all items
for (int32 i = CountItems() - 1; i >= 0; i--)
delete RemoveItem(i);
- fView = view;
+ fTarget = target;
InvalidateLayout();
}
Index: src/kits/interface/ViewLayoutItem.cpp
===================================================================
--- src/kits/interface/ViewLayoutItem.cpp (revision 38092)
+++ src/kits/interface/ViewLayoutItem.cpp (working copy)
@@ -11,6 +11,7 @@
#include
#include
+#include
namespace {
@@ -20,7 +21,8 @@
BViewLayoutItem::BViewLayoutItem(BView* view)
:
- fView(view)
+ fView(view),
+ fAncestorsVisible(true)
{
}
@@ -28,7 +30,8 @@
BViewLayoutItem::BViewLayoutItem(BMessage* from)
:
BLayoutItem(BUnarchiver::PrepareArchive(from)),
- fView(NULL)
+ fView(NULL),
+ fAncestorsVisible(true)
{
BUnarchiver unarchiver(from);
unarchiver.Finish(unarchiver.FindObject(kViewField, 0,
@@ -100,7 +103,8 @@
bool
BViewLayoutItem::IsVisible()
{
- return !fView->IsHidden(fView);
+ int16 showLevel = BView::Private(fView).ShowLevel();
+ return showLevel - (fAncestorsVisible ? 0 : 1) <= 0;
}
@@ -154,12 +158,22 @@
void
-BViewLayoutItem::InvalidateLayout()
+BViewLayoutItem::InvalidateLayout(bool children)
{
- fView->InvalidateLayout();
+ fView->InvalidateLayout(children);
}
+void
+BViewLayoutItem::Relayout(bool immediate)
+{
+ if (immediate)
+ fView->Layout(false);
+ else
+ fView->Relayout();
+}
+
+
status_t
BViewLayoutItem::Archive(BMessage* into, bool deep) const
{
@@ -204,3 +218,18 @@
return new(std::nothrow) BViewLayoutItem(from);
return NULL;
}
+
+
+void
+BViewLayoutItem::AncestorVisibilityChanged(bool shown)
+{
+ if (fAncestorsVisible == shown)
+ return;
+
+ fAncestorsVisible = shown;
+ if (shown)
+ fView->Show();
+ if (!shown)
+ fView->Hide();
+}
+
Index: src/kits/interface/LayoutItem.cpp
===================================================================
--- src/kits/interface/LayoutItem.cpp (revision 38092)
+++ src/kits/interface/LayoutItem.cpp (working copy)
@@ -8,8 +8,11 @@
#include
#include
+#include
+#include
+
BLayoutItem::BLayoutItem()
:
fLayout(NULL),
@@ -30,6 +33,8 @@
BLayoutItem::~BLayoutItem()
{
+ if (fLayout)
+ fLayout->RemoveItem(this);
}
@@ -64,13 +69,24 @@
void
-BLayoutItem::InvalidateLayout()
+BLayoutItem::InvalidateLayout(bool children)
{
if (fLayout)
- fLayout->InvalidateLayout();
+ fLayout->InvalidateLayout(children);
}
+void
+BLayoutItem::Relayout(bool immediate)
+{
+ BView* view = View();
+ if (view && !immediate)
+ view->Relayout();
+ else if (view && immediate)
+ view->Layout(false);
+}
+
+
void*
BLayoutItem::LayoutData() const
{
@@ -144,5 +160,35 @@
void
BLayoutItem::SetLayout(BLayout* layout)
{
- fLayout = layout;
+ if (layout == fLayout)
+ return;
+
+ std::swap(fLayout, layout);
+ if (layout)
+ DetachedFromLayout(layout);
+
+ if (fLayout)
+ AttachedToLayout();
}
+
+
+void
+BLayoutItem::AttachedToLayout()
+{
+ // hook method
+}
+
+
+void
+BLayoutItem::DetachedFromLayout(BLayout* oldLayout)
+{
+ // hook method
+}
+
+
+void
+BLayoutItem::AncestorVisibilityChanged(bool shown)
+{
+ // hook method
+}
+
Index: src/kits/interface/SplitLayout.h
===================================================================
--- src/kits/interface/SplitLayout.h (revision 38092)
+++ src/kits/interface/SplitLayout.h (working copy)
@@ -6,7 +6,7 @@
#define _SPLIT_LAYOUT_H
-#include
+#include
#include
@@ -21,7 +21,7 @@
using BPrivate::Layout::LayoutInfo;
-class BSplitLayout : public BLayout {
+class BSplitLayout : public BAbstractLayout {
public:
BSplitLayout(enum orientation orientation,
float spacing = 0.0f);
@@ -66,18 +66,18 @@
void SetCollapsible(int32 first, int32 last,
bool collapsible);
- virtual BSize MinSize();
- virtual BSize MaxSize();
- virtual BSize PreferredSize();
- virtual BAlignment Alignment();
+ virtual BSize BaseMinSize();
+ virtual BSize BaseMaxSize();
+ virtual BSize BasePreferredSize();
+ virtual BAlignment BaseAlignment();
virtual bool HasHeightForWidth();
virtual void GetHeightForWidth(float width, float* min,
float* max, float* preferred);
- virtual void InvalidateLayout();
+ virtual void InvalidateLayout(bool children = false);
- virtual void LayoutView();
+ virtual void DerivedLayoutItems();
// interface for BSplitView
BRect SplitterItemFrame(int32 index) const;
@@ -106,7 +106,8 @@
class ValueRange;
class SplitterItem;
- void _InvalidateLayout(bool invalidateView);
+ void _InvalidateLayout(bool invalidateView,
+ bool children = false);
void _InvalidateCachedHeightForWidth();
SplitterItem* _SplitterItemAt(const BPoint& point,
Index: src/kits/interface/GroupLayoutBuilder.cpp
===================================================================
--- src/kits/interface/GroupLayoutBuilder.cpp (revision 38092)
+++ src/kits/interface/GroupLayoutBuilder.cpp (working copy)
@@ -28,7 +28,6 @@
_PushLayout(fRootLayout);
}
-
// constructor
BGroupLayoutBuilder::BGroupLayoutBuilder(BGroupView* view)
: fRootLayout(view->GroupLayout())
@@ -64,7 +63,7 @@
BView*
BGroupLayoutBuilder::TopView() const
{
- return TopLayout()->View();
+ return TopLayout()->Owner();
}
// GetTopView
@@ -72,7 +71,7 @@
BGroupLayoutBuilder::GetTopView(BView** _view)
{
if (BGroupLayout* layout = TopLayout())
- *_view = layout->View();
+ *_view = layout->Owner();
else
*_view = NULL;
@@ -181,12 +180,6 @@
return fRootLayout;
}
-// cast operator BView*
-BGroupLayoutBuilder::operator BView*()
-{
- return fRootLayout->View();
-}
-
// _PushLayout
bool
BGroupLayoutBuilder::_PushLayout(BGroupLayout* layout)
Index: src/kits/interface/CardLayout.cpp
===================================================================
--- src/kits/interface/CardLayout.cpp (revision 38092)
+++ src/kits/interface/CardLayout.cpp (working copy)
@@ -17,7 +17,7 @@
BCardLayout::BCardLayout()
:
- BLayout(),
+ BAbstractLayout(),
fMin(0, 0),
fMax(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED),
fPreferred(0, 0),
@@ -29,7 +29,7 @@
BCardLayout::BCardLayout(BMessage* from)
:
- BLayout(BUnarchiver::PrepareArchive(from)),
+ BAbstractLayout(BUnarchiver::PrepareArchive(from)),
fMin(0, 0),
fMax(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED),
fPreferred(0, 0),
@@ -83,13 +83,13 @@
if (fVisibleItem != NULL) {
fVisibleItem->SetVisible(true);
- LayoutView();
+ Relayout();
}
}
BSize
-BCardLayout::MinSize()
+BCardLayout::BaseMinSize()
{
_ValidateMinMax();
return fMin;
@@ -97,7 +97,7 @@
BSize
-BCardLayout::MaxSize()
+BCardLayout::BaseMaxSize()
{
_ValidateMinMax();
return fMax;
@@ -105,7 +105,7 @@
BSize
-BCardLayout::PreferredSize()
+BCardLayout::BasePreferredSize()
{
_ValidateMinMax();
return fPreferred;
@@ -113,7 +113,7 @@
BAlignment
-BCardLayout::Alignment()
+BCardLayout::BaseAlignment()
{
return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
}
@@ -174,25 +174,30 @@
void
-BCardLayout::InvalidateLayout()
+BCardLayout::InvalidateLayout(bool children)
{
- BLayout::InvalidateLayout();
+ BLayout::InvalidateLayout(children);
fMinMaxValid = false;
}
void
-BCardLayout::LayoutView()
+BCardLayout::DerivedLayoutItems()
{
_ValidateMinMax();
- BSize size = View()->Bounds().Size();
- size.width = max_c(size.width, fMin.width);
- size.height = max_c(size.height, fMin.height);
+ BSize size(LayoutArea().Size());
- if (fVisibleItem != NULL)
- fVisibleItem->AlignInFrame(BRect(0, 0, size.width, size.height));
+ // this cannot be done when we are viewless, as our children
+ // would not get cut off in the right place.
+ if (Owner()) {
+ size.width = max_c(size.width, fMin.width);
+ size.height = max_c(size.height, fMin.height);
+ }
+
+ if (fVisibleItem != NULL)
+ fVisibleItem->AlignInFrame(BRect(LayoutArea().LeftTop(), size));
}
@@ -200,7 +205,7 @@
BCardLayout::Archive(BMessage* into, bool deep) const
{
BArchiver archiver(into);
- status_t err = BLayout::Archive(into, deep);
+ status_t err = BAbstractLayout::Archive(into, deep);
if (err == B_OK && deep)
err = into->AddInt32(kVisibleItemField, IndexOfItem(fVisibleItem));
@@ -292,7 +297,5 @@
fPreferred.height = min_c(fPreferred.height, fMax.height);
fMinMaxValid = true;
-
- if (BView* view = View())
- view->ResetLayoutInvalidation();
+ ResetLayoutInvalidation();
}
Index: src/kits/interface/Jamfile
===================================================================
--- src/kits/interface/Jamfile (revision 38092)
+++ src/kits/interface/Jamfile (working copy)
@@ -31,6 +31,7 @@
SEARCH_SOURCE += [ FDirName $(SUBDIR) layouter ] ;
MergeObject interface_kit.o :
+ AbstractLayout.cpp
AbstractLayoutItem.cpp
AffineTransform.cpp
Alert.cpp
Index: src/kits/interface/SplitLayout.cpp
===================================================================
--- src/kits/interface/SplitLayout.cpp (revision 38092)
+++ src/kits/interface/SplitLayout.cpp (working copy)
@@ -196,7 +196,7 @@
BSplitLayout::BSplitLayout(BMessage* from)
:
- BLayout(BUnarchiver::PrepareArchive(from)),
+ BAbstractLayout(BUnarchiver::PrepareArchive(from)),
fSplitterItems(),
fVisibleItems(),
fMin(),
@@ -340,14 +340,14 @@
BLayoutItem*
BSplitLayout::AddView(BView* child)
{
- return BLayout::AddView(child);
+ return BAbstractLayout::AddView(child);
}
BLayoutItem*
BSplitLayout::AddView(int32 index, BView* child)
{
- return BLayout::AddView(index, child);
+ return BAbstractLayout::AddView(index, child);
}
@@ -372,14 +372,14 @@
bool
BSplitLayout::AddItem(BLayoutItem* item)
{
- return BLayout::AddItem(item);
+ return BAbstractLayout::AddItem(item);
}
bool
BSplitLayout::AddItem(int32 index, BLayoutItem* item)
{
- return BLayout::AddItem(index, item);
+ return BAbstractLayout::AddItem(index, item);
}
@@ -480,7 +480,7 @@
BSize
-BSplitLayout::MinSize()
+BSplitLayout::BaseMinSize()
{
_ValidateMinMax();
@@ -489,7 +489,7 @@
BSize
-BSplitLayout::MaxSize()
+BSplitLayout::BaseMaxSize()
{
_ValidateMinMax();
@@ -498,7 +498,7 @@
BSize
-BSplitLayout::PreferredSize()
+BSplitLayout::BasePreferredSize()
{
_ValidateMinMax();
@@ -507,9 +507,9 @@
BAlignment
-BSplitLayout::Alignment()
+BSplitLayout::BaseAlignment()
{
- return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
+ return BAbstractLayout::BaseAlignment();
}
@@ -536,19 +536,19 @@
void
-BSplitLayout::InvalidateLayout()
+BSplitLayout::InvalidateLayout(bool children)
{
- _InvalidateLayout(true);
+ _InvalidateLayout(true, children);
}
void
-BSplitLayout::LayoutView()
+BSplitLayout::DerivedLayoutItems()
{
_ValidateMinMax();
// layout the elements
- BSize size = _SubtractInsets(View()->Bounds().Size());
+ BSize size = _SubtractInsets(LayoutArea().Size());
fHorizontalLayouter->Layout(fHorizontalLayoutInfo, size.width);
Layouter* verticalLayouter;
@@ -647,7 +647,7 @@
return false;
// Things shouldn't be draggable, if we have a >= max layout.
- BSize size = _SubtractInsets(View()->Frame().Size());
+ BSize size = _SubtractInsets(LayoutArea().Size());
if ((fOrientation == B_HORIZONTAL && size.width >= fMax.width)
|| (fOrientation == B_VERTICAL && size.height >= fMax.height)) {
return false;
@@ -655,7 +655,7 @@
int32 index = -1;
if (_SplitterItemAt(point, &index) != NULL) {
- fDraggingStartPoint = View()->ConvertToScreen(point);
+ fDraggingStartPoint = Owner()->ConvertToScreen(point);
fDraggingStartValue = _SplitterValue(index);
fDraggingCurrentValue = fDraggingStartValue;
fDraggingSplitterIndex = index;
@@ -673,7 +673,7 @@
if (fDraggingSplitterIndex < 0)
return false;
- point = View()->ConvertToScreen(point);
+ point = Owner()->ConvertToScreen(point);
int32 valueDiff;
if (fOrientation == B_HORIZONTAL)
@@ -712,7 +712,7 @@
BSplitLayout::Archive(BMessage* into, bool deep) const
{
BArchiver archiver(into);
- status_t err = BLayout::Archive(into, deep);
+ status_t err = BAbstractLayout::Archive(into, deep);
if (err == B_OK)
err = into->AddBool(kIsVerticalField, fOrientation == B_VERTICAL);
@@ -811,10 +811,10 @@
void
-BSplitLayout::_InvalidateLayout(bool invalidateView)
+BSplitLayout::_InvalidateLayout(bool invalidateView, bool children)
{
if (invalidateView)
- BLayout::InvalidateLayout();
+ BAbstractLayout::InvalidateLayout(children);
delete fHorizontalLayouter;
delete fVerticalLayouter;
@@ -929,7 +929,7 @@
info->max = item->MaxSize();
if (item->HasHeightForWidth()) {
- BSize size = _SubtractInsets(View()->Frame().Size());
+ BSize size = _SubtractInsets(LayoutArea().Size());
float minHeight, maxHeight;
item->GetHeightForWidth(size.width, &minHeight, &maxHeight, NULL);
info->min.height = max_c(info->min.height, minHeight);
@@ -958,9 +958,9 @@
item->AlignInFrame(info->layoutFrame);
// if the item became visible, we need to update its internal layout
- if (visibilityChanged) {
- if (BView* itemView = item->View())
- itemView->Layout(false);
+ if (visibilityChanged && fOrientation != B_HORIZONTAL
+ && !HasHeightForWidth()) {
+ item->Relayout(true);
}
}
@@ -1216,7 +1216,7 @@
}
// Just updating the splitter weights is fine in principle. The next
- // LayoutView() will use the correct values. But, if our orientation is
+ // LayoutItems() will use the correct values. But, if our orientation is
// vertical, the cached height for width info needs to be flushed, or the
// obsolete cached values will be used.
if (fOrientation == B_VERTICAL)
@@ -1293,8 +1293,7 @@
if (fHeightForWidthItems.IsEmpty())
fVerticalLayoutInfo = fVerticalLayouter->CreateLayoutInfo();
- if (BView* view = View())
- view->ResetLayoutInvalidation();
+ ResetLayoutInvalidation();
}
Index: src/kits/interface/TwoDimensionalLayout.cpp
===================================================================
--- src/kits/interface/TwoDimensionalLayout.cpp (revision 38092)
+++ src/kits/interface/TwoDimensionalLayout.cpp (working copy)
@@ -258,7 +258,7 @@
BTwoDimensionalLayout::BTwoDimensionalLayout(BMessage* from)
:
- BLayout(from),
+ BAbstractLayout(from),
fLeftInset(0),
fRightInset(0),
fTopInset(0),
@@ -324,7 +324,7 @@
BSize
-BTwoDimensionalLayout::MinSize()
+BTwoDimensionalLayout::BaseMinSize()
{
_ValidateMinMax();
return AddInsets(fLocalLayouter->MinSize());
@@ -332,7 +332,7 @@
BSize
-BTwoDimensionalLayout::MaxSize()
+BTwoDimensionalLayout::BaseMaxSize()
{
_ValidateMinMax();
return AddInsets(fLocalLayouter->MaxSize());
@@ -340,7 +340,7 @@
BSize
-BTwoDimensionalLayout::PreferredSize()
+BTwoDimensionalLayout::BasePreferredSize()
{
_ValidateMinMax();
return AddInsets(fLocalLayouter->PreferredSize());
@@ -348,9 +348,9 @@
BAlignment
-BTwoDimensionalLayout::Alignment()
+BTwoDimensionalLayout::BaseAlignment()
{
- return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
+ return BAbstractLayout::BaseAlignment();
}
@@ -377,72 +377,25 @@
void
-BTwoDimensionalLayout::InvalidateLayout()
+BTwoDimensionalLayout::SetFrame(BRect frame)
{
- BLayout::InvalidateLayout();
-
- fLocalLayouter->InvalidateLayout();
+ BAbstractLayout::SetFrame(frame);
}
void
-BTwoDimensionalLayout::LayoutView()
+BTwoDimensionalLayout::InvalidateLayout(bool children)
{
- _ValidateMinMax();
-
- // layout the horizontal/vertical elements
- BSize size = SubtractInsets(View()->Frame().Size());
-
-#ifdef DEBUG_LAYOUT
-printf("BTwoDimensionalLayout::LayoutView(%p): size: (%.1f, %.1f)\n",
-View(), size.width, size.height);
-#endif
-
- fLocalLayouter->Layout(size);
-
- // layout the items
- int itemCount = CountItems();
- for (int i = 0; i < itemCount; i++) {
- BLayoutItem* item = ItemAt(i);
- if (item->IsVisible()) {
- Dimensions itemDimensions;
- GetItemDimensions(item, &itemDimensions);
- BRect frame = fLocalLayouter->ItemFrame(itemDimensions);
- frame.left += fLeftInset;
- frame.top += fTopInset;
- frame.right += fLeftInset;
- frame.bottom += fTopInset;
-{
-#ifdef DEBUG_LAYOUT
-printf(" frame for item %2d (view: %p): ", i, item->View());
-frame.PrintToStream();
-#endif
-//BSize min(item->MinSize());
-//BSize max(item->MaxSize());
-//printf(" min: (%.1f, %.1f), max: (%.1f, %.1f)\n", min.width, min.height,
-// max.width, max.height);
-//if (item->HasHeightForWidth()) {
-//float minHeight, maxHeight, preferredHeight;
-//item->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight,
-// &preferredHeight);
-//printf(" hfw: min: %.1f, max: %.1f, pref: %.1f\n", minHeight, maxHeight,
-// preferredHeight);
-//}
+ BLayout::InvalidateLayout(children);
+ fLocalLayouter->InvalidateLayout();
}
- item->AlignInFrame(frame);
- }
-//else
-//printf(" item %2d not visible", i);
- }
-}
-
status_t
BTwoDimensionalLayout::Archive(BMessage* into, bool deep) const
{
BArchiver archiver(into);
- status_t err = BLayout::Archive(into, deep);
+ status_t err = BAbstractLayout::Archive(into, deep);
if (err == B_OK) {
BRect insets(fLeftInset, fTopInset, fRightInset, fBottomInset);
@@ -487,6 +440,61 @@
}
+void
+BTwoDimensionalLayout::DerivedLayoutItems()
+{
+ _ValidateMinMax();
+
+ // layout the horizontal/vertical elements
+ BSize size(SubtractInsets(LayoutArea().Size()));
+
+#ifdef DEBUG_LAYOUT
+printf("BTwoDimensionalLayout::DerivedLayoutItems(): view: %p"
+ " size: (%.1f, %.1f)\n", View(), size.Width(), size.Height());
+#endif
+
+ fLocalLayouter->Layout(size);
+
+ // layout the items
+ BPoint itemOffset(LayoutArea().LeftTop());
+ int itemCount = CountItems();
+ for (int i = 0; i < itemCount; i++) {
+ BLayoutItem* item = ItemAt(i);
+ if (item->IsVisible()) {
+ Dimensions itemDimensions;
+ GetItemDimensions(item, &itemDimensions);
+ BRect frame = fLocalLayouter->ItemFrame(itemDimensions);
+ frame.left += fLeftInset;
+ frame.top += fTopInset;
+ frame.right += fLeftInset;
+ frame.bottom += fTopInset;
+ frame.OffsetBy(itemOffset);
+{
+#ifdef DEBUG_LAYOUT
+printf(" frame for item %2d (view: %p): ", i, item->View());
+frame.PrintToStream();
+#endif
+//BSize min(item->MinSize());
+//BSize max(item->MaxSize());
+//printf(" min: (%.1f, %.1f), max: (%.1f, %.1f)\n", min.width, min.height,
+// max.width, max.height);
+//if (item->HasHeightForWidth()) {
+//float minHeight, maxHeight, preferredHeight;
+//item->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight,
+// &preferredHeight);
+//printf(" hfw: min: %.1f, max: %.1f, pref: %.1f\n", minHeight, maxHeight,
+// preferredHeight);
+//}
+}
+
+ item->AlignInFrame(frame);
+ }
+//else
+//printf(" item %2d not visible", i);
+ }
+}
+
+
BSize
BTwoDimensionalLayout::AddInsets(BSize size)
{
@@ -547,20 +555,9 @@
BTwoDimensionalLayout::_ValidateMinMax()
{
fLocalLayouter->ValidateMinMax();
-
- if (BView* view = View())
- view->ResetLayoutInvalidation();
}
-BLayoutContext*
-BTwoDimensionalLayout::_CurrentLayoutContext()
-{
- BView* view = View();
- return (view ? view->LayoutContext() : NULL);
-}
-
-
// #pragma mark - CompoundLayouter
@@ -1060,7 +1057,7 @@
BTwoDimensionalLayout::LocalLayouter::Layout(BSize size)
{
DoHorizontalLayout(size.width);
- fVLayouter->Layout(size.height, this, fLayout->_CurrentLayoutContext());
+ fVLayouter->Layout(size.height, this, fLayout->LayoutContext());
}
@@ -1092,13 +1089,14 @@
fHLayouter->ValidateMinMax();
fVLayouter->ValidateMinMax();
+ fLayout->ResetLayoutInvalidation();
}
void
BTwoDimensionalLayout::LocalLayouter::DoHorizontalLayout(float width)
{
- BLayoutContext* context = fLayout->_CurrentLayoutContext();
+ BLayoutContext* context = fLayout->LayoutContext();
if (fHorizontalLayoutContext != context
|| width != fHorizontalLayoutWidth) {
_SetHorizontalLayoutContext(context, width);
Index: src/kits/interface/Window.cpp
===================================================================
--- src/kits/interface/Window.cpp (revision 38092)
+++ src/kits/interface/Window.cpp (working copy)
@@ -543,6 +543,15 @@
}
+void
+BWindow::AddChild(BLayoutItem* child)
+{
+ BAutolock locker(this);
+ if (locker.IsLocked())
+ fTopView->AddChild(child);
+}
+
+
bool
BWindow::RemoveChild(BView* child)
{
Index: src/kits/interface/GridLayoutBuilder.cpp
===================================================================
--- src/kits/interface/GridLayoutBuilder.cpp (revision 38092)
+++ src/kits/interface/GridLayoutBuilder.cpp (working copy)
@@ -45,7 +45,7 @@
BView*
BGridLayoutBuilder::View() const
{
- return fLayout->View();
+ return fLayout->Owner();
}
// GetGridLayout
@@ -60,7 +60,7 @@
BGridLayoutBuilder&
BGridLayoutBuilder::GetView(BView** _view)
{
- *_view = fLayout->View();
+ *_view = fLayout->Owner();
return *this;
}
@@ -112,8 +112,3 @@
return fLayout;
}
-// cast operator BView*
-BGridLayoutBuilder::operator BView*()
-{
- return fLayout->View();
-}
Index: headers/os/interface/TwoDimensionalLayout.h
===================================================================
--- headers/os/interface/TwoDimensionalLayout.h (revision 38092)
+++ headers/os/interface/TwoDimensionalLayout.h (working copy)
@@ -6,12 +6,12 @@
#define _TWO_DIMENSIONAL_LAYOUT_H
-#include
+#include
class BLayoutContext;
-class BTwoDimensionalLayout : public BLayout {
+class BTwoDimensionalLayout : public BAbstractLayout {
public:
BTwoDimensionalLayout();
BTwoDimensionalLayout(BMessage* from);
@@ -25,18 +25,18 @@
void AlignLayoutWith(BTwoDimensionalLayout* other,
enum orientation orientation);
- virtual BSize MinSize();
- virtual BSize MaxSize();
- virtual BSize PreferredSize();
- virtual BAlignment Alignment();
+ virtual BSize BaseMinSize();
+ virtual BSize BaseMaxSize();
+ virtual BSize BasePreferredSize();
+ virtual BAlignment BaseAlignment();
virtual bool HasHeightForWidth();
virtual void GetHeightForWidth(float width, float* min,
float* max, float* preferred);
- virtual void InvalidateLayout();
+ virtual void SetFrame(BRect frame);
- virtual void LayoutView();
+ virtual void InvalidateLayout(bool children = false);
virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual status_t AllArchived(BMessage* into) const;
@@ -56,6 +56,8 @@
int32 height;
};
+ virtual void DerivedLayoutItems();
+
BSize AddInsets(BSize size);
void AddInsets(float* minHeight, float* maxHeight,
float* preferredHeight);
@@ -82,7 +84,6 @@
friend class LocalLayouter;
void _ValidateMinMax();
- BLayoutContext* _CurrentLayoutContext();
protected:
float fLeftInset;
Index: headers/os/interface/Layout.h
===================================================================
--- headers/os/interface/Layout.h (revision 38092)
+++ headers/os/interface/Layout.h (working copy)
@@ -8,22 +8,27 @@
#include
#include
+#include
#include
#include
+class BLayoutContext;
class BLayoutItem;
class BView;
-class BLayout : public BArchivable {
+class BLayout : public BLayoutItem {
public:
BLayout();
BLayout(BMessage* archive);
virtual ~BLayout();
- BView* View() const;
+ BView* Owner() const;
+ BView* TargetView() const;
+ virtual BView* View(); // from BLayoutItem
+ // methods dealing with items
virtual BLayoutItem* AddView(BView* child);
virtual BLayoutItem* AddView(int32 index, BView* child);
@@ -39,19 +44,23 @@
int32 IndexOfItem(const BLayoutItem* item) const;
int32 IndexOfView(BView* child) const;
- virtual BSize MinSize() = 0;
- virtual BSize MaxSize() = 0;
- virtual BSize PreferredSize() = 0;
- virtual BAlignment Alignment() = 0;
+ bool AncestorsVisible();
- virtual bool HasHeightForWidth() = 0;
- virtual void GetHeightForWidth(float width, float* min,
- float* max, float* preferred) = 0;
+ // Layouting related methods
- virtual void InvalidateLayout();
+ virtual void InvalidateLayout(bool children = false);
+ virtual void Relayout(bool immediate = false);
+ void RequireLayout();
+ bool IsValid();
+ void EnableLayoutInvalidation();
+ void DisableLayoutInvalidation();
- virtual void LayoutView() = 0;
+ void LayoutItems(bool force = false);
+ BRect LayoutArea();
+ BLayoutContext* LayoutContext();
+ // Archiving methods
+
virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual status_t AllUnarchived(const BMessage* from);
@@ -59,17 +68,44 @@
int32 index) const;
virtual status_t ItemUnarchived(const BMessage* from,
BLayoutItem* item, int32 index);
+
protected:
+ // BLayout hook methods
virtual bool ItemAdded(BLayoutItem* item, int32 atIndex);
virtual void ItemRemoved(BLayoutItem* item, int32 fromIndex);
+ virtual void DerivedLayoutItems() = 0;
+ virtual void OwnerChanged(BView* was);
+ // BLayoutItem hook methods
+ virtual void AttachedToLayout();
+ virtual void DetachedFromLayout(BLayout* layout);
+ virtual void AncestorVisibilityChanged(bool shown);
+
+ // To be called by sub-classes in SetVisible().
+ void VisibilityChanged(bool show);
+ // To be called when layout data is known to be good
+ void ResetLayoutInvalidation();
+
private:
friend class BView;
- void SetView(BView* view);
+ bool RemoveViewRecursive(BView* view);
+ bool InvalidateLayoutsForView(BView* view);
+ bool InvalidationLegal();
+ void SetOwner(BView* owner);
+ void SetTarget(BView* target);
- BView* fView;
+ void _LayoutWithinContext(bool force,
+ BLayoutContext* context);
+
+ uint32 fState;
+ bool fAncestorsVisible;
+ int32 fInvalidationDisabled;
+ BLayoutContext* fContext;
+ BView* fOwner;
+ BView* fTarget;
BList fItems;
+ BList fNestedLayouts;
};
Index: headers/os/interface/LayoutBuilder.h
===================================================================
--- headers/os/interface/LayoutBuilder.h (revision 38092)
+++ headers/os/interface/LayoutBuilder.h (working copy)
@@ -33,7 +33,6 @@
public:
inline void SetParent(ParentBuilder* parent);
// conceptually private
-
inline ParentBuilder& End();
protected:
@@ -71,11 +70,23 @@
inline GroupBuilder AddGroup(enum orientation orientation,
float spacing = 0.0f, float weight = 1.0f);
+ inline GroupBuilder AddGroup(BGroupView* groupView,
+ float weight = 1.0f);
+ inline GroupBuilder AddGroup(BGroupLayout* groupLayout,
+ float weight = 1.0f);
+
inline GridBuilder AddGrid(float horizontalSpacing = 0.0f,
float verticalSpacing = 0.0f,
float weight = 1.0f);
+ inline GridBuilder AddGrid(BGridLayout* gridLayout,
+ float weight = 1.0f);
+ inline GridBuilder AddGrid(BGridView* gridView,
+ float weight = 1.0f);
+
inline SplitBuilder AddSplit(enum orientation orientation,
float spacing = 0.0f, float weight = 1.0f);
+ inline SplitBuilder AddSplit(BSplitView* splitView,
+ float weight = 1.0f);
inline ThisBuilder& AddGlue(float weight = 1.0f);
inline ThisBuilder& AddStrut(float size);
@@ -84,7 +95,6 @@
float bottom);
inline operator BGroupLayout*();
- inline operator BView*();
private:
BGroupLayout* fLayout;
@@ -131,13 +141,30 @@
inline GroupBuilder AddGroup(enum orientation orientation,
float spacing, int32 column, int32 row,
int32 columnCount = 1, int32 rowCount = 1);
+ inline GroupBuilder AddGroup(BGroupView* groupView, int32 column,
+ int32 row, int32 columnCount = 1,
+ int32 rowCount = 1);
+ inline GroupBuilder AddGroup(BGroupLayout* groupLayout,
+ int32 column, int32 row,
+ int32 columnCount = 1, int32 rowCount = 1);
+
inline GridBuilder AddGrid(float horizontalSpacing,
float verticalSpacing, int32 column,
int32 row, int32 columnCount = 1,
int32 rowCount = 1);
+ inline GridBuilder AddGrid(BGridLayout* gridLayout,
+ int32 column, int32 row,
+ int32 columnCount = 1, int32 rowCount = 1);
+ inline GridBuilder AddGrid(BGridView* gridView,
+ int32 column, int32 row,
+ int32 columnCount = 1, int32 rowCount = 1);
+
inline SplitBuilder AddSplit(enum orientation orientation,
float spacing, int32 column, int32 row,
int32 columnCount = 1, int32 rowCount = 1);
+ inline SplitBuilder AddSplit(BSplitView* splitView, int32 column,
+ int32 row, int32 columnCount = 1,
+ int32 rowCount = 1);
inline ThisBuilder& SetColumnWeight(int32 column, float weight);
inline ThisBuilder& SetRowWeight(int32 row, float weight);
@@ -146,7 +173,6 @@
float bottom);
inline operator BGridLayout*();
- inline operator BView*();
private:
BGridLayout* fLayout;
@@ -168,7 +194,8 @@
inline Split(BSplitView* view);
inline BSplitView* View() const;
- inline ThisBuilder& GetView(BSplitView** _view);
+ inline ThisBuilder& GetView(BView** _view);
+ inline ThisBuilder& GetSplitView(BSplitView** _view);
inline ThisBuilder& Add(BView* view);
inline ThisBuilder& Add(BView* view, float weight);
@@ -177,11 +204,23 @@
inline GroupBuilder AddGroup(enum orientation orientation,
float spacing = 0.0f, float weight = 1.0f);
+ inline GroupBuilder AddGroup(BGroupView* groupView,
+ float weight = 1.0f);
+ inline GroupBuilder AddGroup(BGroupLayout* groupLayout,
+ float weight = 1.0f);
+
inline GridBuilder AddGrid(float horizontalSpacing = 0.0f,
float verticalSpacing = 0.0f,
float weight = 1.0f);
+ inline GridBuilder AddGrid(BGridView* gridView,
+ float weight = 1.0f);
+ inline GridBuilder AddGrid(BGridLayout* gridLayout,
+ float weight = 1.0f);
+
inline SplitBuilder AddSplit(enum orientation orientation,
float spacing = 0.0f, float weight = 1.0f);
+ inline SplitBuilder AddSplit(BSplitView* splitView,
+ float weight = 1.0f);
inline ThisBuilder& SetCollapsible(bool collapsible);
inline ThisBuilder& SetCollapsible(int32 index, bool collapsible);
@@ -244,7 +283,7 @@
{
window->SetLayout(fLayout);
- fLayout->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+ fLayout->Owner()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// TODO: we get a white background if we don't do this
}
@@ -277,7 +316,7 @@
BView*
Group::View() const
{
- return fLayout->View();
+ return fLayout->Owner();
}
@@ -294,7 +333,7 @@
typename Group::ThisBuilder&
Group::GetView(BView** _view)
{
- *_view = fLayout->View();
+ *_view = fLayout->Owner();
return *this;
}
@@ -340,26 +379,70 @@
Group::AddGroup(enum orientation orientation, float spacing,
float weight)
{
- GroupBuilder builder(orientation, spacing);
+ GroupBuilder builder(new BGroupLayout(orientation, spacing));
builder.SetParent(this);
- fLayout->AddView(builder.View(), weight);
+ fLayout->AddItem(builder.Layout(), weight);
return builder;
}
template
+typename Group::GroupBuilder
+Group::AddGroup(BGroupView* groupView, float weight)
+{
+ GroupBuilder builder(groupView);
+ builder.SetParent(this);
+ fLayout->AddItem(builder.Layout(), weight);
+ return builder;
+}
+
+
+template
+typename Group::GroupBuilder
+Group::AddGroup(BGroupLayout* groupLayout, float weight)
+{
+ GroupBuilder builder(groupLayout);
+ builder.SetParent(this);
+ fLayout->AddItem(builder.Layout(), weight);
+ return builder;
+}
+
+
+template
typename Group::GridBuilder
-Group::AddGrid(float horizontalSpacing, float verticalSpacing,
- float weight)
+Group::AddGrid(float horizontalSpacing,
+ float verticalSpacing, float weight)
{
- GridBuilder builder(horizontalSpacing, verticalSpacing);
+ GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
builder.SetParent(this);
- fLayout->AddView(builder.View(), weight);
+ fLayout->AddItem(builder.Layout(), weight);
return builder;
}
template
+typename Group::GridBuilder
+Group::AddGrid(BGridLayout* gridLayout, float weight)
+{
+ GridBuilder builder(gridLayout);
+ builder.SetParent(this);
+ fLayout->AddItem(builder.Layout(), weight);
+ return builder;
+}
+
+
+template
+typename Group::GridBuilder
+Group::AddGrid(BGridView* gridView, float weight)
+{
+ GridBuilder builder(gridView);
+ builder.SetParent(this);
+ fLayout->AddItem(builder.Layout(), weight);
+ return builder;
+}
+
+
+template
typename Group::SplitBuilder
Group::AddSplit(enum orientation orientation, float spacing,
float weight)
@@ -372,6 +455,17 @@
template
+typename Group::SplitBuilder
+Group::AddSplit(BSplitView* splitView, float weight)
+{
+ SplitBuilder builder(splitView);
+ builder.SetParent(this);
+ fLayout->AddView(builder.View(), weight);
+ return builder;
+}
+
+
+template
typename Group::ThisBuilder&
Group::AddGlue(float weight)
{
@@ -410,13 +504,6 @@
}
-template
-Group::operator BView*()
-{
- return fLayout->View();
-}
-
-
// #pragma mark - Grid
@@ -436,7 +523,7 @@
{
window->SetLayout(fLayout);
- fLayout->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+ fLayout->Owner()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// TODO: we get a white background if we don't do this
}
@@ -469,7 +556,7 @@
BView*
Grid::View() const
{
- return fLayout->View();
+ return fLayout->Owner();
}
@@ -486,7 +573,7 @@
typename Grid::ThisBuilder&
Grid::GetView(BView** _view)
{
- *_view = fLayout->View();
+ *_view = fLayout->Owner();
return *this;
}
@@ -546,20 +633,56 @@
Grid::AddGroup(enum orientation orientation, float spacing,
int32 column, int32 row, int32 columnCount, int32 rowCount)
{
- GroupBuilder builder(orientation, spacing);
+ GroupBuilder builder(new BGroupLayout(orientation, spacing));
builder.SetParent(this);
- fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
+ fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
return builder;
}
template
+typename Grid::GroupBuilder
+Grid::AddGroup(BGroupView* groupView, int32 column, int32 row,
+ int32 columnCount, int32 rowCount)
+{
+ GroupBuilder builder(groupView);
+ builder.SetParent(this);
+ fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
+ return builder;
+}
+
+
+template
+typename Grid::GroupBuilder
+Grid::AddGroup(BGroupLayout* groupLayout, int32 column,
+ int32 row, int32 columnCount, int32 rowCount)
+{
+ GroupBuilder builder(groupLayout);
+ builder.SetParent(this);
+ fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
+ return builder;
+}
+
+
+template
typename Grid::GridBuilder
Grid::AddGrid(float horizontalSpacing, float verticalSpacing,
int32 column, int32 row, int32 columnCount, int32 rowCount)
{
- GridBuilder builder(horizontalSpacing, verticalSpacing);
+ GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
builder.SetParent(this);
+ fLayout->AddItem(builder.Layout(), column, row, columnCount, rowCount);
+ return builder;
+}
+
+
+template
+typename Grid::GridBuilder
+Grid::AddGrid(BGridView* gridView, int32 column, int32 row,
+ int32 columnCount, int32 rowCount)
+{
+ GridBuilder builder(gridView);
+ builder.SetParent(this);
fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
return builder;
}
@@ -574,10 +697,22 @@
builder.SetParent(this);
fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
return builder;
-}
+}
template
+typename Grid::SplitBuilder
+Grid::AddSplit(BSplitView* splitView, int32 column, int32 row,
+ int32 columnCount, int32 rowCount)
+{
+ SplitBuilder builder(splitView);
+ builder.SetParent(this);
+ fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
+ return builder;
+}
+
+
+template
typename Grid::ThisBuilder&
Grid::SetColumnWeight(int32 column, float weight)
{
@@ -612,13 +747,6 @@
}
-template
-Grid::operator BView*()
-{
- return fLayout->View();
-}
-
-
// #pragma mark - Split
@@ -648,7 +776,7 @@
template
typename Split::ThisBuilder&
-Split::GetView(BSplitView** _view)
+Split::GetView(BView** _view)
{
*_view = fView;
return *this;
@@ -657,6 +785,15 @@
template
typename Split::ThisBuilder&
+Split::GetSplitView(BSplitView** _view)
+{
+ *_view = fView;
+ return *this;
+}
+
+
+template
+typename Split::ThisBuilder&
Split::Add(BView* view)
{
fView->AddChild(view);
@@ -696,26 +833,70 @@
Split::AddGroup(enum orientation orientation, float spacing,
float weight)
{
- GroupBuilder builder(orientation, spacing);
+ GroupBuilder builder(new BGroupLayout(orientation, spacing));
builder.SetParent(this);
- fView->AddChild(builder.View(), weight);
+ fView->AddChild(builder.Layout(), weight);
return builder;
}
template
+typename Split::GroupBuilder
+Split::AddGroup(BGroupView* groupView, float weight)
+{
+ GroupBuilder builder(groupView);
+ builder.SetParent(this);
+ fView->AddChild(builder.Layout(), weight);
+ return builder;
+}
+
+
+template
+typename Split::GroupBuilder
+Split::AddGroup(BGroupLayout* groupLayout, float weight)
+{
+ GroupBuilder builder(groupLayout);
+ builder.SetParent(this);
+ fView->AddChild(builder.Layout(), weight);
+ return builder;
+}
+
+
+template
typename Split::GridBuilder
Split::AddGrid(float horizontalSpacing, float verticalSpacing,
float weight)
{
- GridBuilder builder(horizontalSpacing, verticalSpacing);
+ GridBuilder builder(new BGridLayout(horizontalSpacing, verticalSpacing));
builder.SetParent(this);
- fView->AddChild(builder.View(), weight);
+ fView->AddChild(builder.Layout(), weight);
return builder;
}
template
+typename Split::GridBuilder
+Split::AddGrid(BGridView* gridView, float weight)
+{
+ GridBuilder builder(gridView);
+ builder.SetParent(this);
+ fView->AddChild(builder.Layout(), weight);
+ return builder;
+}
+
+
+template
+typename Split::GridBuilder
+Split::AddGrid(BGridLayout* layout, float weight)
+{
+ GridBuilder builder(layout);
+ builder.SetParent(this);
+ fView->AddChild(builder.Layout(), weight);
+ return builder;
+}
+
+
+template
typename Split::SplitBuilder
Split::AddSplit(enum orientation orientation, float spacing,
float weight)
Index: headers/os/interface/GridLayoutBuilder.h
===================================================================
--- headers/os/interface/GridLayoutBuilder.h (revision 38092)
+++ headers/os/interface/GridLayoutBuilder.h (working copy)
@@ -16,9 +16,9 @@
BGridLayoutBuilder(BGridView* view);
BGridLayout* GridLayout() const;
- BView* View() const;
BGridLayoutBuilder& GetGridLayout(BGridLayout** _layout);
- BGridLayoutBuilder& GetView(BView** _view);
+ BView* View() const;
+ BGridLayoutBuilder& GetView(BView** _view);
BGridLayoutBuilder& Add(BView* view, int32 column, int32 row,
int32 columnCount = 1, int32 rowCount = 1);
@@ -32,7 +32,6 @@
float bottom);
operator BGridLayout*();
- operator BView*();
private:
BGridLayout* fLayout;
Index: headers/os/interface/GroupLayoutBuilder.h
===================================================================
--- headers/os/interface/GroupLayoutBuilder.h (revision 38092)
+++ headers/os/interface/GroupLayoutBuilder.h (working copy)
@@ -1,5 +1,5 @@
/*
- * Copyright 2006, Haiku, Inc. All rights reserved.
+ * Copyright 2006-2010, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _GROUP_LAYOUT_BUILDER_H
@@ -39,7 +39,6 @@
float bottom);
operator BGroupLayout*();
- operator BView*();
private:
bool _PushLayout(BGroupLayout* layout);
Index: headers/os/interface/CardLayout.h
===================================================================
--- headers/os/interface/CardLayout.h (revision 38092)
+++ headers/os/interface/CardLayout.h (working copy)
@@ -5,10 +5,10 @@
#ifndef _CARD_LAYOUT_H
#define _CARD_LAYOUT_H
-#include
+#include
-class BCardLayout : public BLayout {
+class BCardLayout : public BAbstractLayout {
public:
BCardLayout();
BCardLayout(BMessage* from);
@@ -19,23 +19,23 @@
void SetVisibleItem(int32 index);
void SetVisibleItem(BLayoutItem* item);
- virtual BSize MinSize();
- virtual BSize MaxSize();
- virtual BSize PreferredSize();
- virtual BAlignment Alignment();
+ virtual BSize BaseMinSize();
+ virtual BSize BaseMaxSize();
+ virtual BSize BasePreferredSize();
+ virtual BAlignment BaseAlignment();
virtual bool HasHeightForWidth();
virtual void GetHeightForWidth(float width, float* min,
float* max, float* preferred);
- virtual void InvalidateLayout();
- virtual void LayoutView();
+ virtual void InvalidateLayout(bool children = false);
virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual status_t AllUnarchived(const BMessage* from);
static BArchivable* Instantiate(BMessage* from);
protected:
+ virtual void DerivedLayoutItems();
virtual bool ItemAdded(BLayoutItem* item, int32 atIndex);
virtual void ItemRemoved(BLayoutItem* item, int32 fromIndex);
Index: headers/os/interface/Window.h
===================================================================
--- headers/os/interface/Window.h (revision 38092)
+++ headers/os/interface/Window.h (working copy)
@@ -103,6 +103,7 @@
void Close() { Quit(); }
void AddChild(BView* child, BView* before = NULL);
+ void AddChild(BLayoutItem* child);
bool RemoveChild(BView* child);
int32 CountChildren() const;
BView* ChildAt(int32 index) const;
Index: headers/os/interface/View.h
===================================================================
--- headers/os/interface/View.h (revision 38092)
+++ headers/os/interface/View.h (working copy)
@@ -562,6 +562,8 @@
void Layout(bool force);
void Relayout();
+ class Private;
+
protected:
virtual void DoLayout();
@@ -580,6 +582,8 @@
private:
void _Layout(bool force, BLayoutContext* context);
+ void _LayoutLeft(BLayout* deleted);
+ void _InvalidateParentLayout();
private:
// FBC padding and forbidden methods
@@ -595,6 +599,7 @@
private:
struct LayoutData;
+ friend class Private;
friend class BBitmap;
friend class BLayout;
friend class BPrintJob;
Index: headers/os/interface/LayoutItem.h
===================================================================
--- headers/os/interface/LayoutItem.h (revision 38092)
+++ headers/os/interface/LayoutItem.h (working copy)
@@ -16,7 +16,7 @@
class BView;
-class BLayoutItem: public BArchivable {
+class BLayoutItem : public BArchivable {
public:
BLayoutItem();
BLayoutItem(BMessage* from);
@@ -46,7 +46,8 @@
virtual BView* View();
- virtual void InvalidateLayout();
+ virtual void InvalidateLayout(bool children = false);
+ virtual void Relayout(bool immediate = false);
void* LayoutData() const;
void SetLayoutData(void* data);
@@ -57,11 +58,19 @@
virtual status_t AllArchived(BMessage* into) const;
virtual status_t AllUnarchived(const BMessage* from);
+protected:
+
+ void SetLayout(BLayout* layout);
+
+ // hook methods
+ virtual void AttachedToLayout();
+ virtual void DetachedFromLayout(BLayout* layout);
+
+ virtual void AncestorVisibilityChanged(bool shown);
+
private:
friend class BLayout;
- void SetLayout(BLayout* layout);
-
BLayout* fLayout;
void* fLayoutData;
};
Index: headers/os/interface/AbstractLayout.h
===================================================================
--- headers/os/interface/AbstractLayout.h (revision 0)
+++ headers/os/interface/AbstractLayout.h (revision 0)
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010, Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _ABSTRACT_LAYOUT_H
+#define _ABSTRACT_LAYOUT_H
+
+#include
+#include
+#include
+
+class BAbstractLayout : public BLayout {
+public:
+ BAbstractLayout();
+ BAbstractLayout(BMessage* from);
+ virtual ~BAbstractLayout();
+
+ virtual BSize MinSize();
+ virtual BSize MaxSize();
+ virtual BSize PreferredSize();
+ virtual BAlignment Alignment();
+
+ virtual void SetExplicitMinSize(BSize size);
+ virtual void SetExplicitMaxSize(BSize size);
+ virtual void SetExplicitPreferredSize(BSize size);
+ virtual void SetExplicitAlignment(BAlignment alignment);
+
+ virtual BSize BaseMinSize();
+ virtual BSize BaseMaxSize();
+ virtual BSize BasePreferredSize();
+ virtual BAlignment BaseAlignment();
+
+ virtual BRect Frame();
+ virtual void SetFrame(BRect frame);
+
+ virtual bool IsVisible();
+ virtual void SetVisible(bool visible);
+
+ virtual status_t Archive(BMessage* into, bool deep = true) const;
+ virtual status_t AllUnarchived(const BMessage* from);
+
+protected:
+ virtual void OwnerChanged(BView* was);
+ virtual void AncestorVisibilityChanged(bool shown);
+
+private:
+ struct Proxy;
+ struct ViewProxy;
+ struct DataProxy;
+
+ Proxy* fExplicitData;
+};
+
+#endif // _ABSTRACT_LAYOUT_ITEM_H
Index: headers/libs/alm/BALMLayout.h
===================================================================
--- headers/libs/alm/BALMLayout.h (revision 38092)
+++ headers/libs/alm/BALMLayout.h (working copy)
@@ -7,8 +7,8 @@
#ifndef BALM_LAYOUT_H
#define BALM_LAYOUT_H
+#include
#include
-#include
#include
#include
#include
@@ -29,7 +29,7 @@
/**
* A GUI layout engine using the ALM.
*/
-class BALMLayout : public BLayout, public LinearSpec {
+class BALMLayout : public BAbstractLayout, public LinearSpec {
public:
BALMLayout();
@@ -70,15 +70,15 @@
bool RemoveItem(BLayoutItem* item);
BLayoutItem* RemoveItem(int32 index);
- BSize MinSize();
- BSize MaxSize();
- BSize PreferredSize();
- BAlignment Alignment();
+ BSize BaseMinSize();
+ BSize BaseMaxSize();
+ BSize BasePreferredSize();
+ BAlignment BaseAlignment();
bool HasHeightForWidth();
void GetHeightForWidth(float width, float* min,
float* max, float* preferred);
- void InvalidateLayout();
- void LayoutView();
+ void InvalidateLayout(bool children = false);
+ virtual void DerivedLayoutItems();
char* PerformancePath() const;
void SetPerformancePath(char* path);
Index: headers/private/interface/ViewPrivate.h
===================================================================
--- headers/private/interface/ViewPrivate.h (revision 38092)
+++ headers/private/interface/ViewPrivate.h (working copy)
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
const static uint32 kDeleteReplicant = 'JAHA';
@@ -48,6 +49,25 @@
};
+class BView::Private {
+public:
+ Private(BView* view)
+ :
+ fView(view)
+ {
+ }
+
+ int16 ShowLevel()
+ {
+ return fView->fShowLevel;
+ }
+
+ bool MinMaxValid();
+
+ BView* fView;
+};
+
+
namespace BPrivate {
class PortLink;