/* * Copyright 2010, Haiku, Inc. * All rights reserved. Distributed under the terms of the MIT License. */ #include #include #include #include #include namespace { const char* const kSizesField = "BAbstractLayout:sizes"; // kSizesField == {min, max, preferred} const char* const kAlignmentField = "BAbstractLayout:alignment"; const char* const kFrameField = "BAbstractLayout:frame"; const char* const kVisibleField = "BAbstractLayout:visible"; enum proxy_type { VIEW_PROXY_TYPE, DATA_PROXY_TYPE }; } struct BAbstractLayout::Proxy { Proxy(proxy_type type) : type(type) { } virtual ~Proxy() { } virtual BSize MinSize() const = 0; virtual void SetMinSize(const BSize&) = 0; virtual BSize MaxSize() const = 0; virtual void SetMaxSize(const BSize&) = 0; virtual BSize PreferredSize() const = 0; virtual void SetPreferredSize(const BSize&) = 0; virtual BAlignment Alignment() const = 0; virtual void SetAlignment(const BAlignment&) = 0; virtual BRect Frame() const = 0; virtual void SetFrame(const BRect& frame) = 0; virtual bool IsVisible(bool ancestorHidden) const = 0; virtual void SetVisible(bool visible) = 0; virtual status_t AddDataToArchive(BMessage* archive, bool ancestorHidden) = 0; virtual status_t RestoreDataFromArchive(const BMessage* archive) = 0; proxy_type type; }; struct BAbstractLayout::DataProxy : Proxy { DataProxy() : Proxy(DATA_PROXY_TYPE), minSize(), maxSize(), preferredSize(), alignment(), frame(-1, -1, 0, 0), visible(true) { } BSize MinSize() const { return minSize; } void SetMinSize(const BSize& min) { minSize = min; } BSize MaxSize() const { return maxSize; } void SetMaxSize(const BSize& max) { maxSize = max; } BSize PreferredSize() const { return preferredSize; } void SetPreferredSize(const BSize& preferred) { preferredSize = preferred; } BAlignment Alignment() const { return this->alignment; } void SetAlignment(const BAlignment& align) { this->alignment = align; } BRect Frame() const { return frame; } void SetFrame(const BRect& frame) { if (frame == this->frame) return; this->frame = frame; } bool IsVisible(bool) const { return visible; } void SetVisible(bool visible) { this->visible = visible; } status_t AddDataToArchive(BMessage* archive, bool ancestorHidden) { status_t err = archive->AddSize(kSizesField, minSize); if (err == B_OK) err = archive->AddSize(kSizesField, maxSize); if (err == B_OK) err = archive->AddSize(kSizesField, preferredSize); if (err == B_OK) err = archive->AddAlignment(kAlignmentField, alignment); if (err == B_OK) err = archive->AddRect(kFrameField, frame); if (err == B_OK) err = archive->AddBool(kVisibleField, visible); return err; } status_t RestoreDataFromArchive(const BMessage* archive) { status_t err = archive->FindSize(kSizesField, 0, &minSize); if (err == B_OK) err = archive->FindSize(kSizesField, 1, &maxSize); if (err == B_OK) err = archive->FindSize(kSizesField, 2, &preferredSize); if (err == B_OK) err = archive->FindAlignment(kAlignmentField, &alignment); if (err == B_OK) err = archive->FindRect(kFrameField, &frame); if (err == B_OK) err = archive->FindBool(kVisibleField, &visible); return err; } BSize minSize; BSize maxSize; BSize preferredSize; BAlignment alignment; BRect frame; bool visible; }; struct BAbstractLayout::ViewProxy : Proxy { ViewProxy(BView* target) : Proxy(VIEW_PROXY_TYPE), view(target) { } BSize MinSize() const { return view->ExplicitMinSize(); } void SetMinSize(const BSize& min) { view->SetExplicitMinSize(min); } BSize MaxSize() const { return view->ExplicitMaxSize(); } void SetMaxSize(const BSize& min) { view->SetExplicitMaxSize(min); } BSize PreferredSize() const { return view->ExplicitPreferredSize(); } void SetPreferredSize(const BSize& preferred) { view->SetExplicitPreferredSize(preferred); } BAlignment Alignment() const { return view->ExplicitAlignment(); } void SetAlignment(const BAlignment& alignment) { view->SetExplicitAlignment(alignment); } BRect Frame() const { return view->Frame(); } void SetFrame(const BRect& frame) { view->MoveTo(frame.LeftTop()); view->ResizeTo(frame.Width(), frame.Height()); } bool IsVisible(bool ancestorsVisible) const { int16 showLevel = BView::Private(view).ShowLevel(); return (showLevel - (ancestorsVisible) ? 0 : 1) <= 0; } void SetVisible(bool visible) { // No need to check that we are not re-hiding, that is done // for us. if (visible) view->Show(); else view->Hide(); } status_t AddDataToArchive(BMessage* archive, bool ancestorHidden) { return B_OK; } status_t RestoreDataFromArchive(const BMessage* archive) { return B_OK; } BView* view; }; BAbstractLayout::BAbstractLayout() : fExplicitData(new BAbstractLayout::DataProxy()) { } BAbstractLayout::BAbstractLayout(BMessage* from) : BLayout(BUnarchiver::PrepareArchive(from)), fExplicitData(new DataProxy()) { BUnarchiver(from).Finish(); } BAbstractLayout::~BAbstractLayout() { delete fExplicitData; } BSize BAbstractLayout::MinSize() { return BLayoutUtils::ComposeSize(fExplicitData->MinSize(), BaseMinSize()); } BSize BAbstractLayout::MaxSize() { return BLayoutUtils::ComposeSize(fExplicitData->MaxSize(), BaseMaxSize()); } BSize BAbstractLayout::PreferredSize() { return BLayoutUtils::ComposeSize(fExplicitData->PreferredSize(), BasePreferredSize()); } BAlignment BAbstractLayout::Alignment() { return BLayoutUtils::ComposeAlignment(fExplicitData->Alignment(), BaseAlignment()); } void BAbstractLayout::SetExplicitMinSize(BSize size) { fExplicitData->SetMinSize(size); } void BAbstractLayout::SetExplicitMaxSize(BSize size) { fExplicitData->SetMaxSize(size); } void BAbstractLayout::SetExplicitPreferredSize(BSize size) { fExplicitData->SetPreferredSize(size); } void BAbstractLayout::SetExplicitAlignment(BAlignment alignment) { fExplicitData->SetAlignment(alignment); } BSize BAbstractLayout::BaseMinSize() { return BSize(0, 0); } BSize BAbstractLayout::BaseMaxSize() { return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); } BSize BAbstractLayout::BasePreferredSize() { return BSize(0, 0); } BAlignment BAbstractLayout::BaseAlignment() { return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); } BRect BAbstractLayout::Frame() { return fExplicitData->Frame(); } void BAbstractLayout::SetFrame(BRect frame) { if (frame != fExplicitData->Frame()) { fExplicitData->SetFrame(frame); if (!Owner()) Relayout(); } } bool BAbstractLayout::IsVisible() { return fExplicitData->IsVisible(AncestorsVisible()); } void BAbstractLayout::SetVisible(bool visible) { if (visible != fExplicitData->IsVisible(AncestorsVisible())) { fExplicitData->SetVisible(visible); if (Layout()) Layout()->InvalidateLayout(false); VisibilityChanged(visible); } } status_t BAbstractLayout::Archive(BMessage* into, bool deep) const { BArchiver archiver(into); status_t err = BLayout::Archive(into, deep); return archiver.Finish(err); } status_t BAbstractLayout::AllArchived(BMessage* archive) const { return BLayout::AllArchived(archive); } status_t BAbstractLayout::AllUnarchived(const BMessage* from) { status_t err = fExplicitData->RestoreDataFromArchive(from); if (err != B_OK) return err; return BLayout::AllUnarchived(from); } status_t BAbstractLayout::ItemArchived(BMessage* into, BLayoutItem* item, int32 index) const { return BLayout::ItemArchived(into, item, index); } status_t BAbstractLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item, int32 index) { return BLayout::ItemUnarchived(from, item, index); } bool BAbstractLayout::ItemAdded(BLayoutItem* item, int32 atIndex) { return BLayout::ItemAdded(item, atIndex); } void BAbstractLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex) { BLayout::ItemRemoved(item, fromIndex); } void BAbstractLayout::LayoutInvalidated(bool children) { BLayout::LayoutInvalidated(children); } void BAbstractLayout::OwnerChanged(BView* was) { if (was) { static_cast(fExplicitData)->view = Owner(); return; } delete fExplicitData; fExplicitData = new ViewProxy(Owner()); } void BAbstractLayout::AttachedToLayout() { BLayout::AttachedToLayout(); } void BAbstractLayout::DetachedFromLayout(BLayout* layout) { BLayout::DetachedFromLayout(layout); } void BAbstractLayout::AncestorVisibilityChanged(bool shown) { if (AncestorsVisible() == shown) return; if (BView* owner = Owner()) { if (shown) owner->Show(); else owner->Hide(); } BLayout::AncestorVisibilityChanged(shown); } // Binary compatibility stuff status_t BAbstractLayout::Perform(perform_code code, void* _data) { return BLayout::Perform(code, _data); } void BAbstractLayout::_ReservedAbstractLayout1() {} void BAbstractLayout::_ReservedAbstractLayout2() {} void BAbstractLayout::_ReservedAbstractLayout3() {} void BAbstractLayout::_ReservedAbstractLayout4() {} void BAbstractLayout::_ReservedAbstractLayout5() {} void BAbstractLayout::_ReservedAbstractLayout6() {} void BAbstractLayout::_ReservedAbstractLayout7() {} void BAbstractLayout::_ReservedAbstractLayout8() {} void BAbstractLayout::_ReservedAbstractLayout9() {} void BAbstractLayout::_ReservedAbstractLayout10() {}