1 /* 2 * Copyright 2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "Icon.h" 10 11 #include <new> 12 #include <stdio.h> 13 14 #include "PathContainer.h" 15 #include "Shape.h" 16 #include "Style.h" 17 #include "StyleContainer.h" 18 19 using std::nothrow; 20 21 #ifdef ICON_O_MATIC 22 IconListener::IconListener() {} 23 IconListener::~IconListener() {} 24 #endif 25 26 // #pragma mark - 27 28 // constructor 29 Icon::Icon() 30 : fStyles(new (nothrow) StyleContainer()), 31 fPaths(new (nothrow) PathContainer(true)), 32 fShapes(new (nothrow) ShapeContainer()) 33 #ifdef ICON_O_MATIC 34 , fListeners(2) 35 #endif 36 { 37 #ifdef ICON_O_MATIC 38 if (fShapes) 39 fShapes->AddListener(this); 40 #endif 41 } 42 43 // constructor 44 Icon::Icon(const Icon& other) 45 : fStyles(new (nothrow) StyleContainer()), 46 fPaths(new (nothrow) PathContainer(true)), 47 fShapes(new (nothrow) ShapeContainer()) 48 #ifdef ICON_O_MATIC 49 , fListeners(2) 50 #endif 51 { 52 if (!fStyles || !fPaths || !fShapes) 53 return; 54 55 #ifdef ICON_O_MATIC 56 fShapes->AddListener(this); 57 #endif 58 59 int32 styleCount = other.fStyles->CountStyles(); 60 for (int32 i = 0; i < styleCount; i++) { 61 Style* style = other.fStyles->StyleAtFast(i); 62 Style* clone = new (nothrow) Style(*style); 63 if (!clone || !fStyles->AddStyle(clone)) { 64 delete clone; 65 return; 66 } 67 } 68 69 int32 pathCount = other.fPaths->CountPaths(); 70 for (int32 i = 0; i < pathCount; i++) { 71 VectorPath* path = other.fPaths->PathAtFast(i); 72 VectorPath* clone = new (nothrow) VectorPath(*path); 73 if (!clone || !fPaths->AddPath(clone)) { 74 delete clone; 75 return; 76 } 77 } 78 79 int32 shapeCount = other.fShapes->CountShapes(); 80 for (int32 i = 0; i < shapeCount; i++) { 81 Shape* shape = other.fShapes->ShapeAtFast(i); 82 Shape* clone = new (nothrow) Shape(*shape); 83 if (!clone || !fShapes->AddShape(clone)) { 84 delete clone; 85 return; 86 } 87 // the cloned shape references styles and paths in 88 // the "other" icon, replace them with "local" styles 89 // and paths 90 int32 styleIndex = other.fStyles->IndexOf(shape->Style()); 91 clone->SetStyle(fStyles->StyleAt(styleIndex)); 92 93 clone->Paths()->MakeEmpty(); 94 pathCount = shape->Paths()->CountPaths(); 95 for (int32 j = 0; j < pathCount; j++) { 96 VectorPath* remote = shape->Paths()->PathAtFast(j); 97 int32 index = other.fPaths->IndexOf(remote); 98 VectorPath* local = fPaths->PathAt(index); 99 if (!local) { 100 printf("failed to match remote and " 101 "local paths while cloning icon\n"); 102 continue; 103 } 104 if (!clone->Paths()->AddPath(local)) { 105 return; 106 } 107 } 108 } 109 } 110 111 // destructor 112 Icon::~Icon() 113 { 114 if (fShapes) { 115 fShapes->MakeEmpty(); 116 #ifdef ICON_O_MATIC 117 fShapes->RemoveListener(this); 118 #endif 119 delete fShapes; 120 } 121 delete fPaths; 122 delete fStyles; 123 } 124 125 // InitCheck 126 status_t 127 Icon::InitCheck() const 128 { 129 return fStyles && fPaths && fShapes ? B_OK : B_NO_MEMORY; 130 } 131 132 #ifdef ICON_O_MATIC 133 // ShapeAdded 134 void 135 Icon::ShapeAdded(Shape* shape, int32 index) 136 { 137 shape->AddObserver(this); 138 _NotifyAreaInvalidated(shape->Bounds(true)); 139 } 140 141 // ShapeRemoved 142 void 143 Icon::ShapeRemoved(Shape* shape) 144 { 145 shape->RemoveObserver(this); 146 _NotifyAreaInvalidated(shape->Bounds(true)); 147 } 148 149 // ObjectChanged 150 void 151 Icon::ObjectChanged(const Observable* object) 152 { 153 const Shape* shape = dynamic_cast<const Shape*>(object); 154 if (shape) { 155 BRect area = shape->LastBounds(); 156 area = area | shape->Bounds(true); 157 area.InsetBy(-1, -1); 158 _NotifyAreaInvalidated(area); 159 } 160 } 161 162 // AddListener 163 bool 164 Icon::AddListener(IconListener* listener) 165 { 166 if (listener && !fListeners.HasItem((void*)listener)) { 167 if (fListeners.AddItem((void*)listener)) { 168 listener->AreaInvalidated(BRect(0, 0, 63, 63)); 169 return true; 170 } 171 } 172 return false; 173 } 174 175 // RemoveListener 176 bool 177 Icon::RemoveListener(IconListener* listener) 178 { 179 return fListeners.RemoveItem((void*)listener); 180 } 181 #endif // ICON_O_MATIC 182 183 184 // Clone 185 Icon* 186 Icon::Clone() const 187 { 188 return new (nothrow) Icon(*this); 189 } 190 191 // MakeEmpty 192 void 193 Icon::MakeEmpty() 194 { 195 fShapes->MakeEmpty(); 196 fPaths->MakeEmpty(); 197 fStyles->MakeEmpty(); 198 } 199 200 // #pragma mark - 201 202 #ifdef ICON_O_MATIC 203 // _NotifyAreaInvalidated 204 void 205 Icon::_NotifyAreaInvalidated(const BRect& area) const 206 { 207 BList listeners(fListeners); 208 int32 count = listeners.CountItems(); 209 for (int32 i = 0; i < count; i++) { 210 IconListener* listener 211 = (IconListener*)listeners.ItemAtFast(i); 212 listener->AreaInvalidated(area); 213 } 214 } 215 #endif // ICON_O_MATIC 216 217 218