Make SharedSolver BArchivable to save extra user constraints.

This commit is contained in:
Alex Wilson
2012-05-03 08:45:36 +12:00
parent bad1d6ba7e
commit 0a5e130725
7 changed files with 273 additions and 41 deletions
+5
View File
@@ -21,6 +21,10 @@ namespace LinearProgramming {
class Constraint;
};
namespace BPrivate {
class SharedSolver;
};
namespace BALM {
@@ -113,6 +117,7 @@ private:
private:
friend class BALMLayout;
friend class RowColumnManager;
friend class BPrivate::SharedSolver;
BLayoutItem* fLayoutItem;
int32 fID;
+9 -5
View File
@@ -16,6 +16,11 @@ namespace LinearProgramming {
};
namespace BPrivate {
class SharedSolver;
};
namespace BALM {
@@ -37,6 +42,10 @@ public:
XTab* Right() const;
private:
friend class BALMLayout;
friend class BALM::RowColumnManager;
friend class BPrivate::SharedSolver;
Column(LinearProgramming::LinearSpec* ls,
XTab* left, XTab* right);
@@ -48,11 +57,6 @@ private:
// managed by RowColumnManager
BObjectList<Area> fAreas;
public:
friend class BALMLayout;
friend class BALM::RowColumnManager;
};
} // namespace BALM
+9 -5
View File
@@ -16,6 +16,11 @@ namespace LinearProgramming {
};
namespace BPrivate {
class SharedSolver;
};
namespace BALM {
@@ -37,6 +42,10 @@ public:
YTab* Bottom() const;
private:
friend class BALMLayout;
friend class BALM::RowColumnManager;
friend class BPrivate::SharedSolver;
Row(LinearProgramming::LinearSpec* ls,
YTab* top, YTab* bottom);
@@ -48,11 +57,6 @@ private:
// managed by RowColumnManager
BObjectList<Area> fAreas;
public:
friend class BALMLayout;
friend class BALM::RowColumnManager;
};
} // namespace BALM
+11 -19
View File
@@ -28,7 +28,7 @@ const BSize kUnsetSize(B_SIZE_UNSET, B_SIZE_UNSET);
namespace {
const char* kFriendField = "BALMLayout:friends";
const char* kSolverField = "BALMLayout:solver";
const char* kBadLayoutPolicyField = "BALMLayout:policy";
const char* kXTabsField = "BALMLayout:xtabs";
const char* kYTabsField = "BALMLayout:ytabs";
@@ -269,6 +269,9 @@ BALMLayout::BALMLayout(BMessage* archive)
if (err == B_OK && archive->GetInfo(kBadLayoutPolicyField, NULL) == B_OK)
err = unarchiver.EnsureUnarchived(kBadLayoutPolicyField);
if (err == B_OK)
err = unarchiver.EnsureUnarchived(kSolverField);
unarchiver.Finish(err);
}
@@ -1061,6 +1064,9 @@ BALMLayout::Archive(BMessage* into, bool deep) const
err = archiver.AddArchivable(kBadLayoutPolicyField, fBadLayoutPolicy);
}
if (err == B_OK)
err = archiver.AddArchivable(kSolverField, fSolver);
if (err == B_OK)
err = archiver.AddArchivable(kMyTabsField, fLeft);
if (err == B_OK)
@@ -1140,26 +1146,14 @@ BALMLayout::AllUnarchived(const BMessage* archive)
{
BUnarchiver unarchiver(archive);
status_t err = B_OK;
if (fSolver == NULL) {
_SetSolver(new SharedSolver());
int32 friendCount = 0;
archive->GetInfo(kFriendField, NULL, &friendCount);
for (int32 i = 0; i < friendCount; i++) {
BALMLayout* layout;
err = unarchiver.FindObject(kFriendField, i,
BUnarchiver::B_DONT_ASSUME_OWNERSHIP, layout);
if (err != B_OK)
return err;
layout->_SetSolver(fSolver);
}
}
SharedSolver* solver;
status_t err = unarchiver.FindObject(kSolverField, solver);
if (err != B_OK)
return err;
_SetSolver(solver);
if (archive->GetInfo(kBadLayoutPolicyField, NULL) == B_OK) {
BadLayoutPolicy* policy;
err = unarchiver.FindObject(kBadLayoutPolicyField, policy);
@@ -1235,8 +1229,6 @@ BALMLayout::AllArchived(BMessage* archive) const
{
status_t err = BAbstractLayout::AllArchived(archive);
if (err == B_OK)
err = fSolver->AddFriendReferences(this, archive, kFriendField);
return err;
}
+7 -1
View File
@@ -14,6 +14,11 @@
#include "Tab.h"
namespace BPrivate {
class SharedSolver;
};
namespace BALM {
@@ -41,6 +46,7 @@ public:
void UpdateConstraints();
void TabsChanged(Area* area);
private:
friend class BPrivate::SharedSolver;
Row* _FindRowFor(Area* area);
Column* _FindColumnFor(Area* area);
@@ -52,7 +58,7 @@ private:
void _UpdateConstraints(Row* row);
void _UpdateConstraints(Column* column);
BObjectList<Row> fRows;
BObjectList<Row> fRows;
BObjectList<Column> fColumns;
LinearSpec* fLinearSpec;
+209 -8
View File
@@ -6,13 +6,26 @@
#include "SharedSolver.h"
#include <set>
#include <ALMLayout.h>
#include <AutoDeleter.h>
#include <ObjectList.h>
#include "RowColumnManager.h"
using LinearProgramming::LinearSpec;
namespace {
type_code kConstraintsTypeCode = 'cnst';
const char* kConstraintsField = "SharedSolver:constraints";
};
struct SharedSolver::MinSizeValidator {
inline void CallSolverMethod(LinearSpec* spec, VariableList* vars)
{
@@ -80,6 +93,19 @@ SharedSolver::SharedSolver()
}
SharedSolver::SharedSolver(BMessage* archive)
:
BArchivable(archive),
fConstraintsValid(false),
fMinValid(false),
fMaxValid(false),
fPreferredValid(false),
fLayoutValid(false),
fLayoutContext(NULL)
{
}
SharedSolver::~SharedSolver()
{
if (fLayouts.CountItems() > 0)
@@ -178,18 +204,184 @@ SharedSolver::ValidateLayout(BLayoutContext* context)
status_t
SharedSolver::AddFriendReferences(const BALMLayout* layout, BMessage* archive,
const char* field)
SharedSolver::Archive(BMessage* archive, bool deep) const
{
status_t err = B_OK;
return BArchivable::Archive(archive, deep);
}
status_t
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
for each constraint in the linear spec:
if it is not in the set above:
archive it
*/
BArchiver archiver(archive);
for (int32 i = fLayouts.CountItems() - 1; i >= 0 && err == B_OK; i--) {
BALMLayout* current = fLayouts.ItemAt(i);
if (current == layout)
std::set<Constraint*> autoConstraints;
for (int32 i = fLayouts.CountItems() - 1; i >= 0; i--) {
BALMLayout* layout = fLayouts.ItemAt(i);
if (!archiver.IsArchived(layout))
continue;
if (archiver.IsArchived(current))
err = archiver.AddArchivable(field, current);
for (int32 j = layout->CountItems() - 1; j >= 0; j--)
_AddConstraintsToSet(layout->AreaAt(j), autoConstraints);
for (int32 j = layout->fRowColumnManager->fRows.CountItems() - 1;
j >= 0; j--) {
Row* row = layout->fRowColumnManager->fRows.ItemAt(i);
autoConstraints.insert(row->fPrefSizeConstraint);
}
for (int32 j = layout->fRowColumnManager->fColumns.CountItems() - 1;
j >= 0; j--) {
Column* column = layout->fRowColumnManager->fColumns.ItemAt(i);
autoConstraints.insert(column->fPrefSizeConstraint);
}
}
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())
err = _AddConstraintToArchive(constraint, archive);
}
return err;
}
status_t
SharedSolver::AllUnarchived(const BMessage* archive)
{
int32 count = 0;
archive->GetInfo(kConstraintsField, NULL, &count);
status_t err = B_OK;
BUnarchiver unarchiver(archive);
for (int32 i = 0; i < count && err == B_OK; i++) {
const void* constraintData;
ssize_t numBytes;
err = archive->FindData(kConstraintsField, kConstraintsTypeCode,
i, &constraintData, &numBytes);
if (err != B_OK)
return err;
err = _InstantiateConstraint(constraintData, numBytes, unarchiver);
}
return err;
}
void
SharedSolver::_AddConstraintsToSet(Area* area,
std::set<Constraint*>& constraints)
{
if (area->fMinContentWidth)
constraints.insert(area->fMinContentWidth);
if (area->fMaxContentWidth)
constraints.insert(area->fMaxContentWidth);
if (area->fMinContentHeight)
constraints.insert(area->fMinContentHeight);
if (area->fMaxContentHeight)
constraints.insert(area->fMaxContentHeight);
if (area->fContentAspectRatioC)
constraints.insert(area->fContentAspectRatioC);
}
status_t
SharedSolver::_AddConstraintToArchive(Constraint* constraint, BMessage* archive)
{
// TODO: check Read/Write calls
BArchiver archiver(archive);
BMallocIO buffer;
SummandList* leftSide = constraint->LeftSide();
int32 summandCount = leftSide->CountItems();
buffer.Write(&summandCount, sizeof(summandCount));
for (int32 i = 0; i < summandCount; i++) {
Summand* summand = leftSide->ItemAt(i);
Variable* var = summand->Var();
BArchivable* varArchivable = dynamic_cast<BArchivable*>(var);
if (!varArchivable || !archiver.IsArchived(varArchivable))
return B_NAME_NOT_FOUND;
int32 token;
archiver.GetTokenForArchivable(varArchivable, token);
buffer.Write(&token, sizeof(token));
double coefficient = summand->Coeff();
buffer.Write(&coefficient, sizeof(coefficient));
}
int32 op = constraint->Op();
buffer.Write(&op, sizeof(op));
double rightSide = constraint->RightSide();
buffer.Write(&rightSide, sizeof(rightSide));
double penaltyNeg = constraint->PenaltyNeg();
buffer.Write(&penaltyNeg, sizeof(penaltyNeg));
double penaltyPos = constraint->PenaltyPos();
buffer.Write(&penaltyPos, sizeof(penaltyPos));
return archive->AddData(kConstraintsField, kConstraintsTypeCode,
buffer.Buffer(), buffer.BufferLength(), false);
}
status_t
SharedSolver::_InstantiateConstraint(const void* rawData, ssize_t numBytes,
BUnarchiver& unarchiver)
{
// TODO: check Read/Write calls
BMemoryIO buffer(rawData, numBytes);
int32 summandCount;
buffer.Read((void*)&summandCount, sizeof(summandCount));
SummandList* summandList = new SummandList(20, true);
ObjectDeleter<SummandList> deleter(summandList);
status_t err = B_OK;
for (int32 i = 0; i < summandCount; i++) {
int32 token;
buffer.Read((void*)&token, sizeof(token));
BArchivable* varArchivable;
err = unarchiver.GetObject(token, varArchivable);
if (err != B_OK)
break;
Variable* var = dynamic_cast<Variable*>(varArchivable);
if (!var)
return B_BAD_TYPE;
fLinearSpec.AddVariable(var);
double coefficient;
buffer.Read(&coefficient, sizeof(coefficient));
summandList->AddItem(new Summand(coefficient, var));
}
int32 op;
buffer.Read(&op, sizeof(op));
double rightSide;
buffer.Read(&rightSide, sizeof(rightSide));
double penaltyNeg;
buffer.Read(&penaltyNeg, sizeof(penaltyNeg));
double penaltyPos;
buffer.Read(&penaltyPos, sizeof(penaltyPos));
if (err == B_OK) {
fLinearSpec.AddConstraint(summandList, (OperatorType)op, rightSide,
penaltyNeg, penaltyPos);
deleter.Detach();
}
return err;
}
@@ -275,3 +467,12 @@ SharedSolver::_Validate(bool& isValid, ResultType& result)
isValid = true;
fLayoutValid = false;
}
BArchivable*
SharedSolver::Instantiate(BMessage* archive)
{
if (validate_instantiation(archive, "BPrivate::SharedSolver"))
return new SharedSolver(archive);
return NULL;
}
+23 -3
View File
@@ -6,6 +6,9 @@
#define _SHARED_SOLVER_H
#include <set>
#include <Archivable.h>
#include <LayoutContext.h>
#include <ObjectList.h>
#include <Referenceable.h>
@@ -17,18 +20,20 @@ class BMessage;
namespace BALM {
class BALMLayout;
class Area;
};
using BALM::BALMLayout;
using BALM::Area;
namespace BPrivate {
class SharedSolver : BLayoutContextListener, public BReferenceable {
class SharedSolver : BLayoutContextListener, public BReferenceable,
public BArchivable {
public:
SharedSolver(BMessage* archive);
SharedSolver();
~SharedSolver();
@@ -47,6 +52,13 @@ public:
status_t AddFriendReferences(const BALMLayout* layout,
BMessage* archive, const char* field);
status_t Archive(BMessage* archive, bool deep) const;
status_t AllArchived(BMessage* archive) const;
status_t AllUnarchived(const BMessage* archive);
static BArchivable* Instantiate(BMessage* archive);
private:
struct MinSizeValidator;
struct MaxSizeValidator;
@@ -56,6 +68,14 @@ private:
friend struct MaxSizeValidator;
friend struct PreferredSizeValidator;
static void _AddConstraintsToSet(Area* area,
std::set<Constraint*>& constraints);
static status_t _AddConstraintToArchive(Constraint* constraint,
BMessage* archive);
status_t _InstantiateConstraint(const void* rawData,
ssize_t numBytes, BUnarchiver& unarchiver);
void SetMaxSize(BALM::BALMLayout* layout,
const BSize& max);
void SetMinSize(BALM::BALMLayout* layout,