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->AcquireReference();
37		fShape->AddObserver(this);
38	}
39	if (fGradient.IsSet()) {
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->ReleaseReference();
54	}
55	if (fGradient.IsSet()) {
56		fGradient->RemoveObserver(this);
57	}
58}
59
60
61// Update
62void
63TransformGradientBox::Update(bool deep)
64{
65	BRect r = Bounds();
66
67	TransformBox::Update(deep);
68
69	BRect dirty(r | Bounds());
70	dirty.InsetBy(-8, -8);
71	fView->Invalidate(dirty);
72
73	if (!deep || !fGradient.IsSet())
74		return;
75
76	fGradient->RemoveObserver(this);
77	fGradient->SuspendNotifications(true);
78
79	// reset the objects transformation to the saved state
80	fGradient->Reset();
81	// combine with the current transformation
82	fGradient->Multiply(*this);
83
84//printf("matrix:\n");
85//double m[6];
86//StoreTo(m);
87//printf("[%5.10f] [%5.10f] [%5.10f]\n", m[0], m[1], m[2]);
88//printf("[%5.10f] [%5.10f] [%5.10f]\n", m[3], m[4], m[5]);
89//
90	fGradient->SuspendNotifications(false);
91	fGradient->AddObserver(this);
92}
93
94
95// ObjectChanged
96void
97TransformGradientBox::ObjectChanged(const Observable* object)
98{
99	if (!fGradient.IsSet() || !fView->LockLooper())
100		return;
101
102	if (object == fShape) {
103		fView->Invalidate(Bounds());
104		fView->UnlockLooper();
105		return;
106	}
107
108	// any TransformGradientCommand cannot use the TransformBox
109	// anymore
110	_NotifyDeleted();
111
112	fGradient->StoreTo(fOriginals);
113
114	// figure out bounds and store initial transformations
115	SetTransformation(*fGradient);
116	SetBox(fGradient->GradientArea());
117
118	fView->UnlockLooper();
119}
120
121
122// Perform
123Command*
124TransformGradientBox::Perform()
125{
126	return NULL;
127}
128
129
130// Cancel
131Command*
132TransformGradientBox::Cancel()
133{
134	SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0);
135
136	return NULL;
137}
138
139
140// TransformFromCanvas
141void
142TransformGradientBox::TransformFromCanvas(BPoint& point) const
143{
144	if (fShape)
145		fShape->InverseTransform(&point);
146	fCanvasView->ConvertFromCanvas(&point);
147}
148
149
150// TransformToCanvas
151void
152TransformGradientBox::TransformToCanvas(BPoint& point) const
153{
154	fCanvasView->ConvertToCanvas(&point);
155	if (fShape)
156		fShape->Transform(&point);
157}
158
159
160// ZoomLevel
161float
162TransformGradientBox::ZoomLevel() const
163{
164	return fCanvasView->ZoomLevel();
165}
166
167
168// ViewSpaceRotation
169double
170TransformGradientBox::ViewSpaceRotation() const
171{
172	Transformable t(*this);
173	if (fShape)
174		t.Multiply(*fShape);
175	return t.rotation() * 180.0 / M_PI;
176}
177
178
179// MakeCommand
180TransformCommand*
181TransformGradientBox::MakeCommand(const char* commandName)
182{
183	return new TransformGradientCommand(this, fGradient, Pivot(),
184	   Translation(), LocalRotation(), LocalXScale(), LocalYScale(),
185	   commandName);
186}
187
188