1 /* 2 * Copyright 2006-2009, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "TransformGradientBox.h" 10 11 #include <new> 12 #include <stdio.h> 13 #include <string.h> 14 15 #include "CanvasView.h" 16 #include "GradientTransformable.h" 17 #include "Shape.h" 18 #include "StateView.h" 19 #include "TransformObjectsCommand.h" 20 21 using std::nothrow; 22 23 24 // constructor 25 TransformGradientBox::TransformGradientBox(CanvasView* view, Gradient* gradient, 26 Shape* parentShape) 27 : 28 TransformBox(view, BRect(0.0, 0.0, 1.0, 1.0)), 29 30 fCanvasView(view), 31 32 fShape(parentShape), 33 fGradient(gradient) 34 { 35 if (fShape) { 36 fShape->Acquire(); 37 fShape->AddObserver(this); 38 } 39 if (fGradient) { 40 // trigger init 41 ObjectChanged(fGradient); 42 } else { 43 SetBox(BRect(0, 0, -1, -1)); 44 } 45 } 46 47 48 // destructor 49 TransformGradientBox::~TransformGradientBox() 50 { 51 if (fShape) { 52 fShape->RemoveObserver(this); 53 fShape->Release(); 54 } 55 if (fGradient) 56 fGradient->RemoveObserver(this); 57 } 58 59 60 // Update 61 void 62 TransformGradientBox::Update(bool deep) 63 { 64 BRect r = Bounds(); 65 66 TransformBox::Update(deep); 67 68 BRect dirty(r | Bounds()); 69 dirty.InsetBy(-8, -8); 70 fView->Invalidate(dirty); 71 72 if (!deep || !fGradient) 73 return; 74 75 fGradient->RemoveObserver(this); 76 fGradient->SuspendNotifications(true); 77 78 // reset the objects transformation to the saved state 79 fGradient->Reset(); 80 // combine with the current transformation 81 fGradient->Multiply(*this); 82 83 //printf("matrix:\n"); 84 //double m[6]; 85 //StoreTo(m); 86 //printf("[%5.10f] [%5.10f] [%5.10f]\n", m[0], m[1], m[2]); 87 //printf("[%5.10f] [%5.10f] [%5.10f]\n", m[3], m[4], m[5]); 88 // 89 fGradient->SuspendNotifications(false); 90 fGradient->AddObserver(this); 91 } 92 93 94 // ObjectChanged 95 void 96 TransformGradientBox::ObjectChanged(const Observable* object) 97 { 98 if (!fGradient || !fView->LockLooper()) 99 return; 100 101 if (object == fShape) { 102 fView->Invalidate(Bounds()); 103 return; 104 } 105 106 // any TransformObjectsCommand cannot use the TransformBox 107 // anymore 108 _NotifyDeleted(); 109 110 fGradient->StoreTo(fOriginals); 111 112 // figure out bounds and store initial transformations 113 SetTransformation(*fGradient); 114 SetBox(fGradient->GradientArea()); 115 116 fView->UnlockLooper(); 117 } 118 119 120 // Perform 121 Command* 122 TransformGradientBox::Perform() 123 { 124 return NULL; 125 } 126 127 128 // Cancel 129 Command* 130 TransformGradientBox::Cancel() 131 { 132 SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0); 133 134 return NULL; 135 } 136 137 138 // TransformFromCanvas 139 void 140 TransformGradientBox::TransformFromCanvas(BPoint& point) const 141 { 142 if (fShape) 143 fShape->InverseTransform(&point); 144 fCanvasView->ConvertFromCanvas(&point); 145 } 146 147 148 // TransformToCanvas 149 void 150 TransformGradientBox::TransformToCanvas(BPoint& point) const 151 { 152 fCanvasView->ConvertToCanvas(&point); 153 if (fShape) 154 fShape->Transform(&point); 155 } 156 157 158 // ZoomLevel 159 float 160 TransformGradientBox::ZoomLevel() const 161 { 162 return fCanvasView->ZoomLevel(); 163 } 164 165 166 // ViewSpaceRotation 167 double 168 TransformGradientBox::ViewSpaceRotation() const 169 { 170 Transformable t(*this); 171 if (fShape) 172 t.Multiply(*fShape); 173 return t.rotation() * 180.0 / M_PI; 174 } 175 176 177 // MakeCommand 178 TransformCommand* 179 TransformGradientBox::MakeCommand(const char* commandName, uint32 nameIndex) 180 { 181 Transformable* objects[1]; 182 objects[0] = fGradient; 183 184 return new TransformObjectsCommand(this, objects, fOriginals, 1, Pivot(), 185 Translation(), LocalRotation(), LocalXScale(), LocalYScale(), commandName, 186 nameIndex); 187 } 188 189