From 37344020ef592f58c61b7de8cd2c83dd31203aca Mon Sep 17 00:00:00 2001 From: Clemens Zeidler Date: Sun, 3 Oct 2010 20:05:52 +0000 Subject: [PATCH] - Add a alternative method to setup a group layout. BLayoutItem / BView are wrapped into a GroupItem. GroupItem overloads the | (horizontal tiling) and / (vertical tiling) operators. In this manner you can create a group layout using these operators, e.g. GroupItem item = GroupItem(button1) | (GroupItem(button2) / GroupItem(button3)); would layout button1 at the left and button2 and button3 at the right in a vertical layout. All the layout information is stored in the GroupItem item, to setup the final layout you have to call BuildLayout(item). If you like it it could also be added to the BGroupLayout. - Add operator test app. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38877 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/libs/alm/ALMLayout.h | 6 ++ headers/libs/alm/Area.h | 32 ++++++++++ src/libs/alm/ALMLayout.cpp | 47 +++++++++++++++ src/libs/alm/Area.cpp | 87 +++++++++++++++++++++++++++ src/libs/alm/Jamfile | 2 +- src/tests/libs/alm/Jamfile | 5 ++ src/tests/libs/alm/OperatorLayout.cpp | 66 ++++++++++++++++++++ src/tests/libs/alm/Views.cpp | 2 +- 8 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 src/tests/libs/alm/OperatorLayout.cpp diff --git a/headers/libs/alm/ALMLayout.h b/headers/libs/alm/ALMLayout.h index 9447e1cfc5..8cb1aec4a9 100644 --- a/headers/libs/alm/ALMLayout.h +++ b/headers/libs/alm/ALMLayout.h @@ -69,6 +69,10 @@ public: YTab* BottomOf(const BView* view) const; YTab* BottomOf(const BLayoutItem* item) const; + void BuildLayout(GroupItem& item, XTab* left = NULL, + YTab* top = NULL, XTab* right = NULL, + YTab* bottom = NULL); + virtual BLayoutItem* AddView(BView* child); virtual BLayoutItem* AddView(int32 index, BView* child); virtual Area* AddView(BView* view, XTab* left, YTab* top, @@ -127,6 +131,8 @@ private: BSize _CalculateMaxSize(); BSize _CalculatePreferredSize(); + void _ParseGroupItem(GroupItem& item, XTab* left, + YTab* top, XTab* right, YTab* bottom); LinearSpec fSolver; diff --git a/headers/libs/alm/Area.h b/headers/libs/alm/Area.h index 8c431ef91a..c9b1cabc6e 100644 --- a/headers/libs/alm/Area.h +++ b/headers/libs/alm/Area.h @@ -6,6 +6,8 @@ #define AREA_H +#include + #include #include #include @@ -24,6 +26,35 @@ class Constraint; namespace BALM { +class GroupItem { +public: + GroupItem(BLayoutItem* item); + GroupItem(BView* view); + + BLayoutItem* LayoutItem(); + BView* View(); + + const std::vector& GroupItems(); + enum orientation Orientation(); + + GroupItem& operator|(const GroupItem& right); + GroupItem& operator/(const GroupItem& bottom); +private: + GroupItem(); + + void _Init(BLayoutItem* item, BView* view, + enum orientation orien = B_HORIZONTAL); + GroupItem& _AddItem(const GroupItem& item, + enum orientation orien); + + BLayoutItem* fLayoutItem; + BView* fView; + + std::vector fGroupItems; + enum orientation fOrientation; +}; + + /** * Rectangular area in the GUI, defined by a tab on each side. */ @@ -122,6 +153,7 @@ public: } // namespace BALM using BALM::Area; +using BALM::GroupItem; #endif // AREA_H diff --git a/src/libs/alm/ALMLayout.cpp b/src/libs/alm/ALMLayout.cpp index 302869b395..10a996cd83 100644 --- a/src/libs/alm/ALMLayout.cpp +++ b/src/libs/alm/ALMLayout.cpp @@ -248,6 +248,53 @@ BALMLayout::BottomOf(const BLayoutItem* item) const } +void +BALMLayout::BuildLayout(GroupItem& item, XTab* left, YTab* top, XTab* right, + YTab* bottom) +{ + if (!left) + left = Left(); + if (!top) + top = Top(); + if (!right) + right = Right(); + if (!bottom) + bottom = Bottom(); + + _ParseGroupItem(item, left, top, right, bottom); +} + + +void +BALMLayout::_ParseGroupItem(GroupItem& item, XTab* left, YTab* top, XTab* right, + YTab* bottom) +{ + if (item.LayoutItem()) + AddItem(item.LayoutItem(), left, top, right, bottom); + else if (item.View()) { + AddView(item.View(), left, top, right, bottom); + } + else { + for (unsigned int i = 0; i < item.GroupItems().size(); i++) { + GroupItem& current = const_cast( + item.GroupItems().at(i)); + if (item.Orientation() == B_HORIZONTAL) { + XTab* r = (i == item.GroupItems().size() - 1) ? right + : AddXTab(); + _ParseGroupItem(current, left, top, r, bottom); + left = r; + } + else { + YTab* b = (i == item.GroupItems().size() - 1) ? bottom + : AddYTab(); + _ParseGroupItem(current, left, top, right, b); + top = b; + } + } + } +} + + BLayoutItem* BALMLayout::AddView(BView* child) { diff --git a/src/libs/alm/Area.cpp b/src/libs/alm/Area.cpp index e0b68aaf2e..22778bcba3 100644 --- a/src/libs/alm/Area.cpp +++ b/src/libs/alm/Area.cpp @@ -22,6 +22,93 @@ using namespace std; +GroupItem::GroupItem(BLayoutItem* item) +{ + _Init(item, NULL); +} + + +GroupItem::GroupItem(BView* view) +{ + _Init(NULL, view); +} + + +BLayoutItem* +GroupItem::LayoutItem() +{ + return fLayoutItem; +} + + +BView* +GroupItem::View() +{ + return fView; +} + + +const std::vector& +GroupItem::GroupItems() +{ + return fGroupItems; +} + + +enum orientation +GroupItem::Orientation() +{ + return fOrientation; +} + + +GroupItem& +GroupItem::operator|(const GroupItem& right) +{ + return _AddItem(right, B_HORIZONTAL); +} + + +GroupItem& +GroupItem::operator/(const GroupItem& bottom) +{ + return _AddItem(bottom, B_VERTICAL); +} + + +GroupItem::GroupItem() +{ + _Init(NULL, NULL); +} + + +void +GroupItem::_Init(BLayoutItem* item, BView* view, enum orientation orien) +{ + fLayoutItem = item; + fView = view; + fOrientation = orien; +} + + +GroupItem& +GroupItem::_AddItem(const GroupItem& item, enum orientation orien) +{ + if (fGroupItems.size() == 0) + fGroupItems.push_back(*this); + else if (fOrientation != orien) { + GroupItem clone = *this; + fGroupItems.clear(); + _Init(NULL, NULL, orien); + fGroupItems.push_back(clone); + } + + _Init(NULL, NULL, orien); + fGroupItems.push_back(item); + return *this; +} + + BView* Area::View() { diff --git a/src/libs/alm/Jamfile b/src/libs/alm/Jamfile index f1d4d0334a..cd17f88565 100644 --- a/src/libs/alm/Jamfile +++ b/src/libs/alm/Jamfile @@ -13,5 +13,5 @@ SharedLibrary libalm.so : ALMLayout.cpp Row.cpp : - be liblpsolve55.so liblinprog.so $(TARGET_LIBSUPC++) + be liblpsolve55.so liblinprog.so $(TARGET_LIBSTDC++) ; diff --git a/src/tests/libs/alm/Jamfile b/src/tests/libs/alm/Jamfile index 77ca180dec..2a1d71ed96 100644 --- a/src/tests/libs/alm/Jamfile +++ b/src/tests/libs/alm/Jamfile @@ -36,3 +36,8 @@ Application ALMTableDemo : be liblpsolve55.so be liblinprog.so libalm.so $(TARGET_LIBSUPC++) ; +Application ALMOperator : + OperatorLayout.cpp + : + be liblpsolve55.so be liblinprog.so libalm.so $(TARGET_LIBSTDC++) +; diff --git a/src/tests/libs/alm/OperatorLayout.cpp b/src/tests/libs/alm/OperatorLayout.cpp new file mode 100644 index 0000000000..c6783fca05 --- /dev/null +++ b/src/tests/libs/alm/OperatorLayout.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2010, Clemens Zeidler + * Distributed under the terms of the MIT License. + */ + + +#include +#include +#include +#include +#include + +#include "ALMLayout.h" + + +class OperatorWindow : public BWindow { +public: + OperatorWindow(BRect frame) + : + BWindow(frame, "ALM Operator", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) + { + BButton* button1 = new BButton("1"); + BButton* button2 = new BButton("2"); + BButton* button3 = new BButton("3"); + BButton* button4 = new BButton("4"); + BButton* button5 = new BButton("5"); + + button1->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + button2->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + button3->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + button4->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + button5->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + + // create a new BALMLayout and use it for this window + float spacing = be_control_look->DefaultItemSpacing(); + BALMLayout* layout = new BALMLayout(spacing); + SetLayout(layout); + layout->SetInset(spacing); + + GroupItem item = GroupItem(button1) | (GroupItem(button2) + / (GroupItem(button3) | GroupItem(BSpaceLayoutItem::CreateGlue()) + | GroupItem(button4)) + / GroupItem(button5)); + layout->BuildLayout(item); + + // test size limits + BSize min = layout->MinSize(); + BSize max = layout->MaxSize(); + SetSizeLimits(min.Width(), max.Width(), min.Height(), max.Height()); + } + +}; + + +int +main() +{ + BApplication app("application/x-vnd.haiku.ALMOperator"); + + OperatorWindow* window = new OperatorWindow(BRect(100, 100, 300, 300)); + window->Show(); + + app.Run(); + return 0; +} + diff --git a/src/tests/libs/alm/Views.cpp b/src/tests/libs/alm/Views.cpp index 29da0b1d62..1b69f86f54 100644 --- a/src/tests/libs/alm/Views.cpp +++ b/src/tests/libs/alm/Views.cpp @@ -24,7 +24,7 @@ class ViewsWindow : public BWindow { public: ViewsWindow(BRect frame) : - BWindow(frame, "ALM Two Views", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) + BWindow(frame, "ALM Views", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) { BButton* button1 = new BButton("BButton"); BRadioButton* radioButton = new BRadioButton("BRadioButton", NULL);