/* * Copyright 2006, 2023, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus * Zardshard */ #include "Icon.h" #include #include #include "PathSourceShape.h" #include "ReferenceImage.h" #include "Shape.h" #include "Style.h" #include "VectorPath.h" using std::nothrow; #ifdef ICON_O_MATIC IconListener::IconListener() {} IconListener::~IconListener() {} #endif // #pragma mark - Icon::Icon() : fStyles(true), fPaths(true), fShapes(true) #ifdef ICON_O_MATIC , fListeners(2) #endif { #ifdef ICON_O_MATIC fShapes.AddListener(this); #endif } Icon::Icon(const Icon& other) : fStyles(true), fPaths(true), fShapes(true) #ifdef ICON_O_MATIC , fListeners(2) #endif { #ifdef ICON_O_MATIC fShapes.AddListener(this); #endif int32 styleCount = other.fStyles.CountItems(); for (int32 i = 0; i < styleCount; i++) { Style* style = other.fStyles.ItemAtFast(i); Style* clone = new (nothrow) Style(*style); if (!clone || !fStyles.AddItem(clone)) { delete clone; return; } } int32 pathCount = other.fPaths.CountItems(); for (int32 i = 0; i < pathCount; i++) { VectorPath* path = other.fPaths.ItemAtFast(i); VectorPath* clone = new (nothrow) VectorPath(*path); if (!clone || !fPaths.AddItem(clone)) { delete clone; return; } } int32 shapeCount = other.fShapes.CountItems(); for (int32 i = 0; i < shapeCount; i++) { Shape* shape = other.fShapes.ItemAtFast(i); Shape* clone = shape->Clone(); if (!clone || !fShapes.AddItem(clone)) { delete clone; return; } // PathSourceShapes require further handling PathSourceShape* pathSourceShape = dynamic_cast(shape); PathSourceShape* pathSourceShapeClone = dynamic_cast(clone); if (pathSourceShape != NULL && pathSourceShapeClone != NULL) { // the cloned shape references styles and paths in // the "other" icon, replace them with "local" styles // and paths int32 styleIndex = other.fStyles.IndexOf(pathSourceShape->Style()); pathSourceShapeClone->SetStyle(fStyles.ItemAt(styleIndex)); pathSourceShapeClone->Paths()->MakeEmpty(); pathCount = pathSourceShape->Paths()->CountItems(); for (int32 j = 0; j < pathCount; j++) { VectorPath* remote = pathSourceShape->Paths()->ItemAtFast(j); int32 index = other.fPaths.IndexOf(remote); VectorPath* local = fPaths.ItemAt(index); if (!local) { printf("failed to match remote and " "local paths while cloning icon\n"); continue; } if (!pathSourceShapeClone->Paths()->AddItem(local)) { return; } } } } } Icon::~Icon() { fShapes.MakeEmpty(); #ifdef ICON_O_MATIC fShapes.RemoveListener(this); #endif } status_t Icon::InitCheck() const { return B_OK; } #ifdef ICON_O_MATIC void Icon::ItemAdded(Shape* shape, int32 index) { shape->AddObserver(this); _NotifyAreaInvalidated(shape->Bounds(true)); } void Icon::ItemRemoved(Shape* shape) { shape->RemoveObserver(this); _NotifyAreaInvalidated(shape->Bounds(true)); } void Icon::ObjectChanged(const Observable* object) { const Shape* shape = dynamic_cast(object); if (shape) { BRect area = shape->LastBounds(); area = area | shape->Bounds(true); area.InsetBy(-1, -1); _NotifyAreaInvalidated(area); } } bool Icon::AddListener(IconListener* listener) { if (listener && !fListeners.HasItem((void*)listener)) { if (fListeners.AddItem((void*)listener)) { listener->AreaInvalidated(BRect(0, 0, 63, 63)); return true; } } return false; } bool Icon::RemoveListener(IconListener* listener) { return fListeners.RemoveItem((void*)listener); } #endif // ICON_O_MATIC Icon* Icon::Clone() const { return new (nothrow) Icon(*this); } void Icon::MakeEmpty() { fShapes.MakeEmpty(); fPaths.MakeEmpty(); fStyles.MakeEmpty(); } // #pragma mark - #ifdef ICON_O_MATIC void Icon::_NotifyAreaInvalidated(const BRect& area) const { BList listeners(fListeners); int32 count = listeners.CountItems(); for (int32 i = 0; i < count; i++) { IconListener* listener = (IconListener*)listeners.ItemAtFast(i); listener->AreaInvalidated(area); } } #endif // ICON_O_MATIC