xref: /haiku/src/apps/icon-o-matic/transformable/TransformGradientBox.cpp (revision c88bc5e973fe56886e5cfd3c16982c2eb25d4d4e)
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