diff --git a/headers/libs/alm/ALMLayout.h b/headers/libs/alm/ALMLayout.h index 9a7a920a47..687c1c4fbe 100644 --- a/headers/libs/alm/ALMLayout.h +++ b/headers/libs/alm/ALMLayout.h @@ -102,6 +102,10 @@ public: bool SaveLayout(BMessage* archive) const; bool RestoreLayout(const BMessage* archive); + struct BadLayoutPolicy; + + void SetBadLayoutPolicy(BadLayoutPolicy* policy); + BadLayoutPolicy* GetBadLayoutPolicy() const; virtual BSize BaseMinSize(); virtual BSize BaseMaxSize(); @@ -117,6 +121,18 @@ protected: virtual void LayoutInvalidated(bool children); virtual void DoLayout(); +public: + struct BadLayoutPolicy { + virtual ~BadLayoutPolicy(); + /* return false to abandon layout, true to use layout */ + virtual bool OnBadLayout(BALMLayout* layout) = 0; + }; + + struct DefaultPolicy : public BadLayoutPolicy { + virtual ~DefaultPolicy(); + virtual bool OnBadLayout(BALMLayout* layout); + }; + private: // FBC padding @@ -151,6 +167,8 @@ private: BSize _CalculateMaxSize(); BSize _CalculatePreferredSize(); + bool _TrySolve(); + LinearProgramming::LinearSpec* fSolver; LinearProgramming::LinearSpec fOwnSolver; @@ -175,6 +193,7 @@ private: RowColumnManager* fRowColumnManager; + BadLayoutPolicy* fBadLayoutPolicy; uint32 _reserved[5]; }; diff --git a/src/libs/alm/ALMLayout.cpp b/src/libs/alm/ALMLayout.cpp index 6458956329..9df6df41b0 100644 --- a/src/libs/alm/ALMLayout.cpp +++ b/src/libs/alm/ALMLayout.cpp @@ -24,6 +24,27 @@ using namespace LinearProgramming; const BSize kUnsetSize(B_SIZE_UNSET, B_SIZE_UNSET); +BALM::BALMLayout::BadLayoutPolicy::~BadLayoutPolicy() +{ +} + + +BALM::BALMLayout::DefaultPolicy::~DefaultPolicy() +{ +} + + +bool +BALM::BALMLayout::DefaultPolicy::OnBadLayout(BALMLayout* layout) +{ + if (layout->Solver()->Result() == kInfeasible) { + debugger("BALMLayout failed to solve your layout!"); + return false; + } else + return true; +} + + /*! * Constructor. * Creates new layout engine. @@ -37,7 +58,8 @@ BALMLayout::BALMLayout(float hSpacing, float vSpacing, BALMLayout* friendLayout) fTopInset(0), fBottomInset(0), fHSpacing(BControlLook::ComposeSpacing(hSpacing)), - fVSpacing(BControlLook::ComposeSpacing(vSpacing)) + fVSpacing(BControlLook::ComposeSpacing(vSpacing)), + fBadLayoutPolicy(new DefaultPolicy()) { fSolver = friendLayout ? friendLayout->Solver() : &fOwnSolver; fRowColumnManager = new RowColumnManager(fSolver); @@ -63,6 +85,7 @@ BALMLayout::BALMLayout(float hSpacing, float vSpacing, BALMLayout* friendLayout) BALMLayout::~BALMLayout() { delete fRowColumnManager; + delete fBadLayoutPolicy; } @@ -661,11 +684,30 @@ BALMLayout::Bottom() const } +void +BALMLayout::SetBadLayoutPolicy(BadLayoutPolicy* policy) +{ + if (fBadLayoutPolicy != policy) + delete fBadLayoutPolicy; + if (policy == NULL) + policy = new DefaultPolicy(); + fBadLayoutPolicy = policy; +} + + +struct BALMLayout::BadLayoutPolicy* +BALMLayout::GetBadLayoutPolicy() const +{ + return fBadLayoutPolicy; +} + + /** * Gets minimum size. */ BSize -BALMLayout::BaseMinSize() { +BALMLayout::BaseMinSize() +{ if (fMinSize == kUnsetSize) fMinSize = _CalculateMinSize(); return fMinSize; @@ -755,18 +797,7 @@ BALMLayout::DoLayout() Right()->SetRange(area.right, area.right); Bottom()->SetRange(area.bottom, area.bottom); - fSolver->Solve(); - - // if new layout is infeasible, use previous layout - if (fSolver->Result() == kInfeasible) - return; - - if (fSolver->Result() != kOptimal) { - fSolver->Save("failed-layout.txt"); - printf("Could not solve the layout specification (%d). ", - fSolver->Result()); - printf("Saved specification in file failed-layout.txt\n"); - } + _TrySolve(); // set the calculated positions and sizes for every area for (int32 i = 0; i < CountItems(); i++) @@ -894,7 +925,11 @@ BALMLayout::_CalculateMinSize() Right()->SetRange(0, 20000); Bottom()->SetRange(0, 20000); - return fSolver->MinSize(Right(), Bottom()); + BSize min(fSolver->MinSize(Right(), Bottom())); + ResultType result = fSolver->Result(); + if (result != kUnbounded && result != kOptimal) + fBadLayoutPolicy->OnBadLayout(this); + return min; } @@ -909,7 +944,11 @@ BALMLayout::_CalculateMaxSize() Right()->SetRange(0, 20000); Bottom()->SetRange(0, 20000); - return fSolver->MaxSize(Right(), Bottom()); + BSize max(fSolver->MaxSize(Right(), Bottom())); + ResultType result = fSolver->Result(); + if (result != kUnbounded && result != kOptimal) + fBadLayoutPolicy->OnBadLayout(this); + return max; } @@ -924,18 +963,25 @@ BALMLayout::_CalculatePreferredSize() Right()->SetRange(0, 20000); Bottom()->SetRange(0, 20000); - fSolver->Solve(); - if (fSolver->Result() != kOptimal) { - fSolver->Save("failed-layout.txt"); - printf("Could not solve the layout specification (%d). " - "Saved specification in file failed-layout.txt", fSolver->Result()); - } + _TrySolve(); return BSize(Right()->Value() - Left()->Value(), Bottom()->Value() - Top()->Value()); } +bool +BALMLayout::_TrySolve() +{ + fSolver->Solve(); + + if (fSolver->Result() != kOptimal) { + return fBadLayoutPolicy->OnBadLayout(this); + } + return true; +} + + void BALMLayout::_UpdateAreaConstraints() {