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-04-30 14:07:06 +12:00
parent 5f4e71ba4c
commit c8b24e3eb5
8 changed files with 90 additions and 14 deletions

View File

@ -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;

View File

@ -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<Constraint*> autoConstraints;
std::set<const Constraint*> 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<Constraint*>& constraints)
std::set<const Constraint*>& 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;
}

View File

@ -70,7 +70,7 @@ private:
static void _AddConstraintsToSet(Area* area,
std::set<Constraint*>& constraints);
std::set<const Constraint*>& constraints);
static status_t _AddConstraintToArchive(Constraint* constraint,
BMessage* archive);
status_t _InstantiateConstraint(const void* rawData,

View File

@ -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);
}

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
ActiveSetSolver::_RemoveSoftConstraint(ConstraintList& list)
{

View File

@ -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);

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.
*

View File

@ -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,