Add a list of constraints which can be associated with a BALMLayout.

- Add Get{X,Y}Tabs methods.
- Remove SaveLayout and RestoreLayout. These can be implemented outside of BALMLayout.
This commit is contained in:
czeidler 2012-09-01 15:36:59 +12:00 committed by Ryan Leavengood
parent 57c3ae1096
commit 96ca65c7b2
2 changed files with 179 additions and 131 deletions

View File

@ -16,6 +16,8 @@
class BView;
class BLayoutItem;
class Constraint;
namespace BPrivate {
class SharedSolver;
@ -53,10 +55,41 @@ public:
XTab* XTabAt(int32 index) const;
YTab* YTabAt(int32 index, bool ordered = false);
YTab* YTabAt(int32 index) const;
const XTabList GetXTabs() const;
const YTabList GetYTabs() const;
int32 IndexOf(XTab* tab, bool ordered = false);
int32 IndexOf(YTab* tab, bool ordered = false);
int32 CountConstraints() const;
Constraint* ConstraintAt(int32 index) const;
bool AddConstraint(Constraint* constraint);
bool RemoveConstraint(Constraint* constraint,
bool deleteConstraint = true);
Constraint* AddConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide,
double penaltyNeg = -1,
double penaltyPos = -1);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
OperatorType op, double rightSide,
double penaltyNeg = -1,
double penaltyPos = -1);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
OperatorType op, double rightSide,
double penaltyNeg = -1,
double penaltyPos = -1);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
double coeff4, Variable* var4,
OperatorType op, double rightSide,
double penaltyNeg = -1,
double penaltyPos = -1);
Row* AddRow(YTab* top, YTab* bottom);
Column* AddColumn(XTab* left, XTab* right);
@ -66,6 +99,7 @@ public:
YTab* Bottom() const;
LinearProgramming::LinearSpec* Solver() const;
LinearProgramming::ResultType ValidateLayout();
void SetInsets(float insets);
void SetInsets(float x, float y);
@ -106,9 +140,7 @@ public:
YTab* bottom = NULL);
virtual Area* AddItem(BLayoutItem* item, Row* row,
Column* column);
bool SaveLayout(BMessage* archive) const;
bool RestoreLayout(const BMessage* archive);
struct BadLayoutPolicy;
void SetBadLayoutPolicy(BadLayoutPolicy* policy);
@ -192,6 +224,9 @@ private:
friend class YTab;
friend class Area;
class BALMLayoutSpecListener;
friend class BALMLayoutSpecListener;
float InsetForTab(XTab* tab) const;
float InsetForTab(YTab* tab) const;
@ -208,6 +243,7 @@ private:
void _SetSolver(BPrivate::SharedSolver* solver);
BPrivate::SharedSolver* fSolver;
BALMLayoutSpecListener* fSpecListener;
BReference<XTab> fLeft;
BReference<XTab> fRight;
@ -231,9 +267,12 @@ private:
YTabList fYTabList;
bool fYTabsSorted;
BObjectList<Constraint> fConstraints;
RowColumnManager* fRowColumnManager;
BadLayoutPolicy* fBadLayoutPolicy;
uint32 _reserved[5];
};

View File

