10e1ba39fSStephan Aßmus /* 27f5bbbdcSAxel Dörfler * Copyright 2006-2009, Haiku. 30e1ba39fSStephan Aßmus * Distributed under the terms of the MIT License. 40e1ba39fSStephan Aßmus * 50e1ba39fSStephan Aßmus * Authors: 60e1ba39fSStephan Aßmus * Stephan Aßmus <superstippi@gmx.de> 70e1ba39fSStephan Aßmus */ 80e1ba39fSStephan Aßmus 90e1ba39fSStephan Aßmus #include "TransformGradientBox.h" 100e1ba39fSStephan Aßmus 110e1ba39fSStephan Aßmus #include <new> 120e1ba39fSStephan Aßmus #include <stdio.h> 130e1ba39fSStephan Aßmus #include <string.h> 140e1ba39fSStephan Aßmus 150e1ba39fSStephan Aßmus #include "CanvasView.h" 16991547efSStephan Aßmus #include "GradientTransformable.h" 170e1ba39fSStephan Aßmus #include "Shape.h" 180e1ba39fSStephan Aßmus #include "StateView.h" 19*c88bc5e9SStephan Aßmus #include "TransformGradientCommand.h" 200e1ba39fSStephan Aßmus 210e1ba39fSStephan Aßmus using std::nothrow; 220e1ba39fSStephan Aßmus 237f5bbbdcSAxel Dörfler 240e1ba39fSStephan Aßmus // constructor 257f5bbbdcSAxel Dörfler TransformGradientBox::TransformGradientBox(CanvasView* view, Gradient* gradient, 260e1ba39fSStephan Aßmus Shape* parentShape) 277f5bbbdcSAxel Dörfler : 287f5bbbdcSAxel Dörfler TransformBox(view, BRect(0.0, 0.0, 1.0, 1.0)), 290e1ba39fSStephan Aßmus 300e1ba39fSStephan Aßmus fCanvasView(view), 310e1ba39fSStephan Aßmus 320e1ba39fSStephan Aßmus fShape(parentShape), 330e1ba39fSStephan Aßmus fGradient(gradient) 340e1ba39fSStephan Aßmus { 350e1ba39fSStephan Aßmus if (fShape) { 360e1ba39fSStephan Aßmus fShape->Acquire(); 370e1ba39fSStephan Aßmus fShape->AddObserver(this); 380e1ba39fSStephan Aßmus } 390e1ba39fSStephan Aßmus if (fGradient) { 400e1ba39fSStephan Aßmus // trigger init 410e1ba39fSStephan Aßmus ObjectChanged(fGradient); 420e1ba39fSStephan Aßmus } else { 430e1ba39fSStephan Aßmus SetBox(BRect(0, 0, -1, -1)); 440e1ba39fSStephan Aßmus } 450e1ba39fSStephan Aßmus } 460e1ba39fSStephan Aßmus 477f5bbbdcSAxel Dörfler 480e1ba39fSStephan Aßmus // destructor 490e1ba39fSStephan Aßmus TransformGradientBox::~TransformGradientBox() 500e1ba39fSStephan Aßmus { 510e1ba39fSStephan Aßmus if (fShape) { 520e1ba39fSStephan Aßmus fShape->RemoveObserver(this); 530e1ba39fSStephan Aßmus fShape->Release(); 540e1ba39fSStephan Aßmus } 550e1ba39fSStephan Aßmus if (fGradient) 560e1ba39fSStephan Aßmus fGradient->RemoveObserver(this); 570e1ba39fSStephan Aßmus } 580e1ba39fSStephan Aßmus 597f5bbbdcSAxel Dörfler 600e1ba39fSStephan Aßmus // Update 610e1ba39fSStephan Aßmus void 620e1ba39fSStephan Aßmus TransformGradientBox::Update(bool deep) 630e1ba39fSStephan Aßmus { 640e1ba39fSStephan Aßmus BRect r = Bounds(); 650e1ba39fSStephan Aßmus 660e1ba39fSStephan Aßmus TransformBox::Update(deep); 670e1ba39fSStephan Aßmus 680e1ba39fSStephan Aßmus BRect dirty(r | Bounds()); 690e1ba39fSStephan Aßmus dirty.InsetBy(-8, -8); 700e1ba39fSStephan Aßmus fView->Invalidate(dirty); 710e1ba39fSStephan Aßmus 720e1ba39fSStephan Aßmus if (!deep || !fGradient) 730e1ba39fSStephan Aßmus return; 740e1ba39fSStephan Aßmus 750e1ba39fSStephan Aßmus fGradient->RemoveObserver(this); 760e1ba39fSStephan Aßmus fGradient->SuspendNotifications(true); 770e1ba39fSStephan Aßmus 780e1ba39fSStephan Aßmus // reset the objects transformation to the saved state 790e1ba39fSStephan Aßmus fGradient->Reset(); 800e1ba39fSStephan Aßmus // combine with the current transformation 810e1ba39fSStephan Aßmus fGradient->Multiply(*this); 820e1ba39fSStephan Aßmus 830e1ba39fSStephan Aßmus //printf("matrix:\n"); 840e1ba39fSStephan Aßmus //double m[6]; 850e1ba39fSStephan Aßmus //StoreTo(m); 860e1ba39fSStephan Aßmus //printf("[%5.10f] [%5.10f] [%5.10f]\n", m[0], m[1], m[2]); 870e1ba39fSStephan Aßmus //printf("[%5.10f] [%5.10f] [%5.10f]\n", m[3], m[4], m[5]); 880e1ba39fSStephan Aßmus // 890e1ba39fSStephan Aßmus fGradient->SuspendNotifications(false); 900e1ba39fSStephan Aßmus fGradient->AddObserver(this); 910e1ba39fSStephan Aßmus } 920e1ba39fSStephan Aßmus 937f5bbbdcSAxel Dörfler 940e1ba39fSStephan Aßmus // ObjectChanged 950e1ba39fSStephan Aßmus void 960e1ba39fSStephan Aßmus TransformGradientBox::ObjectChanged(const Observable* object) 970e1ba39fSStephan Aßmus { 980e1ba39fSStephan Aßmus if (!fGradient || !fView->LockLooper()) 990e1ba39fSStephan Aßmus return; 1000e1ba39fSStephan Aßmus 1010e1ba39fSStephan Aßmus if (object == fShape) { 1020e1ba39fSStephan Aßmus fView->Invalidate(Bounds()); 103cd7f54f1SStephan Aßmus fView->UnlockLooper(); 1040e1ba39fSStephan Aßmus return; 1050e1ba39fSStephan Aßmus } 1060e1ba39fSStephan Aßmus 107*c88bc5e9SStephan Aßmus // any TransformGradientCommand cannot use the TransformBox 1080e1ba39fSStephan Aßmus // anymore 1090e1ba39fSStephan Aßmus _NotifyDeleted(); 1100e1ba39fSStephan Aßmus 1110e1ba39fSStephan Aßmus fGradient->StoreTo(fOriginals); 1120e1ba39fSStephan Aßmus 1130e1ba39fSStephan Aßmus // figure out bounds and store initial transformations 1140e1ba39fSStephan Aßmus SetTransformation(*fGradient); 1150e1ba39fSStephan Aßmus SetBox(fGradient->GradientArea()); 1160e1ba39fSStephan Aßmus 1170e1ba39fSStephan Aßmus fView->UnlockLooper(); 1180e1ba39fSStephan Aßmus } 1190e1ba39fSStephan Aßmus 1207f5bbbdcSAxel Dörfler 1210e1ba39fSStephan Aßmus // Perform 1220e1ba39fSStephan Aßmus Command* 1230e1ba39fSStephan Aßmus TransformGradientBox::Perform() 1240e1ba39fSStephan Aßmus { 1250e1ba39fSStephan Aßmus return NULL; 1260e1ba39fSStephan Aßmus } 1270e1ba39fSStephan Aßmus 1287f5bbbdcSAxel Dörfler 1290e1ba39fSStephan Aßmus // Cancel 1300e1ba39fSStephan Aßmus Command* 1310e1ba39fSStephan Aßmus TransformGradientBox::Cancel() 1320e1ba39fSStephan Aßmus { 1330e1ba39fSStephan Aßmus SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0); 1340e1ba39fSStephan Aßmus 1350e1ba39fSStephan Aßmus return NULL; 1360e1ba39fSStephan Aßmus } 1370e1ba39fSStephan Aßmus 1387f5bbbdcSAxel Dörfler 1390e1ba39fSStephan Aßmus // TransformFromCanvas 1400e1ba39fSStephan Aßmus void 1410e1ba39fSStephan Aßmus TransformGradientBox::TransformFromCanvas(BPoint& point) const 1420e1ba39fSStephan Aßmus { 1430e1ba39fSStephan Aßmus if (fShape) 1440e1ba39fSStephan Aßmus fShape->InverseTransform(&point); 1450e1ba39fSStephan Aßmus fCanvasView->ConvertFromCanvas(&point); 1460e1ba39fSStephan Aßmus } 1470e1ba39fSStephan Aßmus 1487f5bbbdcSAxel Dörfler 1490e1ba39fSStephan Aßmus // TransformToCanvas 1500e1ba39fSStephan Aßmus void 1510e1ba39fSStephan Aßmus TransformGradientBox::TransformToCanvas(BPoint& point) const 1520e1ba39fSStephan Aßmus { 1530e1ba39fSStephan Aßmus fCanvasView->ConvertToCanvas(&point); 1540e1ba39fSStephan Aßmus if (fShape) 1550e1ba39fSStephan Aßmus fShape->Transform(&point); 1560e1ba39fSStephan Aßmus } 1570e1ba39fSStephan Aßmus 1587f5bbbdcSAxel Dörfler 1590e1ba39fSStephan Aßmus // ZoomLevel 1600e1ba39fSStephan Aßmus float 1610e1ba39fSStephan Aßmus TransformGradientBox::ZoomLevel() const 1620e1ba39fSStephan Aßmus { 1630e1ba39fSStephan Aßmus return fCanvasView->ZoomLevel(); 1640e1ba39fSStephan Aßmus } 1650e1ba39fSStephan Aßmus 1667f5bbbdcSAxel Dörfler 1670e1ba39fSStephan Aßmus // ViewSpaceRotation 1680e1ba39fSStephan Aßmus double 1690e1ba39fSStephan Aßmus TransformGradientBox::ViewSpaceRotation() const 1700e1ba39fSStephan Aßmus { 1710e1ba39fSStephan Aßmus Transformable t(*this); 1720e1ba39fSStephan Aßmus if (fShape) 1730e1ba39fSStephan Aßmus t.Multiply(*fShape); 1747f5bbbdcSAxel Dörfler return t.rotation() * 180.0 / M_PI; 1750e1ba39fSStephan Aßmus } 1760e1ba39fSStephan Aßmus 1777f5bbbdcSAxel Dörfler 1780e1ba39fSStephan Aßmus // MakeCommand 1790e1ba39fSStephan Aßmus TransformCommand* 1800e1ba39fSStephan Aßmus TransformGradientBox::MakeCommand(const char* commandName, uint32 nameIndex) 1810e1ba39fSStephan Aßmus { 182*c88bc5e9SStephan Aßmus return new TransformGradientCommand(this, fGradient, Pivot(), 183*c88bc5e9SStephan Aßmus Translation(), LocalRotation(), LocalXScale(), LocalYScale(), 184*c88bc5e9SStephan Aßmus commandName, nameIndex); 1850e1ba39fSStephan Aßmus } 1860e1ba39fSStephan Aßmus 187