From 7a37b89be9f81088d05ea085a099816ec16e7095 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Tue, 27 Jul 2010 20:59:47 +0000 Subject: [PATCH] Updated BMenuField and its custom BLayoutItems for layout-safe archiving. Added an _InitMenu(const BMessage*) method that inits the menu during unarchival. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37778 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/MenuField.h | 3 + src/kits/interface/MenuField.cpp | 236 +++++++++++++++++++++++++++---- 2 files changed, 214 insertions(+), 25 deletions(-) diff --git a/headers/os/interface/MenuField.h b/headers/os/interface/MenuField.h index e8f92ab1c6..5abf0247b5 100644 --- a/headers/os/interface/MenuField.h +++ b/headers/os/interface/MenuField.h @@ -35,6 +35,8 @@ public: static BArchivable* Instantiate(BMessage* archive); virtual status_t Archive(BMessage* archive, bool deep = true) const; + virtual status_t AllArchived(BMessage* into) const; + virtual status_t AllUnarchived(const BMessage* from); virtual void Draw(BRect update); virtual void AttachedToWindow(); @@ -122,6 +124,7 @@ private: void _UpdateFrame(); void _InitMenuBar(BMenu* menu, BRect frame, bool fixedSize); + void _InitMenuBar(const BMessage* archive); void _ValidateLayoutData(); float _MenuBarOffset() const; diff --git a/src/kits/interface/MenuField.cpp b/src/kits/interface/MenuField.cpp index dffbb17002..dfb19b3c49 100644 --- a/src/kits/interface/MenuField.cpp +++ b/src/kits/interface/MenuField.cpp @@ -23,6 +23,7 @@ #include #include +#include //#define TRACE_MENU_FIELD @@ -40,9 +41,17 @@ #endif +namespace { + const char* const kFrameField = "BMenuField:layoutItem:frame"; + const char* const kMenuBarItemField = "BMenuField:barItem"; + const char* const kLabelItemField = "BMenuField:labelItem"; +} + + class BMenuField::LabelLayoutItem : public BAbstractLayoutItem { public: LabelLayoutItem(BMenuField* parent); + LabelLayoutItem(BMessage* archive); virtual bool IsVisible(); virtual void SetVisible(bool visible); @@ -50,6 +59,7 @@ public: virtual BRect Frame(); virtual void SetFrame(BRect frame); + void SetParent(BMenuField* parent); virtual BView* View(); virtual BSize BaseMinSize(); @@ -57,6 +67,9 @@ public: virtual BSize BasePreferredSize(); virtual BAlignment BaseAlignment(); + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* from); + private: BMenuField* fParent; BRect fFrame; @@ -66,6 +79,7 @@ private: class BMenuField::MenuBarLayoutItem : public BAbstractLayoutItem { public: MenuBarLayoutItem(BMenuField* parent); + MenuBarLayoutItem(BMessage* from); virtual bool IsVisible(); virtual void SetVisible(bool visible); @@ -73,6 +87,7 @@ public: virtual BRect Frame(); virtual void SetFrame(BRect frame); + void SetParent(BMenuField* parent); virtual BView* View(); virtual BSize BaseMinSize(); @@ -80,6 +95,9 @@ public: virtual BSize BasePreferredSize(); virtual BAlignment BaseAlignment(); + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* from); + private: BMenuField* fParent; BRect fFrame; @@ -176,38 +194,23 @@ BMenuField::BMenuField(const char* label, BMenu* menu, BMessage* message) BMenuField::BMenuField(BMessage* data) : - BView(data) + BView(BUnarchiver::PrepareArchive(data)) { + BUnarchiver unarchiver(data); const char* label = NULL; data->FindString("_label", &label); InitObject(label); - fMenuBar = (BMenuBar*)FindView("_mc_mb_"); - if (!fMenuBar) - _InitMenuBar(new BMenu(""), BRect(0, 0, 100, 15), false); - fMenu = fMenuBar->SubmenuAt(0); - - InitObject2(); - - bool disable; - if (data->FindBool("_disable", &disable) == B_OK) - SetEnabled(!disable); - - int32 align; - data->FindInt32("_align", &align); - SetAlignment((alignment)align); - data->FindFloat("_divide", &fDivider); - bool fixed; - if (data->FindBool("be:fixeds", &fixed) == B_OK) - fFixedSizeMB = fixed; - - bool dmark = false; - data->FindBool("be:dmark", &dmark); - if (_BMCMenuBar_* menuBar = dynamic_cast<_BMCMenuBar_*>(fMenuBar)) - menuBar->TogglePopUpMarker(dmark); + int32 align; + if (data->FindInt32("_align", &align) == B_OK) + SetAlignment((alignment)align); + + if (!BUnarchiver::IsArchiveManaged(data)) + _InitMenuBar(data); + unarchiver.Finish(); } @@ -236,6 +239,7 @@ BMenuField::Instantiate(BMessage* data) status_t BMenuField::Archive(BMessage* data, bool deep) const { + BArchiver archiver(data); status_t ret = BView::Archive(data, deep); if (ret == B_OK && Label()) @@ -258,7 +262,66 @@ BMenuField::Archive(BMessage* data, bool deep) const data->AddBool("be:dmark", dmark); - return ret; + return archiver.Finish(ret); +} + + +status_t +BMenuField::AllArchived(BMessage* into) const +{ + status_t err; + if ((err = BView::AllArchived(into)) != B_OK) + return err; + + BArchiver archiver(into); + + BArchivable* menuBarItem = fLayoutData->menu_bar_layout_item; + if (archiver.IsArchived(menuBarItem)) + err = archiver.AddArchivable(kMenuBarItemField, menuBarItem); + + if (err != B_OK) + return err; + + BArchivable* labelBarItem = fLayoutData->label_layout_item; + if (archiver.IsArchived(labelBarItem)) + err = archiver.AddArchivable(kLabelItemField, labelBarItem); + + return err; +} + + +status_t +BMenuField::AllUnarchived(const BMessage* from) +{ + BUnarchiver unarchiver(from); + + status_t err = B_OK; + if ((err = BView::AllUnarchived(from)) != B_OK) + return err; + + _InitMenuBar(from); + + if (unarchiver.IsInstantiated(kMenuBarItemField)) { + MenuBarLayoutItem*& menuItem = fLayoutData->menu_bar_layout_item; + err = unarchiver.FindObject(kMenuBarItemField, + BUnarchiver::B_DONT_ASSUME_OWNERSHIP, menuItem); + + if (err == B_OK) + menuItem->SetParent(this); + else + return err; + } + + if (unarchiver.IsInstantiated(kLabelItemField)) { + LabelLayoutItem*& labelItem = fLayoutData->label_layout_item; + err = unarchiver.FindObject(kLabelItemField, + BUnarchiver::B_DONT_ASSUME_OWNERSHIP, labelItem); + + if (err == B_OK) + labelItem->SetParent(this); + } + + return err; } @@ -794,6 +857,22 @@ BMenuField::Perform(perform_code code, void* _data) BMenuField::DoLayout(); return B_OK; } + case PERFORM_CODE_ALL_UNARCHIVED: + { + perform_data_all_unarchived* data + = (perform_data_all_unarchived*)_data; + + data->return_value = BMenuField::AllUnarchived(data->archive); + return B_OK; + } + case PERFORM_CODE_ALL_ARCHIVED: + { + perform_data_all_archived* data + = (perform_data_all_archived*)_data; + + data->return_value = BMenuField::AllArchived(data->archive); + return B_OK; + } } return BView::Perform(code, _data); @@ -1062,6 +1141,35 @@ BMenuField::_InitMenuBar(BMenu* menu, BRect frame, bool fixedSize) } +void +BMenuField::_InitMenuBar(const BMessage* archive) +{ + bool fixed; + if (archive->FindBool("be:fixeds", &fixed) == B_OK) + fFixedSizeMB = fixed; + + fMenuBar = (BMenuBar*)FindView("_mc_mb_"); + if (!fMenuBar) { + _InitMenuBar(new BMenu(""), BRect(0, 0, 100, 15), fFixedSizeMB); + InitObject2(); + } else { + fMenuBar->AddFilter(new _BMCFilter_(this, B_MOUSE_DOWN)); + // this is normally done in InitObject2() + } + + fMenu = fMenuBar->SubmenuAt(0); + + bool disable; + if (archive->FindBool("_disable", &disable) == B_OK) + SetEnabled(!disable); + + bool dmark = false; + archive->FindBool("be:dmark", &dmark); + if (_BMCMenuBar_* menuBar = dynamic_cast<_BMCMenuBar_*>(fMenuBar)) + menuBar->TogglePopUpMarker(dmark); +} + + void BMenuField::_ValidateLayoutData() { @@ -1144,6 +1252,16 @@ BMenuField::LabelLayoutItem::LabelLayoutItem(BMenuField* parent) } +BMenuField::LabelLayoutItem::LabelLayoutItem(BMessage* from) + : + BAbstractLayoutItem(from), + fParent(NULL), + fFrame() +{ + from->FindRect(kFrameField, &fFrame); +} + + bool BMenuField::LabelLayoutItem::IsVisible() { @@ -1173,6 +1291,13 @@ BMenuField::LabelLayoutItem::SetFrame(BRect frame) } +void +BMenuField::LabelLayoutItem::SetParent(BMenuField* parent) +{ + fParent = parent; +} + + BView* BMenuField::LabelLayoutItem::View() { @@ -1214,6 +1339,28 @@ BMenuField::LabelLayoutItem::BaseAlignment() } +status_t +BMenuField::LabelLayoutItem::Archive(BMessage* into, bool deep) const +{ + BArchiver archiver(into); + status_t err = BAbstractLayoutItem::Archive(into, deep); + + if (err == B_OK) + err = into->AddRect(kFrameField, fFrame); + + return archiver.Finish(err); +} + + +BArchivable* +BMenuField::LabelLayoutItem::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "BMenuField::LabelLayoutItem")) + return new LabelLayoutItem(from); + return NULL; +} + + // #pragma mark - @@ -1228,6 +1375,16 @@ BMenuField::MenuBarLayoutItem::MenuBarLayoutItem(BMenuField* parent) } +BMenuField::MenuBarLayoutItem::MenuBarLayoutItem(BMessage* from) + : + BAbstractLayoutItem(from), + fParent(NULL), + fFrame() +{ + from->FindRect(kFrameField, &fFrame); +} + + bool BMenuField::MenuBarLayoutItem::IsVisible() { @@ -1257,6 +1414,13 @@ BMenuField::MenuBarLayoutItem::SetFrame(BRect frame) } +void +BMenuField::MenuBarLayoutItem::SetParent(BMenuField* parent) +{ + fParent = parent; +} + + BView* BMenuField::MenuBarLayoutItem::View() { @@ -1299,3 +1463,25 @@ BMenuField::MenuBarLayoutItem::BaseAlignment() return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); } + +status_t +BMenuField::MenuBarLayoutItem::Archive(BMessage* into, bool deep) const +{ + BArchiver archiver(into); + status_t err = BAbstractLayoutItem::Archive(into, deep); + + if (err == B_OK) + err = into->AddRect(kFrameField, fFrame); + + return archiver.Finish(err); +} + + +BArchivable* +BMenuField::MenuBarLayoutItem::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "BMenuField::MenuBarLayoutItem")) + return new MenuBarLayoutItem(from); + return NULL; +} +