Big change deriving BLayout from BLayoutItem, and allowing viewless BLayouts.

a few highlights:
* BLayout now derives publicly from BLayoutItem
* Added BAbstractLayout class, which our layouts now derive from
* updated layout builders to avoid creating views when they don't need to
* updated layout classes
* updated AboutSystem to fix a little regression
* more details on #6407
* please tell me about any regressions, I've tried to find them all, but some
  may have slipped by.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38207 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alex Wilson
2010-08-17 18:43:41 +00:00
parent 0f274fd5b2
commit 1d6c7b6cb6
28 changed files with 1546 additions and 312 deletions
+8 -8
View File
@@ -7,8 +7,8 @@
#ifndef BALM_LAYOUT_H
#define BALM_LAYOUT_H
#include <AbstractLayout.h>
#include <File.h>
#include <Layout.h>
#include <List.h>
#include <Size.h>
#include <SupportDefs.h>
@@ -29,7 +29,7 @@ namespace BALM {
/**
* 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 @@ public:
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);
+54
View File
@@ -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 <Alignment.h>
#include <Layout.h>
#include <Size.h>
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
+8 -8
View File
@@ -5,10 +5,10 @@
#ifndef _CARD_LAYOUT_H
#define _CARD_LAYOUT_H
#include <Layout.h>
#include <AbstractLayout.h>
class BCardLayout : public BLayout {
class BCardLayout : public BAbstractLayout {
public:
BCardLayout();
BCardLayout(BMessage* from);
@@ -19,23 +19,23 @@ public:
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);
+2 -3
View File
@@ -16,9 +16,9 @@ public:
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 @@ public:
float bottom);
operator BGridLayout*();
operator BView*();
private:
BGridLayout* fLayout;
+1 -2
View File
@@ -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 @@ public:
float bottom);
operator BGroupLayout*();
operator BView*();
private:
bool _PushLayout(BGroupLayout* layout);
+49 -13
View File
@@ -8,22 +8,27 @@
#include <Alignment.h>
#include <Archivable.h>
#include <LayoutItem.h>
#include <List.h>
#include <Size.h>
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,18 +44,22 @@ public:
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 @@ public:
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;
};
+220 -39
View File
@@ -33,7 +33,6 @@ protected:
public:
inline void SetParent(ParentBuilder* parent);
// conceptually private
inline ParentBuilder& End();
protected:
@@ -71,11 +70,23 @@ public:
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 @@ public:
float bottom);
inline operator BGroupLayout*();
inline operator BView*();
private:
BGroupLayout* fLayout;
@@ -131,13 +141,30 @@ public:
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 @@ public:
float bottom);
inline operator BGridLayout*();
inline operator BView*();
private:
BGridLayout* fLayout;
@@ -168,7 +194,8 @@ public:
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 @@ public:
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 @@ Group<ParentBuilder>::Group(BWindow* window, enum orientation orientation,
{
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 @@ template<typename ParentBuilder>
BView*
Group<ParentBuilder>::View() const
{
return fLayout->View();
return fLayout->Owner();
}
@@ -294,7 +333,7 @@ template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::GetView(BView** _view)
{
*_view = fLayout->View();
*_view = fLayout->Owner();
return *this;
}
@@ -340,21 +379,65 @@ typename Group<ParentBuilder>::GroupBuilder
Group<ParentBuilder>::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 ParentBuilder>
typename Group<ParentBuilder>::GroupBuilder
Group<ParentBuilder>::AddGroup(BGroupView* groupView, float weight)
{
GroupBuilder builder(groupView);
builder.SetParent(this);
fLayout->AddItem(builder.Layout(), weight);
return builder;
}
template<typename ParentBuilder>
typename Group<ParentBuilder>::GroupBuilder
Group<ParentBuilder>::AddGroup(BGroupLayout* groupLayout, float weight)
{
GroupBuilder builder(groupLayout);
builder.SetParent(this);
fLayout->AddItem(builder.Layout(), weight);
return builder;
}
template<typename ParentBuilder>
typename Group<ParentBuilder>::GridBuilder
Group<ParentBuilder>::AddGrid(float horizontalSpacing, float verticalSpacing,
float weight)
Group<ParentBuilder>::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 ParentBuilder>
typename Group<ParentBuilder>::GridBuilder
Group<ParentBuilder>::AddGrid(BGridLayout* gridLayout, float weight)
{
GridBuilder builder(gridLayout);
builder.SetParent(this);
fLayout->AddItem(builder.Layout(), weight);
return builder;
}
template<typename ParentBuilder>
typename Group<ParentBuilder>::GridBuilder
Group<ParentBuilder>::AddGrid(BGridView* gridView, float weight)
{
GridBuilder builder(gridView);
builder.SetParent(this);
fLayout->AddItem(builder.Layout(), weight);
return builder;
}
@@ -371,6 +454,17 @@ Group<ParentBuilder>::AddSplit(enum orientation orientation, float spacing,
}
template<typename ParentBuilder>
typename Group<ParentBuilder>::SplitBuilder
Group<ParentBuilder>::AddSplit(BSplitView* splitView, float weight)
{
SplitBuilder builder(splitView);
builder.SetParent(this);
fLayout->AddView(builder.View(), weight);
return builder;
}
template<typename ParentBuilder>
typename Group<ParentBuilder>::ThisBuilder&
Group<ParentBuilder>::AddGlue(float weight)
@@ -410,13 +504,6 @@ Group<ParentBuilder>::operator BGroupLayout*()
}
template<typename ParentBuilder>
Group<ParentBuilder>::operator BView*()
{
return fLayout->View();
}
// #pragma mark - Grid
@@ -436,7 +523,7 @@ Grid<ParentBuilder>::Grid(BWindow* window, float horizontalSpacing,
{
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 @@ template<typename ParentBuilder>
BView*
Grid<ParentBuilder>::View() const
{
return fLayout->View();
return fLayout->Owner();
}
@@ -486,7 +573,7 @@ template<typename ParentBuilder>
typename Grid<ParentBuilder>::ThisBuilder&
Grid<ParentBuilder>::GetView(BView** _view)
{
*_view = fLayout->View();
*_view = fLayout->Owner();
return *this;
}
@@ -546,9 +633,33 @@ typename Grid<ParentBuilder>::GroupBuilder
Grid<ParentBuilder>::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 ParentBuilder>
typename Grid<ParentBuilder>::GroupBuilder
Grid<ParentBuilder>::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 ParentBuilder>
typename Grid<ParentBuilder>::GroupBuilder
Grid<ParentBuilder>::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;
}
@@ -558,7 +669,19 @@ typename Grid<ParentBuilder>::GridBuilder
Grid<ParentBuilder>::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 ParentBuilder>
typename Grid<ParentBuilder>::GridBuilder
Grid<ParentBuilder>::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,7 +697,19 @@ Grid<ParentBuilder>::AddSplit(enum orientation orientation, float spacing,
builder.SetParent(this);
fLayout->AddView(builder.View(), column, row, columnCount, rowCount);
return builder;
}
}
template<typename ParentBuilder>
typename Grid<ParentBuilder>::SplitBuilder
Grid<ParentBuilder>::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 ParentBuilder>
@@ -612,13 +747,6 @@ Grid<ParentBuilder>::operator BGridLayout*()
}
template<typename ParentBuilder>
Grid<ParentBuilder>::operator BView*()
{
return fLayout->View();
}
// #pragma mark - Split
@@ -648,7 +776,16 @@ Split<ParentBuilder>::View() const
template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::GetView(BSplitView** _view)
Split<ParentBuilder>::GetView(BView** _view)
{
*_view = fView;
return *this;
}
template<typename ParentBuilder>
typename Split<ParentBuilder>::ThisBuilder&
Split<ParentBuilder>::GetSplitView(BSplitView** _view)
{
*_view = fView;
return *this;
@@ -696,9 +833,31 @@ typename Split<ParentBuilder>::GroupBuilder
Split<ParentBuilder>::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 ParentBuilder>
typename Split<ParentBuilder>::GroupBuilder
Split<ParentBuilder>::AddGroup(BGroupView* groupView, float weight)
{
GroupBuilder builder(groupView);
builder.SetParent(this);
fView->AddChild(builder.Layout(), weight);
return builder;
}
template<typename ParentBuilder>
typename Split<ParentBuilder>::GroupBuilder
Split<ParentBuilder>::AddGroup(BGroupLayout* groupLayout, float weight)
{
GroupBuilder builder(groupLayout);
builder.SetParent(this);
fView->AddChild(builder.Layout(), weight);
return builder;
}
@@ -708,9 +867,31 @@ typename Split<ParentBuilder>::GridBuilder
Split<ParentBuilder>::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 ParentBuilder>
typename Split<ParentBuilder>::GridBuilder
Split<ParentBuilder>::AddGrid(BGridView* gridView, float weight)
{
GridBuilder builder(gridView);
builder.SetParent(this);
fView->AddChild(builder.Layout(), weight);
return builder;
}
template<typename ParentBuilder>
typename Split<ParentBuilder>::GridBuilder
Split<ParentBuilder>::AddGrid(BGridLayout* layout, float weight)
{
GridBuilder builder(layout);
builder.SetParent(this);
fView->AddChild(builder.Layout(), weight);
return builder;
}
+13 -4
View File
@@ -16,7 +16,7 @@ class BLayout;
class BView;
class BLayoutItem: public BArchivable {
class BLayoutItem : public BArchivable {
public:
BLayoutItem();
BLayoutItem(BMessage* from);
@@ -46,7 +46,8 @@ public:
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 @@ public:
virtual status_t AllArchived(BMessage* into) const;
virtual status_t AllUnarchived(const BMessage* from);
private:
friend class BLayout;
protected:
void SetLayout(BLayout* layout);
// hook methods
virtual void AttachedToLayout();
virtual void DetachedFromLayout(BLayout* layout);
virtual void AncestorVisibilityChanged(bool shown);
private:
friend class BLayout;
BLayout* fLayout;
void* fLayoutData;
};
+10 -9
View File
@@ -6,12 +6,12 @@
#define _TWO_DIMENSIONAL_LAYOUT_H
#include <Layout.h>
#include <AbstractLayout.h>
class BLayoutContext;
class BTwoDimensionalLayout : public BLayout {
class BTwoDimensionalLayout : public BAbstractLayout {
public:
BTwoDimensionalLayout();
BTwoDimensionalLayout(BMessage* from);
@@ -25,18 +25,18 @@ public:
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 @@ protected:
int32 height;
};
virtual void DerivedLayoutItems();
BSize AddInsets(BSize size);
void AddInsets(float* minHeight, float* maxHeight,
float* preferredHeight);
@@ -82,7 +84,6 @@ private:
friend class LocalLayouter;
void _ValidateMinMax();
BLayoutContext* _CurrentLayoutContext();
protected:
float fLeftInset;
+5
View File
@@ -562,6 +562,8 @@ public:
void Layout(bool force);
void Relayout();
class Private;
protected:
virtual void DoLayout();
@@ -580,6 +582,8 @@ protected:
private:
void _Layout(bool force, BLayoutContext* context);
void _LayoutLeft(BLayout* deleted);
void _InvalidateParentLayout();
private:
// FBC padding and forbidden methods
@@ -595,6 +599,7 @@ private:
private:
struct LayoutData;
friend class Private;
friend class BBitmap;
friend class BLayout;
friend class BPrintJob;
+1
View File
@@ -103,6 +103,7 @@ public:
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;
+22
View File
@@ -16,6 +16,7 @@
#include <Rect.h>
#include <Region.h>
#include <ServerProtocolStructs.h>
#include <View.h>
const static uint32 kDeleteReplicant = 'JAHA';
@@ -48,6 +49,27 @@ enum {
};
class BView::Private {
public:
Private(BView* view)
:
fView(view)
{
}
int16 ShowLevel()
{
return fView->fShowLevel;
}
// defined in View.cpp
bool WillLayout();
bool MinMaxValid();
BView* fView;
};
namespace BPrivate {
class PortLink;
+1
View File
@@ -579,6 +579,7 @@ AboutView::AboutView()
const float offset = 5;
SetLayout(new BGroupLayout(B_HORIZONTAL));
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BLayoutBuilder::Group<>((BGroupLayout*)GetLayout())
.AddGroup(B_VERTICAL)
+468
View File
@@ -0,0 +1,468 @@
/*
* Copyright 2010, Haiku, Inc.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include <AbstractLayout.h>
#include <LayoutUtils.h>
#include <Message.h>
#include <View.h>
#include <ViewPrivate.h>
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<ViewProxy*>(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<ViewProxy*>(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);
}
+22 -19
View File
@@ -17,7 +17,7 @@ namespace {
BCardLayout::BCardLayout()
:
BLayout(),
BAbstractLayout(),
fMin(0, 0),
fMax(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED),
fPreferred(0, 0),
@@ -29,7 +29,7 @@ BCardLayout::BCardLayout()
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 @@ BCardLayout::SetVisibleItem(BLayoutItem* item)
if (fVisibleItem != NULL) {
fVisibleItem->SetVisible(true);
LayoutView();
Relayout();
}
}
BSize
BCardLayout::MinSize()
BCardLayout::BaseMinSize()
{
_ValidateMinMax();
return fMin;
@@ -97,7 +97,7 @@ BCardLayout::MinSize()
BSize
BCardLayout::MaxSize()
BCardLayout::BaseMaxSize()
{
_ValidateMinMax();
return fMax;
@@ -105,7 +105,7 @@ BCardLayout::MaxSize()
BSize
BCardLayout::PreferredSize()
BCardLayout::BasePreferredSize()
{
_ValidateMinMax();
return fPreferred;
@@ -113,7 +113,7 @@ BCardLayout::PreferredSize()
BAlignment
BCardLayout::Alignment()
BCardLayout::BaseAlignment()
{
return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
}
@@ -174,25 +174,30 @@ BCardLayout::GetHeightForWidth(float width, float* min, float* max,
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 @@ status_t
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 @@ BCardLayout::_ValidateMinMax()
fPreferred.height = min_c(fPreferred.height, fMax.height);
fMinMaxValid = true;
if (BView* view = View())
view->ResetLayoutInvalidation();
ResetLayoutInvalidation();
}
+2 -7
View File
@@ -45,7 +45,7 @@ BGridLayoutBuilder::GridLayout() const
BView*
BGridLayoutBuilder::View() const
{
return fLayout->View();
return fLayout->Owner();
}
// GetGridLayout
@@ -60,7 +60,7 @@ BGridLayoutBuilder::GetGridLayout(BGridLayout** _layout)
BGridLayoutBuilder&
BGridLayoutBuilder::GetView(BView** _view)
{
*_view = fLayout->View();
*_view = fLayout->Owner();
return *this;
}
@@ -112,8 +112,3 @@ BGridLayoutBuilder::operator BGridLayout*()
return fLayout;
}
// cast operator BView*
BGridLayoutBuilder::operator BView*()
{
return fLayout->View();
}
+2 -9
View File
@@ -28,7 +28,6 @@ BGroupLayoutBuilder::BGroupLayoutBuilder(BGroupLayout* layout)
_PushLayout(fRootLayout);
}
// constructor
BGroupLayoutBuilder::BGroupLayoutBuilder(BGroupView* view)
: fRootLayout(view->GroupLayout())
@@ -64,7 +63,7 @@ BGroupLayoutBuilder::GetTopLayout(BGroupLayout** _layout)
BView*
BGroupLayoutBuilder::TopView() const
{
return TopLayout()->View();
return TopLayout()->Owner();
}
// GetTopView
@@ -72,7 +71,7 @@ BGroupLayoutBuilder&
BGroupLayoutBuilder::GetTopView(BView** _view)
{
if (BGroupLayout* layout = TopLayout())
*_view = layout->View();
*_view = layout->Owner();
else
*_view = NULL;
@@ -181,12 +180,6 @@ BGroupLayoutBuilder::operator BGroupLayout*()
return fRootLayout;
}
// cast operator BView*
BGroupLayoutBuilder::operator BView*()
{
return fRootLayout->View();
}
// _PushLayout
bool
BGroupLayoutBuilder::_PushLayout(BGroupLayout* layout)
+1
View File
@@ -31,6 +31,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) textview_support ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) layouter ] ;
MergeObject <libbe>interface_kit.o :
AbstractLayout.cpp
AbstractLayoutItem.cpp
AffineTransform.cpp
Alert.cpp
+344 -27
View File
@@ -7,26 +7,50 @@
#include <Layout.h>
#include <syslog.h>
#include <algorithm>
#include <new>
#include <syslog.h>
#include <LayoutContext.h>
#include <Message.h>
#include <View.h>
#include <ViewPrivate.h>
#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()
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,15 +77,36 @@ BLayout::BLayout(BMessage* from)
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;
}
@@ -70,11 +120,15 @@ BLayout::AddView(BView* child)
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 @@ BLayout::AddItem(BLayoutItem* item)
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 @@ BLayout::AddItem(int32 index, BLayoutItem* item)
if (fItems.AddItem(item, index) && ItemAdded(item, index)) {
item->SetLayout(this);
if (!fAncestorsVisible)
item->AncestorVisibilityChanged(fAncestorsVisible);
InvalidateLayout();
return true;
} else {
@@ -160,11 +216,11 @@ BLayout::RemoveItem(int32 index)
// 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();
item->SetLayout(NULL);
ItemRemoved(item, index);
item->SetLayout(NULL);
InvalidateLayout();
return item;
@@ -206,11 +262,150 @@ BLayout::IndexOfView(BView* child) const
}
void
BLayout::InvalidateLayout()
bool
BLayout::AncestorsVisible()
{
if (fView)
fView->InvalidateLayout();
return fAncestorsVisible;
}
void
BLayout::InvalidateLayout(bool children)
{
// 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 && BView::Private(fOwner).WillLayout()) {
// 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;
}
@@ -218,7 +413,7 @@ 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 @@ status_t
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 @@ BLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex)
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();
}
+49 -3
View File
@@ -8,6 +8,9 @@
#include <Layout.h>
#include <LayoutUtils.h>
#include <View.h>
#include <algorithm>
BLayoutItem::BLayoutItem()
@@ -30,6 +33,8 @@ BLayoutItem::BLayoutItem(BMessage* from)
BLayoutItem::~BLayoutItem()
{
if (fLayout)
fLayout->RemoveItem(this);
}
@@ -64,10 +69,21 @@ BLayoutItem::View()
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);
}
@@ -144,5 +160,35 @@ BLayoutItem::AllUnarchived(const BMessage* from)
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
}
+26 -27
View File
@@ -196,7 +196,7 @@ BSplitLayout::BSplitLayout(enum orientation orientation,
BSplitLayout::BSplitLayout(BMessage* from)
:
BLayout(BUnarchiver::PrepareArchive(from)),
BAbstractLayout(BUnarchiver::PrepareArchive(from)),
fSplitterItems(),
fVisibleItems(),
fMin(),
@@ -340,14 +340,14 @@ BSplitLayout::SetSplitterSize(float size)
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 @@ BSplitLayout::AddView(int32 index, BView* child, float weight)
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 @@ BSplitLayout::SetCollapsible(int32 first, int32 last, bool collapsible)
BSize
BSplitLayout::MinSize()
BSplitLayout::BaseMinSize()
{
_ValidateMinMax();
@@ -489,7 +489,7 @@ BSplitLayout::MinSize()
BSize
BSplitLayout::MaxSize()
BSplitLayout::BaseMaxSize()
{
_ValidateMinMax();
@@ -498,7 +498,7 @@ BSplitLayout::MaxSize()
BSize
BSplitLayout::PreferredSize()
BSplitLayout::BasePreferredSize()
{
_ValidateMinMax();
@@ -507,9 +507,9 @@ BSplitLayout::PreferredSize()
BAlignment
BSplitLayout::Alignment()
BSplitLayout::BaseAlignment()
{
return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
return BAbstractLayout::BaseAlignment();
}
@@ -536,19 +536,19 @@ BSplitLayout::GetHeightForWidth(float width, float* min, float* max,
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 @@ BSplitLayout::StartDraggingSplitter(BPoint point)
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 @@ BSplitLayout::StartDraggingSplitter(BPoint point)
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 @@ BSplitLayout::DragSplitter(BPoint point)
if (fDraggingSplitterIndex < 0)
return false;
point = View()->ConvertToScreen(point);
point = Owner()->ConvertToScreen(point);
int32 valueDiff;
if (fOrientation == B_HORIZONTAL)
@@ -712,7 +712,7 @@ status_t
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 @@ BSplitLayout::ItemRemoved(BLayoutItem* item, int32 atIndex)
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 @@ BSplitLayout::_LayoutItem(BLayoutItem* item, BRect frame, bool visible)
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 @@ BSplitLayout::_LayoutItem(BLayoutItem* item, ItemLayoutInfo* info)
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 @@ BSplitLayout::_UpdateSplitterWeights()
}
// 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 @@ BSplitLayout::_ValidateMinMax()
if (fHeightForWidthItems.IsEmpty())
fVerticalLayoutInfo = fVerticalLayouter->CreateLayoutInfo();
if (BView* view = View())
view->ResetLayoutInvalidation();
ResetLayoutInvalidation();
}
+10 -9
View File
@@ -6,7 +6,7 @@
#define _SPLIT_LAYOUT_H
#include <Layout.h>
#include <AbstractLayout.h>
#include <Point.h>
@@ -21,7 +21,7 @@ using BPrivate::Layout::Layouter;
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 @@ public:
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 @@ private:
class ValueRange;
class SplitterItem;
void _InvalidateLayout(bool invalidateView);
void _InvalidateLayout(bool invalidateView,
bool children = false);
void _InvalidateCachedHeightForWidth();
SplitterItem* _SplitterItemAt(const BPoint& point,
+70 -72
View File
@@ -258,7 +258,7 @@ BTwoDimensionalLayout::BTwoDimensionalLayout()
BTwoDimensionalLayout::BTwoDimensionalLayout(BMessage* from)
:
BLayout(from),
BAbstractLayout(from),
fLeftInset(0),
fRightInset(0),
fTopInset(0),
@@ -324,7 +324,7 @@ BTwoDimensionalLayout::AlignLayoutWith(BTwoDimensionalLayout* other,
BSize
BTwoDimensionalLayout::MinSize()
BTwoDimensionalLayout::BaseMinSize()
{
_ValidateMinMax();
return AddInsets(fLocalLayouter->MinSize());
@@ -332,7 +332,7 @@ BTwoDimensionalLayout::MinSize()
BSize
BTwoDimensionalLayout::MaxSize()
BTwoDimensionalLayout::BaseMaxSize()
{
_ValidateMinMax();
return AddInsets(fLocalLayouter->MaxSize());
@@ -340,7 +340,7 @@ BTwoDimensionalLayout::MaxSize()
BSize
BTwoDimensionalLayout::PreferredSize()
BTwoDimensionalLayout::BasePreferredSize()
{
_ValidateMinMax();
return AddInsets(fLocalLayouter->PreferredSize());
@@ -348,9 +348,9 @@ BTwoDimensionalLayout::PreferredSize()
BAlignment
BTwoDimensionalLayout::Alignment()
BTwoDimensionalLayout::BaseAlignment()
{
return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
return BAbstractLayout::BaseAlignment();
}
@@ -377,64 +377,17 @@ BTwoDimensionalLayout::GetHeightForWidth(float width, float* min, float* max,
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);
//}
}
item->AlignInFrame(frame);
}
//else
//printf(" item %2d not visible", i);
}
BLayout::InvalidateLayout(children);
fLocalLayouter->InvalidateLayout();
}
@@ -442,7 +395,7 @@ 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 @@ BTwoDimensionalLayout::AllUnarchived(const BMessage* from)
}
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,17 +555,6 @@ void
BTwoDimensionalLayout::_ValidateMinMax()
{
fLocalLayouter->ValidateMinMax();
if (BView* view = View())
view->ResetLayoutInvalidation();
}
BLayoutContext*
BTwoDimensionalLayout::_CurrentLayoutContext()
{
BView* view = View();
return (view ? view->LayoutContext() : NULL);
}
@@ -1060,7 +1057,7 @@ void
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 @@ BTwoDimensionalLayout::LocalLayouter::ValidateMinMax()
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);
+82 -26
View File
@@ -648,7 +648,7 @@ BView::AllUnarchived(const BMessage* from)
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 @@ BView::Hide()
fShowLevel++;
if (fShowLevel == 1 && fParent)
fParent->InvalidateLayout();
_InvalidateParentLayout();
}
@@ -1012,7 +1012,7 @@ BView::Show()
}
if (fShowLevel == 0 && fParent)
fParent->InvalidateLayout();
_InvalidateParentLayout();
}
@@ -4020,7 +4020,7 @@ bool
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 @@ BView::SetLayout(BLayout* layout)
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,21 +4679,27 @@ BView::GetLayout() const
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) {
@@ -4724,15 +4733,12 @@ BView::IsLayoutValid() const
}
/*! \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 @@ BView::Relayout()
{
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 @@ void
BView::DoLayout()
{
if (fLayoutData->fLayout)
fLayoutData->fLayout->LayoutView();
fLayoutData->fLayout->_LayoutWithinContext(false, LayoutContext());
}
@@ -4881,9 +4889,7 @@ BView::_Layout(bool force, BLayoutContext* context)
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 @@ BView::_Layout(bool force, BLayoutContext* context)
}
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,25 @@ BView::_PrintTree()
}
}
}
// #pragma mark -
bool
BView::Private::MinMaxValid()
{
return fView->fLayoutData->fMinMaxValid;
}
bool
BView::Private::WillLayout()
{
BView::LayoutData* data = fView->fLayoutData;
if (data->fLayoutInProgress)
return false;
if (data->fNeedsRelayout || !data->fLayoutValid || !data->fMinMaxValid)
return true;
return false;
}
+34 -5
View File
@@ -11,6 +11,7 @@
#include <Layout.h>
#include <View.h>
#include <ViewPrivate.h>
namespace {
@@ -20,7 +21,8 @@ namespace {
BViewLayoutItem::BViewLayoutItem(BView* view)
:
fView(view)
fView(view),
fAncestorsVisible(true)
{
}
@@ -28,7 +30,8 @@ BViewLayoutItem::BViewLayoutItem(BView* view)
BViewLayoutItem::BViewLayoutItem(BMessage* from)
:
BLayoutItem(BUnarchiver::PrepareArchive(from)),
fView(NULL)
fView(NULL),
fAncestorsVisible(true)
{
BUnarchiver unarchiver(from);
unarchiver.Finish(unarchiver.FindObject<BView>(kViewField, 0,
@@ -100,7 +103,8 @@ BViewLayoutItem::SetExplicitAlignment(BAlignment alignment)
bool
BViewLayoutItem::IsVisible()
{
return !fView->IsHidden(fView);
int16 showLevel = BView::Private(fView).ShowLevel();
return showLevel - (fAncestorsVisible ? 0 : 1) <= 0;
}
@@ -154,9 +158,19 @@ BViewLayoutItem::View()
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();
}
@@ -204,3 +218,18 @@ BViewLayoutItem::Instantiate(BMessage* from)
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();
}
+6 -1
View File
@@ -36,15 +36,20 @@ public:
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
+9
View File
@@ -543,6 +543,15 @@ BWindow::AddChild(BView* child, BView* before)
}
void
BWindow::AddChild(BLayoutItem* child)
{
BAutolock locker(this);
if (locker.IsLocked())
fTopView->AddChild(child);
}
bool
BWindow::RemoveChild(BView* child)
{
+27 -21
View File
@@ -20,7 +20,8 @@
* Creates new layout engine.
*/
BALMLayout::BALMLayout()
: BLayout(),
:
BAbstractLayout(),
LinearSpec()
{
fLayoutStyle = FIT_TO_SIZE;
@@ -189,7 +190,7 @@ BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
{
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 @@ BALMLayout::AddArea(Row* row, Column* column, BView* content,
{
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 @@ BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
{
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 @@ BALMLayout::AddArea(Row* row, Column* column, BView* content)
{
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 @@ BALMLayout::RemoveItem(int32 index)
/**
* 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 @@ BSize BALMLayout::MinSize() {
/**
* Sets and gets maximum size.
* Gets maximum size.
*/
BSize
BALMLayout::MaxSize()
BALMLayout::BaseMaxSize()
{
if (fMaxSize == Area::kUndefinedSize)
fMaxSize = CalculateMaxSize();
@@ -457,10 +459,10 @@ BALMLayout::MaxSize()
/**
* Sets and gets preferred size.
* Gets preferred size.
*/
BSize
BALMLayout::PreferredSize()
BALMLayout::BasePreferredSize()
{
if (fPreferredSize == Area::kUndefinedSize)
fPreferredSize = CalculatePreferredSize();
@@ -472,7 +474,7 @@ BALMLayout::PreferredSize()
* Gets the alignment.
*/
BAlignment
BALMLayout::Alignment()
BALMLayout::BaseAlignment()
{
BAlignment alignment;
alignment.SetHorizontal(B_ALIGN_HORIZONTAL_CENTER);
@@ -492,7 +494,7 @@ BALMLayout::HasHeightForWidth()
/**
* 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 @@ BALMLayout::GetHeightForWidth(float width, float* min, float* max, float* prefer
* 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 @@ BALMLayout::InvalidateLayout()
* 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());
BRect area(LayoutArea());
Right()->SetRange(area.right, area.right);
Bottom()->SetRange(area.bottom, area.bottom);
}
SolveLayout();
@@ -554,7 +560,7 @@ BALMLayout::LayoutView()
// 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));
}