Let BALM::{X|Y}Tabs be in multiple BALMLayouts, if they are friendly.

This commit is contained in:
Alex Wilson
2012-05-03 08:44:55 +12:00
parent f9cabdd009
commit c761a8a6d4
4 changed files with 264 additions and 9 deletions
+14
View File
@@ -151,6 +151,17 @@ private:
BALMLayout(const BALMLayout&);
void operator =(const BALMLayout&);
struct XTabRemover;
struct XTabRemoverFunc;
struct YTabRemover;
struct YTabRemoverFunc;
friend struct XTabRemover;
friend struct XTabRemoverFunc;
friend struct YTabRemover;
friend struct YTabRemoverFunc;
friend class XTab;
friend class YTab;
@@ -159,6 +170,9 @@ private:
float InsetForTab(XTab* tab) const;
float InsetForTab(YTab* tab) const;
void _RemoveSelfFromTab(XTab* tab);
void _RemoveSelfFromTab(YTab* tab);
BLayoutItem* _LayoutItemToAdd(BView* view);
void _UpdateAreaConstraints();
+14 -2
View File
@@ -29,7 +29,14 @@ protected:
XTab(BALMLayout* layout);
private:
BALMLayout* fALMLayout;
struct BALMLayoutList;
bool IsInLayout(BALMLayout* layout);
bool AddedToLayout(BALMLayout* layout);
void LayoutLeaving(BALMLayout* layout);
bool IsSuitableFor(BALMLayout* layout);
BALMLayoutList* fLayouts;
uint32 _reserved[2];
};
@@ -44,7 +51,12 @@ protected:
YTab(BALMLayout* layout);
private:
BALMLayout* fALMLayout;
bool IsInLayout(BALMLayout* layout);
bool AddedToLayout(BALMLayout* layout);
void LayoutLeaving(BALMLayout* layout);
bool IsSuitableFor(BALMLayout* layout);
XTab::BALMLayoutList* fLayouts;
uint32 _reserved[2];
};
+117 -3
View File
@@ -11,18 +11,70 @@
#include <vector>
#include <AutoDeleter.h>
#include <ControlLook.h>
#include "RowColumnManager.h"
#include "ViewLayoutItem.h"
using BPrivate::AutoDeleter;
using namespace LinearProgramming;
const BSize kUnsetSize(B_SIZE_UNSET, B_SIZE_UNSET);
struct BALMLayout::XTabRemoverFunc {
void operator()(XTab* tab)
{
if (tab)
layout->_RemoveSelfFromTab(tab);
}
BALMLayout* layout;
};
struct BALMLayout::XTabRemover
: public AutoDeleter<XTab, BALMLayout::XTabRemoverFunc> {
typedef AutoDeleter<XTab, BALMLayout::XTabRemoverFunc> Base;
XTabRemover(BALMLayout* layout, XTab* tab = NULL)
:
Base(tab)
{
fDelete.layout = layout;
}
};
struct BALMLayout::YTabRemoverFunc {
void operator()(YTab* tab)
{
if (tab)
layout->_RemoveSelfFromTab(tab);
}
BALMLayout* layout;
};
struct BALMLayout::YTabRemover
: public AutoDeleter<YTab, BALMLayout::YTabRemoverFunc> {
typedef AutoDeleter<YTab, BALMLayout::YTabRemoverFunc> Base;
YTabRemover(BALMLayout* layout, YTab* tab = NULL)
:
Base(tab)
{
fDelete.layout = layout;
}
};
BALM::BALMLayout::BadLayoutPolicy::~BadLayoutPolicy()
{
}
@@ -105,6 +157,10 @@ BALMLayout::AddXTab()
return NULL;
fXTabList.AddItem(tab);
if (!tab->AddedToLayout(this)) {
fXTabList.RemoveItem(tab);
return NULL;
}
return tab;
}
@@ -140,6 +196,10 @@ BALMLayout::AddYTab()
return NULL;
fYTabList.AddItem(tab);
if (!tab->AddedToLayout(this)) {
fYTabList.RemoveItem(tab);
return NULL;
}
return tab;
}
@@ -480,6 +540,11 @@ Area*
BALMLayout::AddItem(BLayoutItem* item, XTab* left, YTab* top, XTab* _right,
YTab* _bottom)
{
if (!left->IsSuitableFor(this) || !top->IsSuitableFor(this)
|| (_right && !_right->IsSuitableFor(this))
|| (_bottom && !_bottom->IsSuitableFor(this)))
debugger("Tab added to unfriendly layout!");
BReference<XTab> right = _right;
if (right.Get() == NULL)
right = AddXTab();
@@ -487,16 +552,51 @@ BALMLayout::AddItem(BLayoutItem* item, XTab* left, YTab* top, XTab* _right,
if (bottom.Get() == NULL)
bottom = AddYTab();
// Area is added int ItemAdded
// TODO: make sure all tabs get into the lists
XTabRemover leftRemover(this);
if (!left->IsInLayout(this)) {
if (!left->AddedToLayout(this))
return NULL;
leftRemover.SetTo(left);
}
YTabRemover topRemover(this);
if (!top->IsInLayout(this)) {
if (!top->AddedToLayout(this))
return NULL;
topRemover.SetTo(top);
}
XTabRemover rightRemover(this);
if (_right != NULL && !right->IsInLayout(this)) {
if (!right->AddedToLayout(this))
return NULL;
rightRemover.SetTo(right);
}
YTabRemover bottomRemover(this);
if (_bottom != NULL && !bottom->IsInLayout(this)) {
if (!bottom->AddedToLayout(this))
return NULL;
bottomRemover.SetTo(bottom);
}
// Area is added in ItemAdded
if (!BAbstractLayout::AddItem(-1, item))
return NULL;
Area* area = AreaFor(item);
if (!area)
if (!area) {
RemoveItem(item);
return NULL;
}
area->_Init(fSolver, left, top, right, bottom, fRowColumnManager);
fRowColumnManager->AddArea(area);
leftRemover.Detach();
rightRemover.Detach();
topRemover.Detach();
bottomRemover.Detach();
return area;
}
@@ -907,6 +1007,20 @@ BALMLayout::InsetForTab(YTab* tab) const
}
void
BALMLayout::_RemoveSelfFromTab(XTab* tab)
{
tab->LayoutLeaving(this);
}
void
BALMLayout::_RemoveSelfFromTab(YTab* tab)
{
tab->LayoutLeaving(this);
}
BLayoutItem*
BALMLayout::_LayoutItemToAdd(BView* view)
{
+119 -4
View File
@@ -10,29 +10,144 @@
#include <ALMLayout.h>
using std::nothrow;
struct XTab::BALMLayoutList {
BALMLayoutList(BALMLayout* _layout, BALMLayoutList* _next = NULL)
:
next(_next),
layout(_layout)
{
}
~BALMLayoutList()
{
delete next;
}
bool HasLayout(BALMLayout* search)
{
if (layout == search)
return true;
return next ? next->HasLayout(search) : false;
}
BALMLayoutList* Remove(BALMLayout* remove)
{
if (layout == remove) {
BALMLayoutList* _next = next;
delete this;
return _next;
}
if (next)
next = next->Remove(remove);
return this;
}
BALMLayoutList* next;
BALMLayout* layout;
};
XTab::XTab(BALMLayout* layout)
:
Variable(layout->Solver()),
fALMLayout(layout)
fLayouts(new BALMLayoutList(layout))
{
}
XTab::~XTab()
{
fALMLayout->fXTabList.RemoveItem(this);
BALMLayoutList* layouts = fLayouts;
while (layouts) {
layouts->layout->fXTabList.RemoveItem(this);
layouts = layouts->next;
}
delete fLayouts;
}
bool
XTab::IsInLayout(BALMLayout* layout)
{
return fLayouts->HasLayout(layout);
}
bool
XTab::AddedToLayout(BALMLayout* layout)
{
BALMLayoutList* newHead = new (nothrow) BALMLayoutList(layout, fLayouts);
if (newHead == NULL)
return false;
fLayouts = newHead;
return true;
}
void
XTab::LayoutLeaving(BALMLayout* layout)
{
fLayouts = fLayouts->Remove(layout);
}
bool
XTab::IsSuitableFor(BALMLayout* layout)
{
return (fLayouts->layout->Solver() == layout->Solver());
}
YTab::YTab(BALMLayout* layout)
:
Variable(layout->Solver()),
fALMLayout(layout)
fLayouts(new XTab::BALMLayoutList(layout))
{
}
YTab::~YTab()
{
fALMLayout->fYTabList.RemoveItem(this);
XTab::BALMLayoutList* layouts = fLayouts;
while (layouts) {
layouts->layout->fYTabList.RemoveItem(this);
layouts = layouts->next;
}
delete fLayouts;
}
bool
YTab::IsInLayout(BALMLayout* layout)
{
return fLayouts->HasLayout(layout);
}
bool
YTab::AddedToLayout(BALMLayout* layout)
{
XTab::BALMLayoutList* newHead
= new (nothrow) XTab::BALMLayoutList(layout, fLayouts);
if (newHead == NULL)
return false;
fLayouts = newHead;
return true;
}
void
YTab::LayoutLeaving(BALMLayout* layout)
{
fLayouts = fLayouts->Remove(layout);
}
bool
YTab::IsSuitableFor(BALMLayout* layout)
{
return (fLayouts->layout->Solver() == layout->Solver());
}