diff --git a/headers/libs/alm/Area.h b/headers/libs/alm/Area.h
index ef40616ded..6f471c6431 100644
--- a/headers/libs/alm/Area.h
+++ b/headers/libs/alm/Area.h
@@ -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;
diff --git a/headers/libs/alm/Column.h b/headers/libs/alm/Column.h
index 50cc05b74e..c9ef423268 100644
--- a/headers/libs/alm/Column.h
+++ b/headers/libs/alm/Column.h
@@ -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 fAreas;
-
-public:
- friend class BALMLayout;
- friend class BALM::RowColumnManager;
-
};
} // namespace BALM
diff --git a/headers/libs/alm/Row.h b/headers/libs/alm/Row.h
index b5af7c7cad..af49ea453d 100644
--- a/headers/libs/alm/Row.h
+++ b/headers/libs/alm/Row.h
@@ -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 fAreas;
-
-public:
- friend class BALMLayout;
- friend class BALM::RowColumnManager;
-
};
} // namespace BALM
diff --git a/src/libs/alm/ALMLayout.cpp b/src/libs/alm/ALMLayout.cpp
index 841c1836db..c9a684078e 100644
--- a/src/libs/alm/ALMLayout.cpp
+++ b/src/libs/alm/ALMLayout.cpp
@@ -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;
}
diff --git a/src/libs/alm/RowColumnManager.h b/src/libs/alm/RowColumnManager.h
index 55a844397a..39bc57dbfb 100644
--- a/src/libs/alm/RowColumnManager.h
+++ b/src/libs/alm/RowColumnManager.h
@@ -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 fRows;
+ BObjectList fRows;
BObjectList fColumns;
LinearSpec* fLinearSpec;
diff --git a/src/libs/alm/SharedSolver.cpp b/src/libs/alm/SharedSolver.cpp
index df46da6ac4..57529c5165 100644
--- a/src/libs/alm/SharedSolver.cpp
+++ b/src/libs/alm/SharedSolver.cpp
@@ -6,13 +6,26 @@
#include "SharedSolver.h"
+#include
+
#include
+#include
#include
+#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 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& 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(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 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(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;
+}
diff --git a/src/libs/alm/SharedSolver.h b/src/libs/alm/SharedSolver.h
index ce9319b6d9..0e9c84d649 100644
--- a/src/libs/alm/SharedSolver.h
+++ b/src/libs/alm/SharedSolver.h
@@ -6,6 +6,9 @@
#define _SHARED_SOLVER_H
+#include
+
+#include
#include
#include
#include
@@ -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& 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,