From a5f7275d768f5bf9f7fb100d12e10199b4efdd27 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Tue, 29 Jun 2004 12:20:32 +0000 Subject: [PATCH] Adding some more or less complete classes from Marc Flerackers (BDragger, BShelf and ZombieReplicantView). Not yet added to the build git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8231 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../private/interface/ZombieReplicantView.h | 54 + src/kits/interface/Dragger.cpp | 590 +++++++++++ src/kits/interface/Shelf.cpp | 968 ++++++++++++++++++ src/kits/interface/ZombieReplicantView.cpp | 108 ++ 4 files changed, 1720 insertions(+) create mode 100644 headers/private/interface/ZombieReplicantView.h create mode 100644 src/kits/interface/Dragger.cpp create mode 100644 src/kits/interface/Shelf.cpp create mode 100644 src/kits/interface/ZombieReplicantView.cpp diff --git a/headers/private/interface/ZombieReplicantView.h b/headers/private/interface/ZombieReplicantView.h new file mode 100644 index 0000000000..e7fdb33493 --- /dev/null +++ b/headers/private/interface/ZombieReplicantView.h @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2004, Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: ZombieReplicantView.h +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Class for Zombie replicants +//------------------------------------------------------------------------------ + +#ifndef _ZOMBIE_REPLICANT_VIEW_H +#define _ZOMBIE_REPLICANT_VIEW_H + +#include +#include + + +// _BZombieReplicantView_ class ------------------------------------------------ +class _BZombieReplicantView_ : public BBox { + +public: + _BZombieReplicantView_(BRect frame, status_t error); +virtual ~_BZombieReplicantView_(); + +virtual void MessageReceived(BMessage *msg); + +virtual void Draw(BRect updateRect); + +virtual void MouseDown(BPoint); + + void SetArchive(BMessage *); + +private: + status_t fError; + BMessage *fArchive; +}; + +#endif /* _ZOMBIE_REPLICANT_VIEW_H */ diff --git a/src/kits/interface/Dragger.cpp b/src/kits/interface/Dragger.cpp new file mode 100644 index 0000000000..16ce76c428 --- /dev/null +++ b/src/kits/interface/Dragger.cpp @@ -0,0 +1,590 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2004, Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: Dragger.cpp +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: BDragger represents a replicant "handle". +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- +bool BDragger::sVisible; +bool BDragger::sInited; +BLocker BDragger::sLock; +BList BDragger::sList; + +static rgb_color kZombieColor = {220, 220, 220, 255}; + +const unsigned char kHandBitmap[] = { 255, 255, 0, 0, 0, 255, 255, 255, + 255, 255, 0, 131, 131, 0, 255, 255, + 0, 0, 0, 0, 131, 131, 0, 0, + 0, 131, 0, 0, 131, 131, 0, 0, + 0, 131, 131, 131, 131, 131, 0, 0, + 255, 0, 131, 131, 131, 131, 0, 0, + 255, 255, 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 255, 255, 0, 0}; + + +BDragger::BDragger(BRect bounds, BView *target, uint32 rmask, uint32 flags) + : BView(bounds, "_dragger_", rmask, flags), + fTarget(target), + fRelation(TARGET_UNKNOWN), + fShelf(NULL), + fTransition(false), + fIsZombie(false), + fErrCount(0), + fPopUp(NULL) +{ + fBitmap = new BBitmap(BRect(0.0f, 0.0f, 7.0f, 7.0f), B_CMAP8, false, false); + fBitmap->SetBits(kHandBitmap, fBitmap->BitsLength(), 0, B_CMAP8); +} + + +BDragger::BDragger(BMessage *data) + : BView(data), + fTarget(NULL), + fRelation(TARGET_UNKNOWN), + fShelf(NULL), + fTransition(false), + fIsZombie(false), + fErrCount(0), + fPopUp(NULL) +{ + data->FindInt32("_rel", (int32*)&fRelation); + + fBitmap = new BBitmap(BRect(0.0f, 0.0f, 7.0f, 7.0f), B_CMAP8, false, false); + fBitmap->SetBits(kHandBitmap, fBitmap->BitsLength(), 0, B_CMAP8); + + BMessage popupMsg; + + if (data->FindMessage("_popup", &popupMsg) == B_OK) { + BArchivable *archivable = instantiate_object(&popupMsg); + + if (archivable) + fPopUp = dynamic_cast(archivable); + } +} + + +BDragger::~BDragger() +{ + SetPopUp(NULL); + + delete fBitmap; +} + + +BArchivable * +BDragger::Instantiate(BMessage *data) +{ + if (validate_instantiation(data, "BDragger")) + return new BDragger(data); + else + return NULL; +} + + +status_t +BDragger::Archive(BMessage *data, bool deep) const +{ + BMessage popupMsg; + + if (fPopUp) { + fPopUp->Archive(&popupMsg); + data->AddMessage("_popup", &popupMsg); + } + + data->AddInt32("_rel", fRelation); + + return BView::Archive(data, deep); +} + + +void +BDragger::AttachedToWindow() +{ + if (fIsZombie) { + SetLowColor(kZombieColor); + SetViewColor(kZombieColor); + + } else { + SetLowColor(B_TRANSPARENT_COLOR); + SetViewColor(B_TRANSPARENT_COLOR); + } + + determine_relationship(); + ListManage(true); +} + + +void +BDragger::DetachedFromWindow() +{ + ListManage(false); +} + + +void +BDragger::Draw(BRect update) +{ + BRect bounds(Bounds()); + + if (AreDraggersDrawn() && (!fShelf || fShelf->AllowsDragging())) { + SetDrawingMode(B_OP_OVER); + DrawBitmap(fBitmap, bounds.LeftTop()); + SetDrawingMode(B_OP_COPY); + + if (fIsZombie) { + // TODO: should draw it differently ? + } + } else if (IsVisibilityChanging()) { + if (Parent()) + Parent()->Invalidate(Frame()); + + else { + SetHighColor(255, 255, 255); + FillRect(bounds); + } + } +} + + +void +BDragger::MouseDown(BPoint where) +{ + if (!fTarget || !AreDraggersDrawn()) + return; + + int32 buttons; + + Window()->CurrentMessage()->FindInt32("buttons", &buttons); + + if (buttons & B_SECONDARY_MOUSE_BUTTON) { + if (!fShelf || !fTarget) { + beep(); + return; + } + + ShowPopUp(fTarget, where); + + } else { + // TODO code to determine drag or menu + /*bigtime_t time = system_time(); + bigtime_t click_speed = 0; + + get_click_speed(&click_speed);*/ + + bool drag = false; + + while (true) { + BPoint where2; + uint32 buttons; + + GetMouse(&where2, &buttons); + + if (!buttons) + break; + + if (where2 != where) { + drag = true; + break; + } + + snooze(40000); + } + + if (drag) { + BMessage archive(B_ARCHIVED_OBJECT); + + if (fRelation == TARGET_IS_PARENT) + fTarget->Archive(&archive); + else if (fRelation == TARGET_IS_CHILD) + Archive(&archive); + else { + if (fTarget->Archive(&archive)) { + BMessage widget(B_ARCHIVED_OBJECT); + + if (Archive(&widget)) + archive.AddMessage("__widget", &widget); + } + } + + archive.AddInt32("be:actions", B_TRASH_TARGET); + + BBitmap *bitmap; + BPoint offset; + drawing_mode mode; + + if (bitmap = DragBitmap(&offset, &mode)) + DragMessage(&archive, bitmap, mode, offset, this); + else + DragMessage(&archive, + ConvertFromScreen(fTarget->ConvertToScreen(fTarget->Bounds())), + this); + } else + ShowPopUp(fTarget, where); + } +} + + +void +BDragger::MouseUp(BPoint pt) +{ + BView::MouseUp(pt); +} + + +void +BDragger::MouseMoved(BPoint pt, uint32 code, const BMessage *msg) +{ + BView::MouseMoved(pt, code, msg); +} + + +void +BDragger::MessageReceived(BMessage *msg) +{ + if (msg->what == B_TRASH_TARGET) { + if(fShelf) + Window()->PostMessage(&BMessage('JAHA'), fTarget, NULL); + else + (new BAlert("??", + "Can't delete this replicant from its original application. Life goes on.", + "OK", NULL, NULL, B_WIDTH_FROM_WIDEST, B_WARNING_ALERT))->Go(NULL); + + } else if (msg->what == B_SCREEN_CHANGED) { + if (fRelation == TARGET_IS_CHILD) { + fTransition = true; + Draw(BRect()); + fTransition = false; + + } else { + if ((fShelf && (fShelf->AllowsDragging() && AreDraggersDrawn())) + || AreDraggersDrawn()) + Show(); + else + Hide(); + } + } else + BView::MessageReceived(msg); +} + + +void +BDragger::FrameMoved(BPoint new_position) +{ + BView::FrameMoved(new_position); +} + + +void +BDragger::FrameResized(float new_width, float new_height) +{ + BView::FrameResized(new_width, new_height); +} + + +status_t +BDragger::ShowAllDraggers() +{ + // TODO: Implement. Should ask the registrar or the app server + return B_OK; +} + + +status_t +BDragger::HideAllDraggers() +{ + // TODO: Implement. Should ask the registrar or the app server + return B_OK; +} + + +bool +BDragger::AreDraggersDrawn() +{ + // TODO: Implement. Should ask the registrar or the app server + return true; +} + + +BHandler *BDragger::ResolveSpecifier(BMessage *msg, int32 index, + BMessage *specifier, int32 form, + const char *property) +{ + return BView::ResolveSpecifier(msg, index, specifier, form, property); +} + + +status_t +BDragger::GetSupportedSuites(BMessage *data) +{ + return GetSupportedSuites(data); +} + + +status_t +BDragger::Perform(perform_code d, void *arg) +{ + return Perform(d, arg); +} + + +void +BDragger::ResizeToPreferred() +{ + BView::ResizeToPreferred(); +} + + +void +BDragger::GetPreferredSize(float *width, float *height) +{ + BView::GetPreferredSize(width, height); +} + + +void +BDragger::MakeFocus(bool state) +{ + BView::MakeFocus(state); +} + + +void +BDragger::AllAttached() +{ + BView::AllAttached(); +} + + +void +BDragger::AllDetached() +{ + BView::AllDetached(); +} + + +status_t +BDragger::SetPopUp(BPopUpMenu *context_menu) +{ + if (fPopUp && fPopUp != context_menu) + delete fPopUp; + + fPopUp = context_menu; + return B_OK; +} + + +BPopUpMenu * +BDragger::PopUp() const +{ + if (!fPopUp && fTarget) + const_cast(this)->BuildDefaultPopUp(); + + return fPopUp; +} + + +bool +BDragger::InShelf() const +{ + return fShelf != NULL; +} + + +BView * +BDragger::Target() const +{ + return fTarget; +} + + +BBitmap * +BDragger::DragBitmap(BPoint *offset, drawing_mode *mode) +{ + return NULL; +} + + +bool +BDragger::IsVisibilityChanging() const +{ + return fTransition; +} + + +void BDragger::_ReservedDragger2() {} +void BDragger::_ReservedDragger3() {} +void BDragger::_ReservedDragger4() {} + + +BDragger & +BDragger::operator=(const BDragger &) +{ + return *this; +} + + +void +BDragger::ListManage(bool add) +{ + if (sLock.Lock()) { + bool drawn = AreDraggersDrawn(); + + if (add) { + bool dragging = true; + + sList.AddItem(this); + + if (fShelf) + dragging = fShelf->AllowsDragging(); + + if (!drawn && !dragging) { + if (fRelation != TARGET_IS_CHILD) + Hide(); + } + } else + sList.RemoveItem(this); + + sLock.Unlock(); + } +} + + +status_t +BDragger::determine_relationship() +{ + status_t err = B_OK; + + if (fTarget) { + if (fTarget == Parent()) + fRelation = TARGET_IS_PARENT; + else if (fTarget == ChildAt(0)) + fRelation = TARGET_IS_CHILD; + else + fRelation = TARGET_IS_SIBLING; + } else { + if (fRelation == TARGET_IS_PARENT) + fTarget = Parent(); + else if (fRelation == TARGET_IS_CHILD) + fTarget = ChildAt(0); + else + err = B_ERROR; + } + + return err; +} + + +status_t +BDragger::SetViewToDrag(BView *target) +{ + if (target->Window() != Window()) + return B_ERROR; + + fTarget = target; + + if (Window()) + determine_relationship(); + + return B_OK; +} + + +void +BDragger::SetShelf(BShelf *shelf) +{ + fShelf = shelf; +} + + +void +BDragger::SetZombied(bool state) +{ + fIsZombie = state; + + SetLowColor(kZombieColor); + SetViewColor(kZombieColor); +} + + +void +BDragger::BuildDefaultPopUp() +{ + fPopUp = new BPopUpMenu("Shelf", false, false, B_ITEMS_IN_COLUMN); + + // About + BMessage *msg = new BMessage(B_ABOUT_REQUESTED); + + const char *name = fTarget->Name(); + + if (name) + msg->AddString("target", name); + + // TODO: Fix this + char *about = (char*)malloc(6 + (name ? strlen(name) : 0) + 1); + sprintf(about, "About %s", name); + + fPopUp->AddItem(new BMenuItem(about, msg)); + + free(about); + + // Seperator + fPopUp->AddItem(new BSeparatorItem()); + + // Delete + msg = new BMessage('JAHA'); + + fPopUp->AddItem(new BMenuItem("Delete", msg)); +} + + +void +BDragger::ShowPopUp(BView *target, BPoint where) +{ + BPoint point = ConvertToScreen(where); + + if (!fPopUp && fTarget) + BuildDefaultPopUp(); + + fPopUp->SetTargetForItems(fTarget); + + fPopUp->Go(point, true, false, /*BRect(), */true); +} diff --git a/src/kits/interface/Shelf.cpp b/src/kits/interface/Shelf.cpp new file mode 100644 index 0000000000..eaec840fc2 --- /dev/null +++ b/src/kits/interface/Shelf.cpp @@ -0,0 +1,968 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2004, Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: Shelf.cpp +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: BShelf stores replicant views that are dropped onto it +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +class _rep_data_ { + _rep_data_(BMessage *message, BView *view, BDragger *dragger, + BDragger::relation relation, unsigned long id, image_id image) + : + fMessage(message), + fView(view), + fDragger(NULL), + fRelation(relation), + fId(id), + fImage(image), + fError(B_OK), + fView2(NULL) + + { + } + + _rep_data_() + : + fMessage(NULL), + fView(NULL), + fDragger(NULL), + fRelation(BDragger::TARGET_UNKNOWN), + fId(0), + fError(B_ERROR), + fView2(NULL) + { + } + +static _rep_data_ *find(BList const *list, BMessage const *msg) + { + int32 i = 0; + _rep_data_ *item; + while (item = (_rep_data_*)list->ItemAt(i++)) { + if (item->fMessage == msg) + return item; + } + + return NULL; + } + +static _rep_data_ *find(BList const *list, BView const *view, bool aBool) + { + int32 i = 0; + _rep_data_ *item; + while (item = (_rep_data_*)list->ItemAt(i++)) { + if (item->fView == view) + return item; + + if (aBool && item->fView2 == view) + return item; + } + + return NULL; + } + +static _rep_data_ *find(BList const *list, unsigned long id) + { + int32 i = 0; + _rep_data_ *item; + while (item = (_rep_data_*)list->ItemAt(i++)) { + if (item->fId == id) + return item; + } + + return NULL; + } + +static int32 index_of(BList const *list, BMessage const *msg) + { + int32 i = 0; + _rep_data_ *item; + while (item = (_rep_data_*)list->ItemAt(i++)) { + if (item->fMessage == msg) + return i; + } + + return -1; + } + +static int32 index_of(BList const *list, BView const *view, bool aBool) + { + int32 i = 0; + _rep_data_ *item; + while (item = (_rep_data_*)list->ItemAt(i++)) { + if (item->fView == view) + return i; + + if (aBool && item->fView2 == view) + return i; + } + + return -1; + } + +static int32 index_of(BList const *list, unsigned long id) + { + int32 i = 0; + _rep_data_ *item; + while (item = (_rep_data_*)list->ItemAt(i++)) { + if (item->fId == id) + return i; + } + + return -1; + } + +friend class BShelf; + + BMessage *fMessage; + BView *fView; + BDragger *fDragger; + BDragger::relation fRelation; + unsigned long fId; + image_id fImage; + status_t fError; + BView *fView2; +}; + + +class _TContainerViewFilter_ : public BMessageFilter { +public: + _TContainerViewFilter_(BShelf *shelf, BView *view); +virtual ~_TContainerViewFilter_(); + + filter_result Filter(BMessage *msg, BHandler **handler); + filter_result ObjectDropFilter(BMessage *msg, BHandler **handler); + + BShelf *fShelf; + BView *fView; +}; + + +_TContainerViewFilter_::_TContainerViewFilter_(BShelf *shelf, BView *view) + : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE) +{ + fShelf = shelf; + fView = view; +} + + +_TContainerViewFilter_::~_TContainerViewFilter_() +{ +} + + +filter_result +_TContainerViewFilter_::Filter(BMessage *msg, BHandler **handler) +{ + filter_result filter = B_DISPATCH_MESSAGE; + + if (msg->what == B_ARCHIVED_OBJECT || + msg->what == B_ABOUT_REQUESTED) + return ObjectDropFilter(msg, handler); + + return filter; +} + + +filter_result +_TContainerViewFilter_::ObjectDropFilter(BMessage *msg, BHandler **_handler) +{ + BView *mouseView; + + if (*_handler) + mouseView = dynamic_cast(*_handler); + else + mouseView = NULL; + + if (msg->WasDropped()) { + if (!fShelf->fAllowDragging) { + printf("Dragging replicants isn't allowed to this shelf."); + beep(); + return B_SKIP_MESSAGE; + } + } + + BPoint point; + BPoint offset; + + if (msg->WasDropped()) { + point = msg->DropPoint(&offset); + + point = mouseView->ConvertFromScreen(point - offset); + } + + BHandler *handler; + BLooper *looper; + handler = msg->ReturnAddress().Target(&looper); + + BDragger *dragger; + + if (Looper() == looper) { + if (handler) + dragger = dynamic_cast(handler); + else + dragger = NULL; + + if (dragger->fRelation == BDragger::TARGET_IS_CHILD) { + BRect rect = dragger->Frame(); + rect.OffsetTo(point); + point = fShelf->AdjustReplicantBy(rect, msg); + + } else { + BRect rect = dragger->fTarget->Frame(); + rect.OffsetTo(point); + point = fShelf->AdjustReplicantBy(rect, msg); + } + + if (dragger->fRelation == BDragger::TARGET_IS_PARENT) + dragger->fTarget->MoveTo(point); + else if (dragger->fRelation == BDragger::TARGET_IS_CHILD) + dragger->MoveTo(point); + else { + //TODO: TARGET_UNKNOWN/TARGET_SIBLING + } + + } else { + if (fShelf->RealAddReplicant(msg, &point, 0) == B_OK) + Looper()->DetachCurrentMessage(); + } + + return B_SKIP_MESSAGE; +} + + +class _TReplicantViewFilter_ : public BMessageFilter { +public: + _TReplicantViewFilter_(BShelf *shelf, BView *view) + : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE) + { + fShelf = shelf; + fView = view; + } +virtual ~_TReplicantViewFilter_() + { + } + + filter_result Filter(BMessage *, BHandler **) + { + return B_DISPATCH_MESSAGE; + } + + BShelf *fShelf; + BView *fView; +}; + + +// **** BShelf **** +BShelf::BShelf(BView *view, bool allow_drags, const char *shelf_type) + : BHandler(shelf_type) +{ + InitData(NULL, NULL, view, allow_drags); +} + + +BShelf::BShelf(const entry_ref *ref, BView *view, bool allow_drags, + const char *shelf_type) + : BHandler(shelf_type) +{ + InitData(new BEntry(ref), NULL, view, allow_drags); +} + + +BShelf::BShelf(BDataIO *stream, BView *view, bool allow_drags, + const char *shelf_type) + : BHandler(shelf_type) +{ + InitData(NULL, stream, view, allow_drags); +} + + +BShelf::BShelf(BMessage *data) + : BHandler(data) +{ + // TODO: Implement ? +} + + +BShelf::~BShelf() +{ + Save(); + + delete fEntry; +} + + +status_t +BShelf::Archive(BMessage *data, bool deep) const +{ + return B_ERROR; +} + + +BArchivable * +BShelf::Instantiate(BMessage *data) +{ + return NULL; +} + + +void +BShelf::MessageReceived(BMessage *msg) +{ +} + + +status_t +BShelf::Save() +{ + //TODO + return B_ERROR; +} + + +void +BShelf::SetDirty(bool state) +{ + fDirty = state; +} + + +bool +BShelf::IsDirty() const +{ + return fDirty; +} + + +BHandler * +BShelf::ResolveSpecifier(BMessage *msg, int32 index, + BMessage *specifier, int32 form, + const char *property) +{ + //TODO + return NULL; +} + + +status_t +BShelf::GetSupportedSuites(BMessage *data) +{ + //TODO + return B_ERROR; +} + + +status_t +BShelf::Perform(perform_code d, void *arg) +{ + return BHandler::Perform(d, arg); +} + + +bool +BShelf::AllowsDragging() const +{ + return fAllowDragging; +} + + +void +BShelf::SetAllowsDragging(bool state) +{ + fAllowDragging = state; +} + + +bool +BShelf::AllowsZombies() const +{ + return fAllowZombies; +} + + +void +BShelf::SetAllowsZombies(bool state) +{ + fAllowZombies = state; +} + + +bool +BShelf::DisplaysZombies() const +{ + return fDisplayZombies; +} + + +void +BShelf::SetDisplaysZombies(bool state) +{ + fDisplayZombies = state; +} + + +bool +BShelf::IsTypeEnforced() const +{ + return fTypeEnforced; +} + + +void +BShelf::SetTypeEnforced(bool state) +{ + fTypeEnforced = state; +} + + +status_t +BShelf::SetSaveLocation(BDataIO *data_io) +{ + fDirty = true; + + if (fEntry) { + delete fEntry; + fEntry = NULL; + } + + fStream = data_io; + + return B_OK; +} + + +status_t +BShelf::SetSaveLocation(const entry_ref *ref) +{ + fDirty = true; + + if (fEntry) + delete fEntry; + else + fStream = NULL; + + fEntry = new BEntry(ref); + + return B_OK; +} + + +BDataIO * +BShelf::SaveLocation(entry_ref *ref) const +{ + entry_ref entry; + + if (fStream && ref) { + *ref = entry; + return fStream; + + } else if (fEntry) { + fEntry->GetRef(&entry); + + if (ref) + *ref = entry; + + return NULL; + + } else { + *ref = entry; + return NULL; + } +} + + +status_t +BShelf::AddReplicant(BMessage *data, BPoint location) +{ + return RealAddReplicant(data, &location, 0); +} + + +status_t +BShelf::DeleteReplicant(BView *replicant) +{ + int32 index = _rep_data_::index_of(&fReplicants, replicant, true); + + _rep_data_ *item = (_rep_data_*)fReplicants.ItemAt(index); + + if (!item) + return B_ERROR; + + bool aBool; + + item->fMessage->FindBool("", &aBool); + + BView *view = item->fView; + + if (!view) + view = item->fView2; + + if (view) + view->RemoveSelf(); + + if (item->fDragger) + item->fDragger->RemoveSelf(); + + fReplicants.RemoveItem(item); + + if (aBool && item->fImage >= 0) + unload_add_on(item->fImage); + + delete item; + + return B_OK; +} + + +status_t +BShelf::DeleteReplicant(BMessage *data) +{ + int32 index = _rep_data_::index_of(&fReplicants, data); + + _rep_data_ *item = (_rep_data_*)fReplicants.ItemAt(index); + + if (!item) + return B_ERROR; + + bool aBool; + + item->fMessage->FindBool("", &aBool); + + BView *view = item->fView; + + if (!view) + view = item->fView2; + + if (view) + view->RemoveSelf(); + + if (item->fDragger) + item->fDragger->RemoveSelf(); + + fReplicants.RemoveItem(item); + + if (aBool && item->fImage >= 0) + unload_add_on(item->fImage); + + delete item; + + return B_OK; +} + + +status_t +BShelf::DeleteReplicant(int32 index) +{ + _rep_data_ *item = (_rep_data_*)fReplicants.ItemAt(index); + + if (!item) + return B_ERROR; + + bool aBool; + + item->fMessage->FindBool("", &aBool); + + BView *view = item->fView; + + if (!view) + view = item->fView2; + + if (view) + view->RemoveSelf(); + + if (item->fDragger) + item->fDragger->RemoveSelf(); + + ReplicantDeleted(index, item->fMessage, item->fView); + + fReplicants.RemoveItem(item); + + if (aBool && item->fImage >= 0) + unload_add_on(item->fImage); + + delete item; + + return B_OK; +} + + +int32 +BShelf::CountReplicants() const +{ + return fReplicants.CountItems(); +} + + +BMessage * +BShelf::ReplicantAt(int32 index, BView **view, uint32 *uid, + status_t *perr) const +{ + status_t err = B_ERROR; + BMessage *message = NULL; + + _rep_data_ *item = (_rep_data_*)fReplicants.ItemAt(index); + + if (item) { + message = item->fMessage; + *view = item->fView; + *uid = item->fId; + *perr = item->fError; + + } else { + *view = NULL; + *uid = 0; + *perr = err; + } + + return message; +} + + +int32 +BShelf::IndexOf(const BView *replicant_view) const +{ + return _rep_data_::index_of(&fReplicants, replicant_view, false); +} + + +int32 +BShelf::IndexOf(const BMessage *archive) const +{ + return _rep_data_::index_of(&fReplicants, archive); +} + + +int32 +BShelf::IndexOf(uint32 id) const +{ + return _rep_data_::index_of(&fReplicants, id); +} + + +bool +BShelf::CanAcceptReplicantMessage(BMessage*) const +{ + return true; +} + + +bool +BShelf::CanAcceptReplicantView(BRect, BView*, BMessage*) const +{ + return true; +} + + +BPoint +BShelf::AdjustReplicantBy(BRect, BMessage*) const +{ + return B_ORIGIN; +} + + +void +BShelf::ReplicantDeleted(int32 index, const BMessage *archive, + const BView *replicant) +{ +} + + +void BShelf::_ReservedShelf2() {} +void BShelf::_ReservedShelf3() {} +void BShelf::_ReservedShelf4() {} +void BShelf::_ReservedShelf5() {} +#if !_PR3_COMPATIBLE_ +void BShelf::_ReservedShelf6() {} +void BShelf::_ReservedShelf7() {} +void BShelf::_ReservedShelf8() {} +#endif + + +BShelf::BShelf(const BShelf&) +{ +} + + +BShelf & +BShelf::operator=(const BShelf &) +{ + return *this; +} + + +status_t +BShelf::_Archive(BMessage *data) const +{ + BHandler::Archive(data); + + data->AddBool("_zom_dsp", DisplaysZombies()); + data->AddBool("_zom_alw", AllowsZombies()); + data->AddInt32("_sg_cnt", fGenCount); + + BMessage archive('ARCV'); + + // TODO archive replicants + + return B_ERROR; +} + + +void +BShelf::InitData(BEntry *entry, BDataIO *stream, BView *view, + bool allow_drags) +{ + fContainerView = view; + fStream = NULL; + fEntry = entry; + fFilter = NULL; + fGenCount = 1; + fAllowDragging = allow_drags; + fDirty = true; + fDisplayZombies = false; + fAllowZombies = true; + fTypeEnforced = false; + + if (entry) + fStream = new BFile(entry, B_READ_ONLY); + else + fStream = stream; + + fFilter = new _TContainerViewFilter_(this, fContainerView); + + fContainerView->AddFilter(fFilter); + fContainerView->set_shelf(this); + + if (fStream) { + BMessage archive; + + if (archive.Unflatten(fStream) == B_OK) { + bool aBool; + + if (!archive.FindBool("_zom_dsp", &aBool)) + aBool = false; + + SetDisplaysZombies(aBool); + + if (!archive.FindBool("_zom_alw", &aBool)) + aBool = true; + + SetAllowsZombies(aBool); + + int32 genCount; + + if (!archive.FindInt32("_sg_cnt", &genCount)) + genCount = 1; + + // TODO find archived replicants + } + } +} + + +status_t +BShelf::RealAddReplicant(BMessage *data, BPoint *loc, uint32 uid) +{ + BView *replicant = NULL; + BDragger *dragger = NULL; + BDragger::relation relation = BDragger::TARGET_UNKNOWN; + BMessage widget; + BMessage reply; + image_id image = B_ERROR; + image_id image2 = B_ERROR; + _BZombieReplicantView_ *zombie = NULL; + bool wasDropped = data->WasDropped(); + const char *shelf_type = NULL; + + data->FindString("shelf_type", &shelf_type); + + // Check shelf types if needed + if (fTypeEnforced) { + if (shelf_type) { + if (Name() && strcmp(shelf_type, Name()) != 0) { + printf("Replicant was rejected by BShelf: The BShelf's type and the Replicant's type don't match."); + return B_ERROR; + + } else { + printf("Replicant was rejected by BShelf: Replicant indicated a (%s), but the shelf does not.", shelf_type); + return B_ERROR; + } + + } else { + printf("Replicant was rejected by BShelf: Replicant did not have a "); + return B_ERROR; + } + } + + // Check if we can accept this message + if (!CanAcceptReplicantMessage(data)) + return B_ERROR; + + // Check if we can create multiple instances + if (data->FindBool("be:load_each_time")) { + const char *_class = NULL; + const char *add_on = NULL; + + if (data->FindString("class", &_class)) { + if (data->FindString("add_on", &add_on)) { + int32 i; + _rep_data_ *item; + const char *rep_class = NULL; + const char *rep_add_on = NULL; + + while (item = (_rep_data_*)fReplicants.ItemAt(i++)) { + item->fMessage->FindString("class", &rep_class); + item->fMessage->FindString("add_on", &rep_add_on); + + if (strcmp(_class, rep_class) == 0) { + if (add_on && rep_add_on && strcmp(_class, rep_class) == 0) + printf("Replicant was rejected. Unique replicant already exists. class=%s, signature=%s", + rep_class, rep_add_on); + } + } + } + } + } + + // Instantiate the object, if this fails we have a zombie + BArchivable *archivable = instantiate_object(data, &image); + + if (archivable) { + BView *view = dynamic_cast(archivable); + BPoint point; + + if (loc) + point = *loc; + else + point = view->Frame().LeftTop(); + + // Check if we have a dragger archived as "__widget" inside the message + if (data->FindMessage("__widget", &widget) == B_OK) { + BArchivable *archivable2 = instantiate_object(&widget, &image2); + + replicant = view; + + if (archivable2) { + if (dragger = dynamic_cast(archivable2)) { + // Replicant is either a sibling or unknown + dragger->SetViewToDrag(replicant); + } + } + } else { + // Replicant is child of the dragger + if (dragger = dynamic_cast(view)) + dragger->SetViewToDrag(replicant = dragger->ChildAt(0)); + else { + // Replicant is parent of the dragger + replicant = view; + dragger = dynamic_cast(replicant->FindView("_dragger_")); + + if (dragger) + dragger->SetViewToDrag(replicant); + } + } + + dragger->SetShelf(this); + + AddFilter(new _TReplicantViewFilter_(this, replicant)); + + fContainerView->AddChild(view); + + } else if (fDisplayZombies && fAllowZombies) { + BRect _frame; + + if (data->FindRect("_frame", &_frame) != B_OK) + _frame = BRect(); + + if (data->WasDropped()) { + BPoint dropPoint, offset; + dropPoint = data->DropPoint(&offset); + + _frame.OffsetTo(B_ORIGIN); + _frame.OffsetTo(fContainerView->ConvertFromScreen(dropPoint)-offset); + + zombie = new _BZombieReplicantView_(_frame, B_ERROR); + + _frame.OffsetTo(B_ORIGIN); + + BDragger *dragger = new BDragger(_frame, zombie); + + dragger->SetShelf(this); + dragger->SetZombied(true); + + zombie->AddChild(dragger); + + AddFilter(new _TReplicantViewFilter_(this, zombie)); + + fContainerView->AddChild(zombie); + } + } + + data->RemoveName("_drop_point_"); + data->RemoveName("_drop_offset_"); + + _rep_data_ *item = new _rep_data_(data, replicant, dragger, relation, uid, + image); + + item->fError = B_OK; + item->fView2 = zombie; + + if (zombie) + zombie->SetArchive(data); + + fReplicants.AddItem(item); + + if (data->IsSourceWaiting()) { + reply.AddInt32("id", uid); + reply.AddInt32("error", B_OK); + data->SendReply(&reply); + } + + //TODO: + + return B_ERROR; +} + + +status_t +BShelf::GetProperty(BMessage *msg, BMessage *reply) +{ + //TODO: Implement + return B_ERROR; +} diff --git a/src/kits/interface/ZombieReplicantView.cpp b/src/kits/interface/ZombieReplicantView.cpp new file mode 100644 index 0000000000..7c49c8dd18 --- /dev/null +++ b/src/kits/interface/ZombieReplicantView.cpp @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2004, Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: ZombieReplicantView.cpp +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Class for Zombie replicants +//------------------------------------------------------------------------------ + +#include +#include +#include + +#include + +#include + +const static rgb_color kZombieColor = {220, 220, 220, 255}; + +_BZombieReplicantView_::_BZombieReplicantView_(BRect frame, status_t error) + : BBox(frame, "", B_FOLLOW_NONE, B_WILL_DRAW) +{ + fError = error; + + BFont font(be_bold_font); + font.SetSize(9.0f); // TODO + SetFont(&font); + SetViewColor(kZombieColor); +} + + +_BZombieReplicantView_::~_BZombieReplicantView_() +{ +} + + +void +_BZombieReplicantView_::MessageReceived(BMessage *msg) +{ + switch (msg->what) { + case B_ABOUT_REQUESTED: + { + const char *add_on = NULL; + char description[B_MIME_TYPE_LENGTH]; + + if (fArchive->FindString("add_on", &add_on) == B_OK) { + BMimeType type(add_on); + type.GetShortDescription(description); + } + + char error[1024]; + + sprintf(error, "Can't create the \"%s\" replicant because the library is in the Trash. (%s)", + description, strerror(fError)); + + (new BAlert("Error", error, "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go(); + + break; + } + default: + BView::MessageReceived(msg); + } +} + + +void +_BZombieReplicantView_::Draw(BRect updateRect) +{ + BRect bounds(Bounds()); + font_height fh; + + GetFontHeight(&fh); + + DrawChar('?', BPoint(bounds.Width() / 2.0f - StringWidth("?") / 2.0f, + bounds.Height() / 2.0f - fh.ascent / 2.0f)); + + BBox::Draw(updateRect); +} + + +void +_BZombieReplicantView_::MouseDown(BPoint) +{ +} + + +void +_BZombieReplicantView_::SetArchive(BMessage *archive) +{ + fArchive = archive; +}