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 "TransformShapesBox.h" 10 11 #include <new> 12 #include <stdio.h> 13 #include <string.h> 14 15 #include "Shape.h" 16 #include "StateView.h" 17 #include "TransformObjectsCommand.h" 18 19 using std::nothrow; 20 21 // constructor 22 TransformShapesBox::TransformShapesBox(CanvasView* view, 23 const Shape** shapes, 24 int32 count) 25 : CanvasTransformBox(view), 26 27 fShapes(shapes && count > 0 ? new Shape*[count] : NULL), 28 fCount(count), 29 30 fOriginals(NULL), 31 32 fParentTransform() 33 { 34 if (fShapes) { 35 // allocate storage for the current transformations 36 // of each object 37 fOriginals = new double[fCount * Transformable::matrix_size]; 38 39 memcpy(fShapes, shapes, fCount * sizeof(Shape*)); 40 41 for (int32 i = 0; i < fCount; i++) { 42 if (fShapes[i]) 43 fShapes[i]->AddObserver(this); 44 } 45 46 // trigger init 47 ObjectChanged(fShapes[0]); 48 } else { 49 SetBox(BRect(0, 0, -1, -1)); 50 } 51 } 52 53 // destructor 54 TransformShapesBox::~TransformShapesBox() 55 { 56 if (fShapes) { 57 for (int32 i = 0; i < fCount; i++) { 58 if (fShapes[i]) 59 fShapes[i]->RemoveObserver(this); 60 } 61 delete[] fShapes; 62 } 63 64 delete[] fOriginals; 65 } 66 67 // Update 68 void 69 TransformShapesBox::Update(bool deep) 70 { 71 BRect r = Bounds(); 72 73 TransformBox::Update(deep); 74 75 BRect dirty(r | Bounds()); 76 dirty.InsetBy(-8, -8); 77 fView->Invalidate(dirty); 78 79 if (!deep || !fShapes) 80 return; 81 82 for (int32 i = 0; i < fCount; i++) { 83 if (!fShapes[i]) 84 continue; 85 86 fShapes[i]->RemoveObserver(this); 87 fShapes[i]->SuspendNotifications(true); 88 89 // reset the objects transformation to the saved state 90 fShapes[i]->LoadFrom(&fOriginals[i * Transformable::matrix_size]); 91 // combined with the current transformation 92 fShapes[i]->Multiply(*this); 93 94 fShapes[i]->SuspendNotifications(false); 95 fShapes[i]->AddObserver(this); 96 } 97 } 98 99 // ObjectChanged 100 void 101 TransformShapesBox::ObjectChanged(const Observable* object) 102 { 103 if (!fView->LockLooper()) 104 return; 105 106 fParentTransform.Reset(); 107 // figure out bounds and store initial transformations 108 BRect box(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN); 109 for (int32 i = 0; i < fCount; i++) { 110 if (!fShapes[i]) 111 continue; 112 113 box = box | fShapes[i]->Bounds(); 114 fShapes[i]->StoreTo(&fOriginals[i * Transformable::matrix_size]); 115 } 116 // any TransformObjectsCommand cannot use the TransformBox 117 // anymore 118 _NotifyDeleted(); 119 120 Reset(); 121 SetBox(box); 122 123 fView->UnlockLooper(); 124 } 125 126 // MakeCommand 127 TransformCommand* 128 TransformShapesBox::MakeCommand(const char* commandName, uint32 nameIndex) 129 { 130 Transformable* objects[fCount]; 131 for (int32 i = 0; i < fCount; i++) 132 objects[i] = fShapes[i]; 133 134 return new TransformObjectsCommand(this, objects, fOriginals, fCount, 135 136 Pivot(), 137 Translation(), 138 LocalRotation(), 139 LocalXScale(), 140 LocalYScale(), 141 142 commandName, 143 nameIndex); 144 } 145 146