From c8b24e3eb51bac128f5eeb0a5a22a60b69a1a53e Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Mon, 30 Apr 2012 14:07:06 +1200 Subject: [PATCH] Fix BALMLayout archiving issues. SharedSolver was archiving too many constraints, partly because of multiple typos, also because it archived some which were just artifacts of the layout process. These extra constraints are created when the layout calls SetRange() on the left/top/right/bottom tabs during layout. * LinearSpec/ActiveSetSolver had to be adjusted to get access to the constraints added by the SetRange() calls. * BALM::TabBase was adjusted to avoid a segfault during unarchiving, caused by an unitialized member. * ALMFriendLayoutTest was adjusted to include a more obvious custom constraint for testing. --- headers/libs/linprog/LinearSpec.h | 7 ++++ src/libs/alm/SharedSolver.cpp | 60 +++++++++++++++++++++++----- src/libs/alm/SharedSolver.h | 2 +- src/libs/alm/Tab.cpp | 3 +- src/libs/linprog/ActiveSetSolver.cpp | 13 ++++++ src/libs/linprog/ActiveSetSolver.h | 3 ++ src/libs/linprog/LinearSpec.cpp | 12 ++++++ src/tests/libs/alm/FriendLayout.cpp | 4 +- 8 files changed, 90 insertions(+), 14 deletions(-) diff --git a/headers/libs/linprog/LinearSpec.h b/headers/libs/linprog/LinearSpec.h index b6e0fac067..b0dc5adbb2 100644 --- a/headers/libs/linprog/LinearSpec.h +++ b/headers/libs/linprog/LinearSpec.h @@ -58,6 +58,10 @@ public: virtual ResultType FindMins(const VariableList* variables) = 0; virtual ResultType FindMaxs(const VariableList* variables) = 0; + virtual void GetRangeConstraints(const Variable* var, + const Constraint** _min, + const Constraint** _max) const = 0; + protected: LinearSpec* fLinearSpec; }; @@ -138,6 +142,9 @@ public: BString ToString() const; + void GetRangeConstraints(const Variable*, + const Constraint** _min, + const Constraint** _max) const; const ConstraintList& Constraints() const; const VariableList& UsedVariables() const; const VariableList& AllVariables() const; diff --git a/src/libs/alm/SharedSolver.cpp b/src/libs/alm/SharedSolver.cpp index 57529c5165..34f090abe4 100644 --- a/src/libs/alm/SharedSolver.cpp +++ b/src/libs/alm/SharedSolver.cpp @@ -217,12 +217,13 @@ SharedSolver::AllArchived(BMessage* archive) const for each archived layout: add it to our archive add constraints created by areas and column manager to a set + add range constraints on the left/top/right/bottom tabs to the same set for each constraint in the linear spec: if it is not in the set above: archive it */ BArchiver archiver(archive); - std::set autoConstraints; + std::set autoConstraints; for (int32 i = fLayouts.CountItems() - 1; i >= 0; i--) { BALMLayout* layout = fLayouts.ItemAt(i); if (!archiver.IsArchived(layout)) @@ -233,22 +234,35 @@ SharedSolver::AllArchived(BMessage* archive) const for (int32 j = layout->fRowColumnManager->fRows.CountItems() - 1; j >= 0; j--) { - Row* row = layout->fRowColumnManager->fRows.ItemAt(i); + Row* row = layout->fRowColumnManager->fRows.ItemAt(j); autoConstraints.insert(row->fPrefSizeConstraint); } for (int32 j = layout->fRowColumnManager->fColumns.CountItems() - 1; j >= 0; j--) { - Column* column = layout->fRowColumnManager->fColumns.ItemAt(i); + Column* column = layout->fRowColumnManager->fColumns.ItemAt(j); autoConstraints.insert(column->fPrefSizeConstraint); } + + Variable* corners[] = {layout->fLeft, layout->fTop, layout->fRight, + layout->fBottom}; + + for (int32 j = 0; j < 4; j++) { + const Constraint* min; + const Constraint* max; + fLinearSpec.GetRangeConstraints(corners[j], &min, &max); + if (min) + autoConstraints.insert(min); + if (max) + autoConstraints.insert(max); + } } status_t err = B_OK; const ConstraintList& constraints = fLinearSpec.Constraints(); for (int32 i = constraints.CountItems() - 1; i >= 0 && err == B_OK; i--) { Constraint* constraint = constraints.ItemAt(i); - if (autoConstraints.find(constraint) != autoConstraints.end()) + if (autoConstraints.find(constraint) == autoConstraints.end()) err = _AddConstraintToArchive(constraint, archive); } return err; @@ -279,7 +293,7 @@ SharedSolver::AllUnarchived(const BMessage* archive) void SharedSolver::_AddConstraintsToSet(Area* area, - std::set& constraints) + std::set& constraints) { if (area->fMinContentWidth) constraints.insert(area->fMinContentWidth); @@ -295,8 +309,20 @@ SharedSolver::_AddConstraintsToSet(Area* area, status_t -SharedSolver::_AddConstraintToArchive(Constraint* constraint, BMessage* archive) +SharedSolver::_AddConstraintToArchive(Constraint* constraint, + BMessage* archive) { + /* Format: + * int32: summandCount + * { int32 : token + * double: coefficient + * } [summandCount] + * int32: operator + * double: rightSide + * double: penaltyNeg + * double: penaltyPos + */ + // TODO: check Read/Write calls BArchiver archiver(archive); BMallocIO buffer; @@ -338,6 +364,17 @@ status_t SharedSolver::_InstantiateConstraint(const void* rawData, ssize_t numBytes, BUnarchiver& unarchiver) { + /* Format: + * int32: summandCount + * { int32 : token + * double: coefficient + * } [summandCount] + * int32: operator + * double: rightSide + * double: penaltyNeg + * double: penaltyPos + */ + // TODO: check Read/Write calls BMemoryIO buffer(rawData, numBytes); int32 summandCount; @@ -376,13 +413,16 @@ SharedSolver::_InstantiateConstraint(const void* rawData, ssize_t numBytes, double penaltyPos; buffer.Read(&penaltyPos, sizeof(penaltyPos)); - if (err == B_OK) { - fLinearSpec.AddConstraint(summandList, (OperatorType)op, rightSide, - penaltyNeg, penaltyPos); + if (err != B_OK) + return err; + + if (fLinearSpec.AddConstraint(summandList, (OperatorType)op, rightSide, + penaltyNeg, penaltyPos) != NULL) { deleter.Detach(); + return B_OK; } - return err; + return B_NO_MEMORY; } diff --git a/src/libs/alm/SharedSolver.h b/src/libs/alm/SharedSolver.h index 0e9c84d649..3d397fa427 100644 --- a/src/libs/alm/SharedSolver.h +++ b/src/libs/alm/SharedSolver.h @@ -70,7 +70,7 @@ private: static void _AddConstraintsToSet(Area* area, - std::set& constraints); + std::set& constraints); static status_t _AddConstraintToArchive(Constraint* constraint, BMessage* archive); status_t _InstantiateConstraint(const void* rawData, diff --git a/src/libs/alm/Tab.cpp b/src/libs/alm/Tab.cpp index 13646c4119..f9614b6789 100644 --- a/src/libs/alm/Tab.cpp +++ b/src/libs/alm/Tab.cpp @@ -60,7 +60,8 @@ TabBase::TabBase() TabBase::TabBase(BMessage* archive) : - BArchivable(BUnarchiver::PrepareArchive(archive)) + BArchivable(BUnarchiver::PrepareArchive(archive)), + fLayouts(NULL) { BUnarchiver(archive).Finish(B_OK); } diff --git a/src/libs/linprog/ActiveSetSolver.cpp b/src/libs/linprog/ActiveSetSolver.cpp index aa592a23d5..95c98281e4 100644 --- a/src/libs/linprog/ActiveSetSolver.cpp +++ b/src/libs/linprog/ActiveSetSolver.cpp @@ -613,6 +613,19 @@ ActiveSetSolver::FindMins(const VariableList* variables) } +void +ActiveSetSolver::GetRangeConstraints(const Variable* var, + const Constraint** _min, const Constraint** _max) const +{ + int32 variableIndex = var->GlobalIndex(); + + if (_min) + *_min = fVariableGEConstraints.ItemAt(variableIndex); + if (_max) + *_max = fVariableLEConstraints.ItemAt(variableIndex); +} + + void ActiveSetSolver::_RemoveSoftConstraint(ConstraintList& list) { diff --git a/src/libs/linprog/ActiveSetSolver.h b/src/libs/linprog/ActiveSetSolver.h index ec55b1c906..397afe5834 100644 --- a/src/libs/linprog/ActiveSetSolver.h +++ b/src/libs/linprog/ActiveSetSolver.h @@ -77,6 +77,9 @@ public: ResultType FindMaxs(const VariableList* variables); ResultType FindMins(const VariableList* variables); + void GetRangeConstraints(const Variable* var, + const Constraint** _min, + const Constraint** _max) const; private: void _RemoveSoftConstraint(ConstraintList& list); void _AddSoftConstraint(const ConstraintList& list); diff --git a/src/libs/linprog/LinearSpec.cpp b/src/libs/linprog/LinearSpec.cpp index fa3e8d5af5..a266f0485f 100644 --- a/src/libs/linprog/LinearSpec.cpp +++ b/src/libs/linprog/LinearSpec.cpp @@ -590,6 +590,18 @@ LinearSpec::Save(const char* fileName) } +/** + * Gets the constraints generated by calls to Variable::SetRange() + * + */ +void +LinearSpec::GetRangeConstraints(const Variable* var, const Constraint** _min, + const Constraint** _max) const +{ + fSolver->GetRangeConstraints(var, _min, _max); +} + + /** * Gets the constraints. * diff --git a/src/tests/libs/alm/FriendLayout.cpp b/src/tests/libs/alm/FriendLayout.cpp index 5006cc16a3..0d12305f24 100644 --- a/src/tests/libs/alm/FriendLayout.cpp +++ b/src/tests/libs/alm/FriendLayout.cpp @@ -69,8 +69,8 @@ public: fRight = xTabs[1]; layout1->AreaFor(button2)->SetContentAspectRatio(1.0f); - fLayout2->Solver()->AddConstraint(-1.0f, xTabs[0], 1.0f, xTabs[1], - LinearProgramming::kGE, 20.0f); + fLayout2->Solver()->AddConstraint(-1.0f, layout1->Left(), 1.0f, xTabs[0], + LinearProgramming::kLE, 90.0f); BButton* archiveButton = new BButton("clone", new BMessage('arcv')); archiveButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,