@ -184,6 +184,25 @@ BALM::BALMLayout::DefaultPolicy::Instantiate(BMessage* archive)
}
class BALMLayout::BALMLayoutSpecListener
: public LinearProgramming::SpecificationListener {
public:
BALMLayoutSpecListener(BALMLayout* layout)
:
fLayout(layout)
{
}
void ConstraintRemoved(Constraint* constraint)
{
fLayout->fConstraints.RemoveItem(constraint);
}
private:
BALMLayout* fLayout;
};
/*!
* Constructor.
* Creates new layout engine.
@ -204,6 +223,9 @@ BALMLayout::BALMLayout(float hSpacing, float vSpacing, BALMLayout* friendLayout)
{
_SetSolver(friendLayout ? friendLayout->fSolver : new SharedSolver());
fSpecListener = new BALMLayoutSpecListener(this);
Solver()->AddListener(fSpecListener);
fLeft = AddXTab();
fRight = AddXTab();
fTop = AddYTab();
@ -278,14 +300,23 @@ BALMLayout::BALMLayout(BMessage* archive)
err = unarchiver.EnsureUnarchived(kSolverField);
unarchiver.Finish(err);
fSpecListener = new BALMLayoutSpecListener(this);
Solver()->AddListener(fSpecListener);
}
BALMLayout::~BALMLayout()
{
Solver()->RemoveListener(fSpecListener);
delete fSpecListener;
delete fRowColumnManager;
delete fBadLayoutPolicy;
for (int32 i = 0; i < fConstraints.CountItems(); i++)
Solver()->RemoveConstraint(fConstraints.ItemAt(i), true);
if (fSolver) {
fSolver->LayoutLeaving(this);
fSolver->ReleaseReference();
@ -409,6 +440,20 @@ BALMLayout::YTabAt(int32 index) const
}
const XTabList
BALMLayout::GetXTabs() const
{
return fXTabList;
}
const YTabList
BALMLayout::GetYTabs() const
{
return fYTabList;
}
int32
BALMLayout::IndexOf(XTab* tab, bool ordered)
{
@ -433,6 +478,85 @@ BALMLayout::IndexOf(YTab* tab, bool ordered)
}
int32
BALMLayout::CountConstraints() const
{
return fConstraints.CountItems();
}
Constraint*
BALMLayout::ConstraintAt(int32 index) const
{
return fConstraints.ItemAt(index);
}
bool
BALMLayout::AddConstraint(Constraint* constraint)
{
fConstraints.AddItem(constraint);
return Solver()->AddConstraint(constraint);
}
bool
BALMLayout::RemoveConstraint(Constraint* constraint,
bool deleteConstraint)
{
if (!fConstraints.RemoveItem(constraint))
return false;
return Solver()->RemoveConstraint(constraint, deleteConstraint);
}
Constraint*
BALMLayout::AddConstraint(double coeff1, Variable* var1, OperatorType op,
double rightSide, double penaltyNeg, double penaltyPos)
{
Constraint* constraint = Solver()->AddConstraint(coeff1, var1, op,
rightSide, penaltyNeg, penaltyPos);
fConstraints.AddItem(constraint);
return constraint;
}
Constraint*
BALMLayout::AddConstraint(double coeff1, Variable* var1, double coeff2,
Variable* var2, OperatorType op, double rightSide, double penaltyNeg,
double penaltyPos)
{
Constraint* constraint = Solver()->AddConstraint(coeff1, var1, coeff2, var2,
op, rightSide, penaltyNeg, penaltyPos);
fConstraints.AddItem(constraint);
return constraint;
}
Constraint*
BALMLayout::AddConstraint(double coeff1, Variable* var1, double coeff2,
Variable* var2, double coeff3, Variable* var3, OperatorType op,
double rightSide, double penaltyNeg, double penaltyPos)
{
Constraint* constraint = Solver()->AddConstraint(coeff1, var1, coeff2, var2,
coeff3, var3, op, rightSide, penaltyNeg, penaltyPos);
fConstraints.AddItem(constraint);
return constraint;
}
Constraint*
BALMLayout::AddConstraint(double coeff1, Variable* var1, double coeff2,
Variable* var2, double coeff3, Variable* var3, double coeff4,
Variable* var4, OperatorType op, double rightSide, double penaltyNeg,
double penaltyPos)
{
Constraint* constraint = Solver()->AddConstraint(coeff1, var1, coeff2, var2,
coeff3, var3, coeff4, var4, op, rightSide, penaltyNeg, penaltyPos);
fConstraints.AddItem(constraint);
return constraint;
}
namespace {
@ -775,6 +899,7 @@ BALMLayout::AddItem(BLayoutItem* item, XTab* _left, YTab* _top, XTab* _right,
return NULL;
}
fSolver->Invalidate(true);
area->_Init(Solver(), left, top, right, bottom, fRowColumnManager);
fRowColumnManager->AddArea(area);
@ -795,6 +920,7 @@ BALMLayout::AddItem(BLayoutItem* item, Row* row, Column* column)
if (!area)
return NULL;
fSolver->Invalidate(true);
area->_Init(Solver(), row, column, fRowColumnManager);
fRowColumnManager->AddArea(area);
@ -802,134 +928,6 @@ BALMLayout::AddItem(BLayoutItem* item, Row* row, Column* column)
}
enum {
kLeftBorderIndex = -2,
kTopBorderIndex = -3,
kRightBorderIndex = -4,
kBottomBorderIndex = -5,
};
bool
BALMLayout::SaveLayout(BMessage* archive) const
{
archive->MakeEmpty();
archive->AddInt32("nXTabs", CountXTabs());
archive->AddInt32("nYTabs", CountYTabs());
XTabList xTabs = fXTabList;
xTabs.RemoveItem(fLeft);
xTabs.RemoveItem(fRight);
YTabList yTabs = fYTabList;
yTabs.RemoveItem(fTop);
yTabs.RemoveItem(fBottom);
int32 nAreas = CountAreas();
for (int32 i = 0; i < nAreas; i++) {
Area* area = AreaAt(i);
if (area->Left() == fLeft)
archive->AddInt32("left", kLeftBorderIndex);
else
archive->AddInt32("left", xTabs.IndexOf(area->Left()));
if (area->Top() == fTop)
archive->AddInt32("top", kTopBorderIndex);
else
archive->AddInt32("top", yTabs.IndexOf(area->Top()));
if (area->Right() == fRight)
archive->AddInt32("right", kRightBorderIndex);
else
archive->AddInt32("right", xTabs.IndexOf(area->Right()));
if (area->Bottom() == fBottom)
archive->AddInt32("bottom", kBottomBorderIndex);
else
archive->AddInt32("bottom", yTabs.IndexOf(area->Bottom()));
}
return true;
}
bool
BALMLayout::RestoreLayout(const BMessage* archive)
{
int32 neededXTabs;
int32 neededYTabs;
if (archive->FindInt32("nXTabs", &neededXTabs) != B_OK)
return false;
if (archive->FindInt32("nYTabs", &neededYTabs) != B_OK)
return false;
// First store a reference to all needed tabs otherwise they might get lost
// while editing the layout
std::vector<BReference<XTab> > newXTabs;
std::vector<BReference<YTab> > newYTabs;
int32 existingXTabs = fXTabList.CountItems();
for (int32 i = 0; i < neededXTabs; i++) {
if (i < existingXTabs)
newXTabs.push_back(BReference<XTab>(fXTabList.ItemAt(i)));
else
newXTabs.push_back(AddXTab());
}
int32 existingYTabs = fYTabList.CountItems();
for (int32 i = 0; i < neededYTabs; i++) {
if (i < existingYTabs)
newYTabs.push_back(BReference<YTab>(fYTabList.ItemAt(i)));
else
newYTabs.push_back(AddYTab());
}
XTabList xTabs = fXTabList;
xTabs.RemoveItem(fLeft);
xTabs.RemoveItem(fRight);
YTabList yTabs = fYTabList;
yTabs.RemoveItem(fTop);
yTabs.RemoveItem(fBottom);
int32 nAreas = CountAreas();
for (int32 i = 0; i < nAreas; i++) {
Area* area = AreaAt(i);
if (area == NULL)
return false;
int32 left = -1;
if (archive->FindInt32("left", i, &left) != B_OK)
break;
int32 top = archive->FindInt32("top", i);
int32 right = archive->FindInt32("right", i);
int32 bottom = archive->FindInt32("bottom", i);
XTab* leftTab = NULL;
YTab* topTab = NULL;
XTab* rightTab = NULL;
YTab* bottomTab = NULL;
if (left == kLeftBorderIndex)
leftTab = fLeft;
else
leftTab = xTabs.ItemAt(left);
if (top == kTopBorderIndex)
topTab = fTop;
else
topTab = yTabs.ItemAt(top);
if (right == kRightBorderIndex)
rightTab = fRight;
else
rightTab = xTabs.ItemAt(right);
if (bottom == kBottomBorderIndex)
bottomTab = fBottom;
else
bottomTab = yTabs.ItemAt(bottom);
if (leftTab == NULL || topTab == NULL || rightTab == NULL
|| bottomTab == NULL)
return false;
area->SetLeft(leftTab);
area->SetTop(topTab);
area->SetRight(rightTab);
area->SetBottom(bottomTab);
}
return true;
}
/**
* Gets the left variable.
*/
@ -1337,6 +1335,17 @@ BALMLayout::Solver() const
}
ResultType
BALMLayout::ValidateLayout()
{
// we explicitly recaluclate the layout so set the invalidate flag first
fSolver->Invalidate(true);
BLayoutContext* context = LayoutContext();
return fSolver->ValidateLayout(context);
}
void
BALMLayout::SetInsets(float left, float top, float right,
float bottom)