From 1a726098ecee6525b34f70b457413e7904ba77a7 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 17 Jun 2009 19:38:51 +0000 Subject: [PATCH] New approach to layout building: * The new builders are templatized and completely inline. * They are easily nestable, which only worked for groups with the old approach. * Added builder for split views. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31094 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/LayoutBuilder.h | 688 +++++++++++++++++++++++++++ 1 file changed, 688 insertions(+) create mode 100644 headers/os/interface/LayoutBuilder.h diff --git a/headers/os/interface/LayoutBuilder.h b/headers/os/interface/LayoutBuilder.h new file mode 100644 index 0000000000..25b196162b --- /dev/null +++ b/headers/os/interface/LayoutBuilder.h @@ -0,0 +1,688 @@ +/* + * Copyright 2009, Haiku Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _LAYOUT_BUILDER_H +#define _LAYOUT_BUILDER_H + +#include +#include +#include +#include +#include +#include + + +namespace BLayoutBuilder { + +template class Base; +template class Group; +template class Grid; +template class Split; + + +template +class Base { +protected: + inline Base(); + +public: + inline void SetParent(ParentBuilder* parent); + // conceptionally private + + inline ParentBuilder& End(); + +protected: + ParentBuilder* fParent; +}; + + +template +class Group : public Base { +public: + typedef Group ThisBuilder; + typedef Group GroupBuilder; + typedef Grid GridBuilder; + typedef Split SplitBuilder; + +public: + inline Group(enum orientation orientation + = B_HORIZONTAL, + float spacing = 0.0f); + inline Group(BGroupLayout* layout); + inline Group(BGroupView* view); + + inline BGroupLayout* Layout() const; + inline BView* View() const; + inline ThisBuilder& GetLayout(BGroupLayout** _layout); + inline ThisBuilder& GetView(BView** _view); + + inline ThisBuilder& Add(BView* view); + inline ThisBuilder& Add(BView* view, float weight); + inline ThisBuilder& Add(BLayoutItem* item); + inline ThisBuilder& Add(BLayoutItem* item, float weight); + + inline GroupBuilder AddGroup(enum orientation orientation, + float spacing = 0.0f, float weight = 1.0f); + inline GridBuilder AddGrid(float horizontalSpacing = 0.0f, + float verticalSpacing = 0.0f, + float weight = 1.0f); + inline SplitBuilder AddSplit(enum orientation orientation, + float spacing = 0.0f, float weight = 1.0f); + + inline ThisBuilder& AddGlue(float weight = 1.0f); + inline ThisBuilder& AddStrut(float size); + + inline ThisBuilder& SetInsets(float left, float top, float right, + float bottom); + + inline operator BGroupLayout*(); + inline operator BView*(); + +private: + BGroupLayout* fLayout; +}; + + +template +class Grid : public Base { +public: + typedef Grid ThisBuilder; + typedef Group GroupBuilder; + typedef Grid GridBuilder; + typedef Split SplitBuilder; + +public: + inline Grid(float horizontalSpacing = 0.0f, + float verticalSpacing = 0.0f); + inline Grid(BGridLayout* layout); + inline Grid(BGridView* view); + + inline BGridLayout* Layout() const; + inline BView* View() const; + inline ThisBuilder& GetLayout(BGridLayout** _layout); + inline ThisBuilder& GetView(BView** _view); + + inline ThisBuilder& Add(BView* view, int32 column, int32 row, + int32 columnCount = 1, int32 rowCount = 1); + inline ThisBuilder& Add(BLayoutItem* item, int32 column, int32 row, + int32 columnCount = 1, int32 rowCount = 1); + + inline GroupBuilder AddGroup(enum orientation orientation, + float spacing, 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 SplitBuilder AddSplit(enum orientation orientation, + float spacing, int32 column, int32 row, + int32 columnCount = 1, int32 rowCount = 1); + + inline ThisBuilder& SetColumnWeight(int32 column, float weight); + inline ThisBuilder& SetRowWeight(int32 row, float weight); + + inline ThisBuilder& SetInsets(float left, float top, float right, + float bottom); + + inline operator BGridLayout*(); + inline operator BView*(); + +private: + BGridLayout* fLayout; +}; + + +template +class Split : public Base { +public: + typedef Split ThisBuilder; + typedef Group GroupBuilder; + typedef Grid GridBuilder; + typedef Split SplitBuilder; + +public: + inline Split(enum orientation orientation + = B_HORIZONTAL, + float spacing = 0.0f); + inline Split(BSplitView* view); + + inline BSplitView* View() const; + inline ThisBuilder& GetView(BSplitView** _view); + + inline ThisBuilder& Add(BView* view); + inline ThisBuilder& Add(BView* view, float weight); + inline ThisBuilder& Add(BLayoutItem* item); + inline ThisBuilder& Add(BLayoutItem* item, float weight); + + inline GroupBuilder AddGroup(enum orientation orientation, + float spacing = 0.0f, float weight = 1.0f); + inline GridBuilder AddGrid(float horizontalSpacing = 0.0f, + float verticalSpacing = 0.0f, + float weight = 1.0f); + inline SplitBuilder AddSplit(enum orientation orientation, + float spacing = 0.0f, float weight = 1.0f); + + inline ThisBuilder& SetCollapsible(bool collapsible); + inline ThisBuilder& SetCollapsible(int32 index, bool collapsible); + inline ThisBuilder& SetCollapsible(int32 first, int32 last, + bool collapsible); + + inline operator BSplitView*(); + +private: + BSplitView* fView; +}; + + +// #pragma mark - Base + + +template +Base::Base() + : + fParent(NULL) +{ +} + + +template +void +Base::SetParent(ParentBuilder* parent) +{ + fParent = parent; +} + + +template +ParentBuilder& +Base::End() +{ + return *fParent; +} + + +// #pragma mark - Group + + +template +Group::Group(enum orientation orientation, float spacing) + : + fLayout((new BGroupView(orientation, spacing))->GroupLayout()) +{ +} + + +template +Group::Group(BGroupLayout* layout) + : + fLayout(layout) +{ +} + + +template +Group::Group(BGroupView* view) + : + fLayout(view->GroupLayout()) +{ +} + + +template +BGroupLayout* +Group::Layout() const +{ + return fLayout; +} + + +template +BView* +Group::View() const +{ + return fLayout->View(); +} + + +template +typename Group::ThisBuilder& +Group::GetLayout(BGroupLayout** _layout) +{ + *_layout = fLayout; + return *this; +} + + +template +typename Group::ThisBuilder& +Group::GetView(BView** _view) +{ + *_view = fLayout->View(); + return *this; +} + + +template +typename Group::ThisBuilder& +Group::Add(BView* view) +{ + fLayout->AddView(view); + return *this; +} + + +template +typename Group::ThisBuilder& +Group::Add(BView* view, float weight) +{ + fLayout->AddView(view, weight); + return *this; +} + + +template +typename Group::ThisBuilder& +Group::Add(BLayoutItem* item) +{ + fLayout->AddItem(item); + return *this; +} + + +template +typename Group::ThisBuilder& +Group::Add(BLayoutItem* item, float weight) +{ + fLayout->AddItem(item, weight); + return *this; +} + + +template +typename Group::GroupBuilder +Group::AddGroup(enum orientation orientation, float spacing, + float weight) +{ + GroupBuilder builder(orientation, spacing); + builder.SetParent(this); + fLayout->AddView(builder.View(), weight); + return builder; +} + + +template +typename Group::GridBuilder +Group::AddGrid(float horizontalSpacing, float verticalSpacing, + float weight) +{ + GridBuilder builder(horizontalSpacing, verticalSpacing); + builder.SetParent(this); + fLayout->AddView(builder.View(), weight); + return builder; +} + + +template +typename Group::SplitBuilder +Group::AddSplit(enum orientation orientation, float spacing, + float weight) +{ + SplitBuilder builder(orientation, spacing); + builder.SetParent(this); + fLayout->AddView(builder.View(), weight); + return builder; +} + + +template +typename Group::ThisBuilder& +Group::AddGlue(float weight) +{ + fLayout->AddItem(BSpaceLayoutItem::CreateGlue(), weight); + return *this; +} + + +template +typename Group::ThisBuilder& +Group::AddStrut(float size) +{ + if (fLayout->Orientation() == B_HORIZONTAL) + fLayout->AddItem(BSpaceLayoutItem::CreateHorizontalStrut(size)); + else + fLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(size)); + + return *this; +} + + +template +typename Group::ThisBuilder& +Group::SetInsets(float left, float top, float right, + float bottom) +{ + fLayout->SetInsets(left, top, right, bottom); + return *this; +} + + +template +Group::operator BGroupLayout*() +{ + return fLayout; +} + + +template +Group::operator BView*() +{ + return fLayout->View(); +} + + +// #pragma mark - Grid + + +template +Grid::Grid(float horizontalSpacing, float verticalSpacing) + : + fLayout((new BGridView(horizontalSpacing, verticalSpacing))->GridLayout()) +{ +} + + +template +Grid::Grid(BGridLayout* layout) + : + fLayout(layout) +{ +} + + +template +Grid::Grid(BGridView* view) + : + fLayout(view->GridLayout()) +{ +} + + +template +BGridLayout* +Grid::Layout() const +{ + return fLayout; +} + + +template +BView* +Grid::View() const +{ + return fLayout->View(); +} + + +template +typename Grid::ThisBuilder& +Grid::GetLayout(BGridLayout** _layout) +{ + *_layout = fLayout; + return *this; +} + + +template +typename Grid::ThisBuilder& +Grid::GetView(BView** _view) +{ + *_view = fLayout->View(); + return *this; +} + + +template +typename Grid::ThisBuilder& +Grid::Add(BView* view, int32 column, int32 row, + int32 columnCount, int32 rowCount) +{ + fLayout->AddView(view, column, row, columnCount, rowCount); + return *this; +} + + +template +typename Grid::ThisBuilder& +Grid::Add(BLayoutItem* item, int32 column, int32 row, + int32 columnCount, int32 rowCount) +{ + fLayout->AddItem(item, column, row, columnCount, rowCount); + return *this; +} + + +template +typename Grid::GroupBuilder +Grid::AddGroup(enum orientation orientation, float spacing, + int32 column, int32 row, int32 columnCount, int32 rowCount) +{ + GroupBuilder builder(orientation, spacing); + builder.SetParent(this); + fLayout->AddView(builder.View(), 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); + builder.SetParent(this); + fLayout->AddView(builder.View(), column, row, columnCount, rowCount); + return builder; +} + + +template +typename Grid::SplitBuilder +Grid::AddSplit(enum orientation orientation, float spacing, + int32 column, int32 row, int32 columnCount, int32 rowCount) +{ + SplitBuilder builder(orientation, spacing); + builder.SetParent(this); + fLayout->AddView(builder.View(), column, row, columnCount, rowCount); + return builder; +} + + +template +typename Grid::ThisBuilder& +Grid::SetColumnWeight(int32 column, float weight) +{ + fLayout->SetColumnWeight(column, weight); + return *this; +} + + +template +typename Grid::ThisBuilder& +Grid::SetRowWeight(int32 row, float weight) +{ + fLayout->SetRowWeight(row, weight); + return *this; +} + + +template +typename Grid::ThisBuilder& +Grid::SetInsets(float left, float top, float right, + float bottom) +{ + fLayout->SetInsets(left, top, right, bottom); + return *this; +} + + +template +Grid::operator BGridLayout*() +{ + return fLayout; +} + + +template +Grid::operator BView*() +{ + return fLayout->View(); +} + + +// #pragma mark - Split + + +template +Split::Split(enum orientation orientation, float spacing) + : + fView(new BSplitView(orientation, spacing)) +{ +} + + +template +Split::Split(BSplitView* view) + : + fView(view) +{ +} + + +template +BSplitView* +Split::View() const +{ + return fView; +} + + +template +typename Split::ThisBuilder& +Split::GetView(BSplitView** _view) +{ + *_view = fView; + return *this; +} + + +template +typename Split::ThisBuilder& +Split::Add(BView* view) +{ + fView->AddChild(view); + return *this; +} + + +template +typename Split::ThisBuilder& +Split::Add(BView* view, float weight) +{ + fView->AddChild(view, weight); + return *this; +} + + +template +typename Split::ThisBuilder& +Split::Add(BLayoutItem* item) +{ + fView->AddChild(item); + return *this; +} + + +template +typename Split::ThisBuilder& +Split::Add(BLayoutItem* item, float weight) +{ + fView->AddChild(item, weight); + return *this; +} + + +template +typename Split::GroupBuilder +Split::AddGroup(enum orientation orientation, float spacing, + float weight) +{ + GroupBuilder builder(orientation, spacing); + builder.SetParent(this); + fView->AddChild(builder.View(), weight); + return builder; +} + + +template +typename Split::GridBuilder +Split::AddGrid(float horizontalSpacing, float verticalSpacing, + float weight) +{ + GridBuilder builder(horizontalSpacing, verticalSpacing); + builder.SetParent(this); + fView->AddChild(builder.View(), weight); + return builder; +} + + +template +typename Split::SplitBuilder +Split::AddSplit(enum orientation orientation, float spacing, + float weight) +{ + SplitBuilder builder(orientation, spacing); + builder.SetParent(this); + fView->AddChild(builder.View(), weight); + return builder; +} + + +template +typename Split::ThisBuilder& +Split::SetCollapsible(bool collapsible) +{ + fView->SetCollapsible(collapsible); + return *this; +} + + +template +typename Split::ThisBuilder& +Split::SetCollapsible(int32 index, bool collapsible) +{ + fView->SetCollapsible(index, collapsible); + return *this; +} + + +template +typename Split::ThisBuilder& +Split::SetCollapsible(int32 first, int32 last, bool collapsible) +{ + fView->SetCollapsible(first, last, collapsible); + return *this; +} + + +template +Split::operator BSplitView*() +{ + return fView; +} + + +} // namespace BLayoutBuilder + + +#endif // _LAYOUT_BUILDER_H