diff --git a/headers/libs/alm/ALMLayout.h b/headers/libs/alm/ALMLayout.h index 3a7cf821d9..98522b8698 100644 --- a/headers/libs/alm/ALMLayout.h +++ b/headers/libs/alm/ALMLayout.h @@ -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 fLeft; BReference fRight; @@ -231,9 +267,12 @@ private: YTabList fYTabList; bool fYTabsSorted; + BObjectList fConstraints; + RowColumnManager* fRowColumnManager; BadLayoutPolicy* fBadLayoutPolicy; + uint32 _reserved[5]; }; diff --git a/src/libs/alm/ALMLayout.cpp b/src/libs/alm/ALMLayout.cpp index 647ef82b43..a294f0143b 100644 --- a/src/libs/alm/ALMLayout.cpp +++ b/src/libs/alm/ALMLayout.cpp @@ -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 > newXTabs; - std::vector > newYTabs; - int32 existingXTabs = fXTabList.CountItems(); - for (int32 i = 0; i < neededXTabs; i++) { - if (i < existingXTabs) - newXTabs.push_back(BReference(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(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)