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 "TransformGradientCommand.h"
20
21using std::nothrow;
22
23
24// constructor
25TransformGradientBox::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
49TransformGradientBox::~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
61void
62TransformGradientBox::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
95void
96TransformGradientBox::ObjectChanged(const Observable* object)
97{
98	if (!fGradient || !fView->LockLooper())
99		return;
100
101	if (object == fShape) {
102		fView->Invalidate(Bounds());
103		fView->UnlockLooper();
104		return;
105	}
106
107	// any TransformGradientCommand cannot use the TransformBox
108	// anymore
109	_NotifyDeleted();
110
111	fGradient->StoreTo(fOriginals);
112
113	// figure out bounds and store initial transformations
114	SetTransformation(*fGradient);
115	SetBox(fGradient->GradientArea());
116
117	fView->UnlockLooper();
118}
119
120
121// Perform
122Command*
123TransformGradientBox::Perform()
124{
125	return NULL;
126}
127
128
129// Cancel
130Command*
131TransformGradientBox::Cancel()
132{
133	SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0);
134
135	return NULL;
136}
137
138
139// TransformFromCanvas
140void
141TransformGradientBox::TransformFromCanvas(BPoint& point) const
142{
143	if (fShape)
144		fShape->InverseTransform(&point);
145	fCanvasView->ConvertFromCanvas(&point);
146}
147
148
149// TransformToCanvas
150void
151TransformGradientBox::TransformToCanvas(BPoint& point) const
152{
153	fCanvasView->ConvertToCanvas(&point);
154	if (fShape)
155		fShape->Transform(&point);
156}
157
158
159// ZoomLevel
160float
161TransformGradientBox::ZoomLevel() const
162{
163	return fCanvasView->ZoomLevel();
164}
165
166
167// ViewSpaceRotation
168double
169TransformGradientBox::ViewSpaceRotation() const
170{
171	Transformable t(*this);
172	if (fShape)
173		t.Multiply(*fShape);
174	return t.rotation() * 180.0 / M_PI;
175}
176
177
178// MakeCommand
179TransformCommand*
180TransformGradientBox::MakeCommand(const char* commandName, uint32 nameIndex)
181{
182	return new TransformGradientCommand(this, fGradient, Pivot(),
183	   Translation(), LocalRotation(), LocalXScale(), LocalYScale(),
184	   commandName, nameIndex);
185}
186
187