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.
This commit is contained in:
Alex Wilson
2012-05-03 08:45:44 +12:00
parent 5f4e71ba4c
commit c8b24e3eb5
8 changed files with 90 additions and 14 deletions
+7
View File
@@ -58,6 +58,10 @@ public:
virtual ResultType FindMins(const VariableList* variables) = 0; virtual ResultType FindMins(const VariableList* variables) = 0;
virtual ResultType FindMaxs(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: protected:
LinearSpec* fLinearSpec; LinearSpec* fLinearSpec;
}; };
@@ -138,6 +142,9 @@ public:
BString ToString() const; BString ToString() const;
void GetRangeConstraints(const Variable*,
const Constraint** _min,
const Constraint** _max) const;
const ConstraintList& Constraints() const; const ConstraintList& Constraints() const;
const VariableList& UsedVariables() const; const VariableList& UsedVariables() const;
const VariableList& AllVariables() const; const VariableList& AllVariables() const;
+50 -10
View File
@@ -217,12 +217,13 @@ SharedSolver::AllArchived(BMessage* archive) const
for each archived layout: for each archived layout:
add it to our archive add it to our archive
add constraints created by areas and column manager to a set 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: for each constraint in the linear spec:
if it is not in the set above: if it is not in the set above:
archive it archive it
*/ */
BArchiver archiver(archive); BArchiver archiver(archive);
std::set<Constraint*> autoConstraints; std::set<const Constraint*> autoConstraints;
for (int32 i = fLayouts.CountItems() - 1; i >= 0; i--) { for (int32 i = fLayouts.CountItems() - 1; i >= 0; i--) {
BALMLayout* layout = fLayouts.ItemAt(i); BALMLayout* layout = fLayouts.ItemAt(i);
if (!archiver.IsArchived(layout)) if (!archiver.IsArchived(layout))
@@ -233,22 +234,35 @@ SharedSolver::AllArchived(BMessage* archive) const
for (int32 j = layout->fRowColumnManager->fRows.CountItems() - 1; for (int32 j = layout->fRowColumnManager->fRows.CountItems() - 1;
j >= 0; j--) { j >= 0; j--) {
Row* row = layout->fRowColumnManager->fRows.ItemAt(i); Row* row = layout->fRowColumnManager->fRows.ItemAt(j);
autoConstraints.insert(row->fPrefSizeConstraint); autoConstraints.insert(row->fPrefSizeConstraint);
} }
for (int32 j = layout->fRowColumnManager->fColumns.CountItems() - 1; for (int32 j = layout->fRowColumnManager->fColumns.CountItems() - 1;
j >= 0; j--) { j >= 0; j--) {
Column* column = layout->fRowColumnManager->fColumns.ItemAt(i); Column* column = layout->fRowColumnManager->fColumns.ItemAt(j);
autoConstraints.insert(column->fPrefSizeConstraint); 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; status_t err = B_OK;
const ConstraintList& constraints = fLinearSpec.Constraints(); const ConstraintList& constraints = fLinearSpec.Constraints();
for (int32 i = constraints.CountItems() - 1; i >= 0 && err == B_OK; i--) { for (int32 i = constraints.CountItems() - 1; i >= 0 && err == B_OK; i--) {
Constraint* constraint = constraints.ItemAt(i); Constraint* constraint = constraints.ItemAt(i);
if (autoConstraints.find(constraint) != autoConstraints.end()) if (autoConstraints.find(constraint) == autoConstraints.end())
err = _AddConstraintToArchive(constraint, archive); err = _AddConstraintToArchive(constraint, archive);
} }
return err; return err;
@@ -279,7 +293,7 @@ SharedSolver::AllUnarchived(const BMessage* archive)
void void
SharedSolver::_AddConstraintsToSet(Area* area, SharedSolver::_AddConstraintsToSet(Area* area,
std::set<Constraint*>& constraints) std::set<const Constraint*>& constraints)
{ {
if (area->fMinContentWidth) if (area->fMinContentWidth)
constraints.insert(area->fMinContentWidth); constraints.insert(area->fMinContentWidth);
@@ -295,8 +309,20 @@ SharedSolver::_AddConstraintsToSet(Area* area,
status_t 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 // TODO: check Read/Write calls
BArchiver archiver(archive); BArchiver archiver(archive);
BMallocIO buffer; BMallocIO buffer;
@@ -338,6 +364,17 @@ status_t
SharedSolver::_InstantiateConstraint(const void* rawData, ssize_t numBytes, SharedSolver::_InstantiateConstraint(const void* rawData, ssize_t numBytes,
BUnarchiver& unarchiver) BUnarchiver& unarchiver)
{ {
/* Format:
* int32: summandCount
* { int32 : token
* double: coefficient
* } [summandCount]
* int32: operator
* double: rightSide
* double: penaltyNeg
* double: penaltyPos
*/
// TODO: check Read/Write calls // TODO: check Read/Write calls
BMemoryIO buffer(rawData, numBytes); BMemoryIO buffer(rawData, numBytes);
int32 summandCount; int32 summandCount;
@@ -376,13 +413,16 @@ SharedSolver::_InstantiateConstraint(const void* rawData, ssize_t numBytes,
double penaltyPos; double penaltyPos;
buffer.Read(&penaltyPos, sizeof(penaltyPos)); buffer.Read(&penaltyPos, sizeof(penaltyPos));
if (err == B_OK) { if (err != B_OK)
fLinearSpec.AddConstraint(summandList, (OperatorType)op, rightSide, return err;
penaltyNeg, penaltyPos);
if (fLinearSpec.AddConstraint(summandList, (OperatorType)op, rightSide,
penaltyNeg, penaltyPos) != NULL) {
deleter.Detach(); deleter.Detach();
return B_OK;
} }
return err; return B_NO_MEMORY;
} }
+1 -1
View File
@@ -70,7 +70,7 @@ private:
static void _AddConstraintsToSet(Area* area, static void _AddConstraintsToSet(Area* area,
std::set<Constraint*>& constraints); std::set<const Constraint*>& constraints);
static status_t _AddConstraintToArchive(Constraint* constraint, static status_t _AddConstraintToArchive(Constraint* constraint,
BMessage* archive); BMessage* archive);
status_t _InstantiateConstraint(const void* rawData, status_t _InstantiateConstraint(const void* rawData,
+2 -1
View File
@@ -60,7 +60,8 @@ TabBase::TabBase()
TabBase::TabBase(BMessage* archive) TabBase::TabBase(BMessage* archive)
: :
BArchivable(BUnarchiver::PrepareArchive(archive)) BArchivable(BUnarchiver::PrepareArchive(archive)),
fLayouts(NULL)
{ {
BUnarchiver(archive).Finish(B_OK); BUnarchiver(archive).Finish(B_OK);
} }
+13
View File
@@ -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 void
ActiveSetSolver::_RemoveSoftConstraint(ConstraintList& list) ActiveSetSolver::_RemoveSoftConstraint(ConstraintList& list)
{ {
+3
View File
@@ -77,6 +77,9 @@ public:
ResultType FindMaxs(const VariableList* variables); ResultType FindMaxs(const VariableList* variables);
ResultType FindMins(const VariableList* variables); ResultType FindMins(const VariableList* variables);
void GetRangeConstraints(const Variable* var,
const Constraint** _min,
const Constraint** _max) const;
private: private:
void _RemoveSoftConstraint(ConstraintList& list); void _RemoveSoftConstraint(ConstraintList& list);
void _AddSoftConstraint(const ConstraintList& list); void _AddSoftConstraint(const ConstraintList& list);
+12
View File
@@ -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. * Gets the constraints.
* *
+2 -2
View File
@@ -69,8 +69,8 @@ public:
fRight = xTabs[1]; fRight = xTabs[1];
layout1->AreaFor(button2)->SetContentAspectRatio(1.0f); layout1->AreaFor(button2)->SetContentAspectRatio(1.0f);
fLayout2->Solver()->AddConstraint(-1.0f, xTabs[0], 1.0f, xTabs[1], fLayout2->Solver()->AddConstraint(-1.0f, layout1->Left(), 1.0f, xTabs[0],
LinearProgramming::kGE, 20.0f); LinearProgramming::kLE, 90.0f);
BButton* archiveButton = new BButton("clone", new BMessage('arcv')); BButton* archiveButton = new BButton("clone", new BMessage('arcv'));
archiveButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, archiveButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,