xref: /haiku/src/apps/icon-o-matic/transformable/TransformGradientBox.cpp (revision a75a222b35d17cd83bc75253f3cd8e24a6a911f4)
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"
19c88bc5e9SStephan Aßmus #include "TransformGradientCommand.h"
200e1ba39fSStephan Aßmus 
210e1ba39fSStephan Aßmus using std::nothrow;
220e1ba39fSStephan Aßmus 
237f5bbbdcSAxel Dörfler 
240e1ba39fSStephan Aßmus // constructor
TransformGradientBox(CanvasView * view,Gradient * gradient,Shape * parentShape)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) {
360cbb6c11SStephan Aßmus 		fShape->AcquireReference();
370e1ba39fSStephan Aßmus 		fShape->AddObserver(this);
380e1ba39fSStephan Aßmus 	}
392263aa8fSZardshard 	if (fGradient.IsSet()) {
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
~TransformGradientBox()490e1ba39fSStephan Aßmus TransformGradientBox::~TransformGradientBox()
500e1ba39fSStephan Aßmus {
510e1ba39fSStephan Aßmus 	if (fShape) {
520e1ba39fSStephan Aßmus 		fShape->RemoveObserver(this);
530cbb6c11SStephan Aßmus 		fShape->ReleaseReference();
540e1ba39fSStephan Aßmus 	}
552263aa8fSZardshard 	if (fGradient.IsSet()) {
560e1ba39fSStephan Aßmus 		fGradient->RemoveObserver(this);
570e1ba39fSStephan Aßmus 	}
582263aa8fSZardshard }
590e1ba39fSStephan Aßmus 
607f5bbbdcSAxel Dörfler 
610e1ba39fSStephan Aßmus // Update
620e1ba39fSStephan Aßmus void
Update(bool deep)630e1ba39fSStephan Aßmus TransformGradientBox::Update(bool deep)
640e1ba39fSStephan Aßmus {
650e1ba39fSStephan Aßmus 	BRect r = Bounds();
660e1ba39fSStephan Aßmus 
670e1ba39fSStephan Aßmus 	TransformBox::Update(deep);
680e1ba39fSStephan Aßmus 
690e1ba39fSStephan Aßmus 	BRect dirty(r | Bounds());
700e1ba39fSStephan Aßmus 	dirty.InsetBy(-8, -8);
710e1ba39fSStephan Aßmus 	fView->Invalidate(dirty);
720e1ba39fSStephan Aßmus 
732263aa8fSZardshard 	if (!deep || !fGradient.IsSet())
740e1ba39fSStephan Aßmus 		return;
750e1ba39fSStephan Aßmus 
760e1ba39fSStephan Aßmus 	fGradient->RemoveObserver(this);
770e1ba39fSStephan Aßmus 	fGradient->SuspendNotifications(true);
780e1ba39fSStephan Aßmus 
790e1ba39fSStephan Aßmus 	// reset the objects transformation to the saved state
800e1ba39fSStephan Aßmus 	fGradient->Reset();
810e1ba39fSStephan Aßmus 	// combine with the current transformation
820e1ba39fSStephan Aßmus 	fGradient->Multiply(*this);
830e1ba39fSStephan Aßmus 
840e1ba39fSStephan Aßmus //printf("matrix:\n");
850e1ba39fSStephan Aßmus //double m[6];
860e1ba39fSStephan Aßmus //StoreTo(m);
870e1ba39fSStephan Aßmus //printf("[%5.10f] [%5.10f] [%5.10f]\n", m[0], m[1], m[2]);
880e1ba39fSStephan Aßmus //printf("[%5.10f] [%5.10f] [%5.10f]\n", m[3], m[4], m[5]);
890e1ba39fSStephan Aßmus //
900e1ba39fSStephan Aßmus 	fGradient->SuspendNotifications(false);
910e1ba39fSStephan Aßmus 	fGradient->AddObserver(this);
920e1ba39fSStephan Aßmus }
930e1ba39fSStephan Aßmus 
947f5bbbdcSAxel Dörfler 
950e1ba39fSStephan Aßmus // ObjectChanged
960e1ba39fSStephan Aßmus void
ObjectChanged(const Observable * object)970e1ba39fSStephan Aßmus TransformGradientBox::ObjectChanged(const Observable* object)
980e1ba39fSStephan Aßmus {
992263aa8fSZardshard 	if (!fGradient.IsSet() || !fView->LockLooper())
1000e1ba39fSStephan Aßmus 		return;
1010e1ba39fSStephan Aßmus 
1020e1ba39fSStephan Aßmus 	if (object == fShape) {
1030e1ba39fSStephan Aßmus 		fView->Invalidate(Bounds());
104cd7f54f1SStephan Aßmus 		fView->UnlockLooper();
1050e1ba39fSStephan Aßmus 		return;
1060e1ba39fSStephan Aßmus 	}
1070e1ba39fSStephan Aßmus 
108c88bc5e9SStephan Aßmus 	// any TransformGradientCommand cannot use the TransformBox
1090e1ba39fSStephan Aßmus 	// anymore
1100e1ba39fSStephan Aßmus 	_NotifyDeleted();
1110e1ba39fSStephan Aßmus 
1120e1ba39fSStephan Aßmus 	fGradient->StoreTo(fOriginals);
1130e1ba39fSStephan Aßmus 
1140e1ba39fSStephan Aßmus 	// figure out bounds and store initial transformations
1150e1ba39fSStephan Aßmus 	SetTransformation(*fGradient);
1160e1ba39fSStephan Aßmus 	SetBox(fGradient->GradientArea());
1170e1ba39fSStephan Aßmus 
1180e1ba39fSStephan Aßmus 	fView->UnlockLooper();
1190e1ba39fSStephan Aßmus }
1200e1ba39fSStephan Aßmus 
1217f5bbbdcSAxel Dörfler 
1220e1ba39fSStephan Aßmus // Perform
1230e1ba39fSStephan Aßmus Command*
Perform()1240e1ba39fSStephan Aßmus TransformGradientBox::Perform()
1250e1ba39fSStephan Aßmus {
1260e1ba39fSStephan Aßmus 	return NULL;
1270e1ba39fSStephan Aßmus }
1280e1ba39fSStephan Aßmus 
1297f5bbbdcSAxel Dörfler 
1300e1ba39fSStephan Aßmus // Cancel
1310e1ba39fSStephan Aßmus Command*
Cancel()1320e1ba39fSStephan Aßmus TransformGradientBox::Cancel()
1330e1ba39fSStephan Aßmus {
1340e1ba39fSStephan Aßmus 	SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0);
1350e1ba39fSStephan Aßmus 
1360e1ba39fSStephan Aßmus 	return NULL;
1370e1ba39fSStephan Aßmus }
1380e1ba39fSStephan Aßmus 
1397f5bbbdcSAxel Dörfler 
1400e1ba39fSStephan Aßmus // TransformFromCanvas
1410e1ba39fSStephan Aßmus void
TransformFromCanvas(BPoint & point) const1420e1ba39fSStephan Aßmus TransformGradientBox::TransformFromCanvas(BPoint& point) const
1430e1ba39fSStephan Aßmus {
1440e1ba39fSStephan Aßmus 	if (fShape)
1450e1ba39fSStephan Aßmus 		fShape->InverseTransform(&point);
1460e1ba39fSStephan Aßmus 	fCanvasView->ConvertFromCanvas(&point);
1470e1ba39fSStephan Aßmus }
1480e1ba39fSStephan Aßmus 
1497f5bbbdcSAxel Dörfler 
1500e1ba39fSStephan Aßmus // TransformToCanvas
1510e1ba39fSStephan Aßmus void
TransformToCanvas(BPoint & point) const1520e1ba39fSStephan Aßmus TransformGradientBox::TransformToCanvas(BPoint& point) const
1530e1ba39fSStephan Aßmus {
1540e1ba39fSStephan Aßmus 	fCanvasView->ConvertToCanvas(&point);
1550e1ba39fSStephan Aßmus 	if (fShape)
1560e1ba39fSStephan Aßmus 		fShape->Transform(&point);
1570e1ba39fSStephan Aßmus }
1580e1ba39fSStephan Aßmus 
1597f5bbbdcSAxel Dörfler 
1600e1ba39fSStephan Aßmus // ZoomLevel
1610e1ba39fSStephan Aßmus float
ZoomLevel() const1620e1ba39fSStephan Aßmus TransformGradientBox::ZoomLevel() const
1630e1ba39fSStephan Aßmus {
1640e1ba39fSStephan Aßmus 	return fCanvasView->ZoomLevel();
1650e1ba39fSStephan Aßmus }
1660e1ba39fSStephan Aßmus 
1677f5bbbdcSAxel Dörfler 
1680e1ba39fSStephan Aßmus // ViewSpaceRotation
1690e1ba39fSStephan Aßmus double
ViewSpaceRotation() const1700e1ba39fSStephan Aßmus TransformGradientBox::ViewSpaceRotation() const
1710e1ba39fSStephan Aßmus {
1720e1ba39fSStephan Aßmus 	Transformable t(*this);
1730e1ba39fSStephan Aßmus 	if (fShape)
1740e1ba39fSStephan Aßmus 		t.Multiply(*fShape);
1757f5bbbdcSAxel Dörfler 	return t.rotation() * 180.0 / M_PI;
1760e1ba39fSStephan Aßmus }
1770e1ba39fSStephan Aßmus 
1787f5bbbdcSAxel Dörfler 
1790e1ba39fSStephan Aßmus // MakeCommand
1800e1ba39fSStephan Aßmus TransformCommand*
MakeCommand(const char * commandName)181*a75a222bSZardshard TransformGradientBox::MakeCommand(const char* commandName)
1820e1ba39fSStephan Aßmus {
183c88bc5e9SStephan Aßmus 	return new TransformGradientCommand(this, fGradient, Pivot(),
184c88bc5e9SStephan Aßmus 	   Translation(), LocalRotation(), LocalXScale(), LocalYScale(),
185*a75a222bSZardshard 	   commandName);
1860e1ba39fSStephan Aßmus }
1870e1ba39fSStephan Aßmus 
188