Add initial support for archiving a BALMLayout.

What's supported:
* basic archive/instantiate
* friend layouts
coming soon:
* saving of custom restraints
* archiving of BadLayoutPolicy
This commit is contained in:
Alex Wilson
2012-05-03 08:45:32 +12:00
parent f9c58743e3
commit 35bf0b5c1c
6 changed files with 375 additions and 12 deletions
+13
View File
@@ -39,6 +39,7 @@ public:
BALMLayout(float hSpacing = 0.0f,
float vSpacing = 0.0f,
BALMLayout* friendLayout = NULL);
BALMLayout(BMessage* archive);
virtual ~BALMLayout();
BReference<XTab> AddXTab();
@@ -118,12 +119,23 @@ public:
virtual BSize BasePreferredSize();
virtual BAlignment BaseAlignment();
virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
virtual status_t Perform(perform_code d, void* arg);
protected:
virtual bool ItemAdded(BLayoutItem* item, int32 atIndex);
virtual void ItemRemoved(BLayoutItem* item, int32 fromIndex);
virtual status_t ItemArchived(BMessage* into, BLayoutItem* item,
int32 index) const;
virtual status_t ItemUnarchived(const BMessage* from,
BLayoutItem* item, int32 index);
virtual status_t AllUnarchived(const BMessage* archive);
virtual status_t AllArchived(BMessage* archive) const;
virtual void LayoutInvalidated(bool children);
virtual void DoLayout();
@@ -184,6 +196,7 @@ private:
bool _AddedTab(YTab* tab);
BLayoutItem* _LayoutItemToAdd(BView* view);
void _SetSolver(BPrivate::SharedSolver* solver);
BPrivate::SharedSolver* fSolver;
+7 -1
View File
@@ -6,6 +6,7 @@
#define X_TAB_H
#include <Archivable.h>
#include <Referenceable.h>
#include "Variable.h"
@@ -17,9 +18,10 @@ namespace BALM {
class BALMLayout;
class TabBase {
class TabBase : public BArchivable {
private:
TabBase();
TabBase(BMessage* archive);
virtual ~TabBase();
friend class BALMLayout;
@@ -43,11 +45,13 @@ class XTab : public Variable, public TabBase, public BReferenceable {
public:
virtual ~XTab();
static BArchivable* Instantiate(BMessage* archive);
protected:
friend class BALMLayout;
XTab(BALMLayout* layout);
private:
XTab(BMessage* archive);
uint32 _reserved[2];
};
@@ -56,10 +60,12 @@ class YTab : public Variable, public TabBase, public BReferenceable {
public:
virtual ~YTab();
static BArchivable* Instantiate(BMessage* archive);
protected:
friend class BALMLayout;
YTab(BALMLayout* layout);
private:
YTab(BMessage* archive);
uint32 _reserved[2];
};
+282 -7
View File
@@ -26,9 +26,21 @@ using namespace LinearProgramming;
const BSize kUnsetSize(B_SIZE_UNSET, B_SIZE_UNSET);
namespace {
const char* kFriendField = "BALMLayout:friends";
const char* kXTabsField = "BALMLayout:xtabs";
const char* kYTabsField = "BALMLayout:ytabs";
const char* kTabsField = "BALMLayout:item:tabs";
const char* kMyTabsField = "BALMLayout:tabs";
const char* kInsetsField = "BALMLayout:insets";
const char* kSpacingField = "BALMLayout:spacing";
int CompareXTabFunc(const XTab* tab1, const XTab* tab2);
int CompareYTabFunc(const YTab* tab1, const YTab* tab2);
};
namespace BALM {
@@ -144,10 +156,7 @@ BALMLayout::BALMLayout(float hSpacing, float vSpacing, BALMLayout* friendLayout)
fYTabsSorted(false),
fBadLayoutPolicy(new DefaultPolicy())
{
fSolver = friendLayout ? friendLayout->fSolver : new SharedSolver();
fSolver->AcquireReference();
fSolver->RegisterLayout(this);
fRowColumnManager = new RowColumnManager(Solver());
_SetSolver(friendLayout ? friendLayout->fSolver : new SharedSolver());
fLeft = AddXTab();
fRight = AddXTab();
@@ -167,13 +176,68 @@ BALMLayout::BALMLayout(float hSpacing, float vSpacing, BALMLayout* friendLayout)
}
BALMLayout::BALMLayout(BMessage* archive)
:
BAbstractLayout(BUnarchiver::PrepareArchive(archive)),
fSolver(NULL),
fLeft(NULL),
fRight(NULL),
fTop(NULL),
fBottom(NULL),
fMinSize(kUnsetSize),
fMaxSize(kUnsetSize),
fPreferredSize(kUnsetSize),
fXTabsSorted(false),
fYTabsSorted(false),
fBadLayoutPolicy(new DefaultPolicy())
{
BUnarchiver unarchiver(archive);
BRect insets;
status_t err = archive->FindRect(kInsetsField, &insets);
if (err != B_OK) {
unarchiver.Finish(err);
return;
}
fLeftInset = insets.left;
fRightInset = insets.right;
fTopInset = insets.top;
fBottomInset = insets.bottom;
BSize spacing;
err = archive->FindSize(kSpacingField, &spacing);
if (err != B_OK) {
unarchiver.Finish(err);
return;
}
fHSpacing = spacing.width;
fVSpacing = spacing.height;
int32 tabCount = 0;
archive->GetInfo(kXTabsField, NULL, &tabCount);
for (int32 i = 0; i < tabCount && err == B_OK; i++)
err = unarchiver.EnsureUnarchived(kXTabsField, i);
archive->GetInfo(kYTabsField, NULL, &tabCount);
for (int32 i = 0; i < tabCount && err == B_OK; i++)
err = unarchiver.EnsureUnarchived(kYTabsField, i);
unarchiver.Finish(err);
}
BALMLayout::~BALMLayout()
{
delete fRowColumnManager;
delete fBadLayoutPolicy;
fSolver->LayoutLeaving(this);
fSolver->ReleaseReference();
if (fSolver) {
fSolver->LayoutLeaving(this);
fSolver->ReleaseReference();
}
}
@@ -317,6 +381,9 @@ BALMLayout::IndexOf(YTab* tab, bool ordered)
}
namespace {
int
CompareXTabFunc(const XTab* tab1, const XTab* tab2)
{
@@ -339,6 +406,7 @@ CompareYTabFunc(const YTab* tab1, const YTab* tab2)
}
}; // end anonymous namespace
/**
@@ -921,6 +989,202 @@ BALMLayout::BaseAlignment()
}
status_t
BALMLayout::Archive(BMessage* into, bool deep) const
{
BArchiver archiver(into);
status_t err = BAbstractLayout::Archive(into, deep);
if (err != B_OK)
return archiver.Finish(err);
BRect insets(fLeftInset, fTopInset, fRightInset, fBottomInset);
err = into->AddRect(kInsetsField, insets);
if (err != B_OK)
return archiver.Finish(err);
BSize spacing(fHSpacing, fVSpacing);
err = into->AddSize(kSpacingField, spacing);
if (err != B_OK)
return archiver.Finish(err);
if (deep) {
for (int32 i = CountXTabs() - 1; i >= 0 && err == B_OK; i--)
err = archiver.AddArchivable(kXTabsField, XTabAt(i));
for (int32 i = CountYTabs() - 1; i >= 0 && err == B_OK; i--)
err = archiver.AddArchivable(kYTabsField, YTabAt(i));
}
if (err == B_OK)
err = archiver.AddArchivable(kMyTabsField, fLeft);
if (err == B_OK)
err = archiver.AddArchivable(kMyTabsField, fTop);
if (err == B_OK)
err = archiver.AddArchivable(kMyTabsField, fRight);
if (err == B_OK)
err = archiver.AddArchivable(kMyTabsField, fBottom);
return archiver.Finish(err);
}
BArchivable*
BALMLayout::Instantiate(BMessage* from)
{
if (validate_instantiation(from, "BALM::BALMLayout"))
return new BALMLayout(from);
return NULL;
}
status_t
BALMLayout::ItemArchived(BMessage* into, BLayoutItem* item, int32 index) const
{
BArchiver archiver(into);
status_t err = BAbstractLayout::ItemArchived(into, item, index);
if (err != B_OK)
return err;
Area* area = AreaFor(item);
err = archiver.AddArchivable(kTabsField, area->Left());
if (err == B_OK)
archiver.AddArchivable(kTabsField, area->Top());
if (err == B_OK)
archiver.AddArchivable(kTabsField, area->Right());
if (err == B_OK)
archiver.AddArchivable(kTabsField, area->Bottom());
return err;
}
status_t
BALMLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item,
int32 index)
{
BUnarchiver unarchiver(from);
status_t err = BAbstractLayout::ItemUnarchived(from, item, index);
if (err != B_OK)
return err;
Area* area = AreaFor(item);
XTab* left;
XTab* right;
YTab* bottom;
YTab* top;
err = unarchiver.FindObject(kTabsField, index * 4, left);
if (err == B_OK)
err = unarchiver.FindObject(kTabsField, index * 4 + 1, top);
if (err == B_OK)
err = unarchiver.FindObject(kTabsField, index * 4 + 2, right);
if (err == B_OK)
err = unarchiver.FindObject(kTabsField, index * 4 + 3, bottom);
if (err == B_OK) {
area->_Init(Solver(), left, top, right, bottom, fRowColumnManager);
fRowColumnManager->AddArea(area);
}
return err;
}
status_t
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);
}
}
LinearSpec* spec = Solver();
int32 tabCount = 0;
archive->GetInfo(kXTabsField, NULL, &tabCount);
for (int32 i = 0; i < tabCount && err == B_OK; i++) {
XTab* tab;
err = unarchiver.FindObject(kXTabsField, i,
BUnarchiver::B_DONT_ASSUME_OWNERSHIP, tab);
spec->AddVariable(tab);
TabAddTransaction<XTab> adder(this);
if (adder.AttempAdd(tab))
adder.Commit();
else
err = B_NO_MEMORY;
}
archive->GetInfo(kYTabsField, NULL, &tabCount);
for (int32 i = 0; i < tabCount; i++) {
YTab* tab;
unarchiver.FindObject(kYTabsField, i,
BUnarchiver::B_DONT_ASSUME_OWNERSHIP, tab);
spec->AddVariable(tab);
TabAddTransaction<YTab> adder(this);
if (adder.AttempAdd(tab))
adder.Commit();
else
err = B_NO_MEMORY;
}
if (err == B_OK) {
XTab* leftTab = NULL;
err = unarchiver.FindObject(kMyTabsField, 0, leftTab);
fLeft = leftTab;
}
if (err == B_OK) {
YTab* topTab = NULL;
err = unarchiver.FindObject(kMyTabsField, 1, topTab);
fTop = topTab;
}
if (err == B_OK) {
XTab* rightTab = NULL;
err = unarchiver.FindObject(kMyTabsField, 2, rightTab);
fRight = rightTab;
}
if (err == B_OK) {
YTab* bottomTab = NULL;
err = unarchiver.FindObject(kMyTabsField, 3, bottomTab);
fBottom = bottomTab;
}
if (err == B_OK) {
fLeft->SetRange(0, 0);
fTop->SetRange(0, 0);
err = BAbstractLayout::AllUnarchived(archive);
}
return err;
}
status_t
BALMLayout::AllArchived(BMessage* archive) const
{
status_t err = BAbstractLayout::AllArchived(archive);
if (err == B_OK)
err = fSolver->AddFriendReferences(this, archive, kFriendField);
return err;
}
/**
* Invalidates the layout.
* Resets minimum/maximum/preferred size.
@@ -934,7 +1198,8 @@ BALMLayout::LayoutInvalidated(bool children)
fXTabsSorted = false;
fYTabsSorted = false;
fSolver->Invalidate(children);
if (fSolver)
fSolver->Invalidate(children);
}
@@ -1108,6 +1373,16 @@ BALMLayout::_LayoutItemToAdd(BView* view)
}
void
BALMLayout::_SetSolver(SharedSolver* solver)
{
fSolver = solver;
fSolver->AcquireReference();
fSolver->RegisterLayout(this);
fRowColumnManager = new RowColumnManager(Solver());
}
status_t
BALMLayout::Perform(perform_code d, void* arg)
{
+19 -2
View File
@@ -124,9 +124,9 @@ SharedSolver::RegisterLayout(BALMLayout* layout)
void
SharedSolver::LayoutLeaving(BALMLayout* layout)
SharedSolver::LayoutLeaving(const BALMLayout* layout)
{
fLayouts.RemoveItem(layout);
fLayouts.RemoveItem(const_cast<BALMLayout*>(layout));
Invalidate(false);
}
@@ -177,6 +177,23 @@ SharedSolver::ValidateLayout(BLayoutContext* context)
}
status_t
SharedSolver::AddFriendReferences(const BALMLayout* layout, BMessage* archive,
const char* field)
{
status_t err = B_OK;
BArchiver archiver(archive);
for (int32 i = fLayouts.CountItems() - 1; i >= 0 && err == B_OK; i--) {
BALMLayout* current = fLayouts.ItemAt(i);
if (current == layout)
continue;
if (archiver.IsArchived(current))
err = archiver.AddArchivable(field, current);
}
return err;
}
void
SharedSolver::SetMaxSize(BALMLayout* layout, const BSize& max)
{
+10 -2
View File
@@ -13,11 +13,16 @@
#include "LinearSpec.h"
class BMessage;
namespace BALM {
class BALMLayout;
};
using BALM::BALMLayout;
namespace BPrivate {
@@ -32,13 +37,16 @@ public:
LinearSpec* Solver() const;
ResultType Result();
void RegisterLayout(BALM::BALMLayout* layout);
void LayoutLeaving(BALM::BALMLayout* layout);
void RegisterLayout(BALMLayout* layout);
void LayoutLeaving(const BALMLayout* layout);
ResultType ValidateMinSize();
ResultType ValidateMaxSize();
ResultType ValidatePreferredSize();
ResultType ValidateLayout(BLayoutContext* context);
status_t AddFriendReferences(const BALMLayout* layout,
BMessage* archive, const char* field);
private:
struct MinSizeValidator;
struct MaxSizeValidator;
+44
View File
@@ -58,6 +58,14 @@ TabBase::TabBase()
}
TabBase::TabBase(BMessage* archive)
:
BArchivable(BUnarchiver::PrepareArchive(archive))
{
BUnarchiver(archive).Finish(B_OK);
}
TabBase::~TabBase()
{
}
@@ -103,6 +111,15 @@ XTab::XTab(BALMLayout* layout)
}
XTab::XTab(BMessage* archive)
:
Variable(NULL),
TabBase(BUnarchiver::PrepareArchive(archive))
{
BUnarchiver(archive).Finish(B_OK);
}
XTab::~XTab()
{
TabBase::BALMLayoutList* layouts = fLayouts;
@@ -114,6 +131,15 @@ XTab::~XTab()
}
BArchivable*
XTab::Instantiate(BMessage* archive)
{
if (validate_instantiation(archive, "BALM::XTab"))
return new XTab(archive);
return NULL;
}
YTab::YTab(BALMLayout* layout)
:
Variable(layout->Solver())
@@ -122,6 +148,15 @@ YTab::YTab(BALMLayout* layout)
}
YTab::YTab(BMessage* archive)
:
Variable(NULL),
TabBase(BUnarchiver::PrepareArchive(archive))
{
BUnarchiver(archive).Finish(B_OK);
}
YTab::~YTab()
{
TabBase::BALMLayoutList* layouts = fLayouts;
@@ -131,3 +166,12 @@ YTab::~YTab()
}
delete fLayouts;
}
BArchivable*
YTab::Instantiate(BMessage* archive)
{
if (validate_instantiation(archive, "BALM::YTab"))
return new YTab(archive);
return NULL;
}