1fb07ece0SStephan Aßmus/*
2fb07ece0SStephan Aßmus * Copyright 2006, Haiku. All rights reserved.
3fb07ece0SStephan Aßmus * Distributed under the terms of the MIT License.
4fb07ece0SStephan Aßmus *
5fb07ece0SStephan Aßmus * Authors:
6fb07ece0SStephan Aßmus *		Stephan A��mus <superstippi@gmx.de>
7fb07ece0SStephan Aßmus */
8fb07ece0SStephan Aßmus
9fb07ece0SStephan Aßmus#include "Shape.h"
10fb07ece0SStephan Aßmus
11fb07ece0SStephan Aßmus#include <Message.h>
12fb07ece0SStephan Aßmus#include <TypeConstants.h>
13fb07ece0SStephan Aßmus
14fb07ece0SStephan Aßmus#include <new>
15fb07ece0SStephan Aßmus#include <limits.h>
16fb07ece0SStephan Aßmus#include <stdio.h>
17fb07ece0SStephan Aßmus
18fb07ece0SStephan Aßmus#include "agg_bounding_rect.h"
19fb07ece0SStephan Aßmus
20fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
21fb07ece0SStephan Aßmus# include "CommonPropertyIDs.h"
22fb07ece0SStephan Aßmus# include "Property.h"
23fb07ece0SStephan Aßmus# include "PropertyObject.h"
24fb07ece0SStephan Aßmus#endif // ICON_O_MATIC
25fb07ece0SStephan Aßmus#include "Style.h"
26fb07ece0SStephan Aßmus#include "TransformerFactory.h"
27fb07ece0SStephan Aßmus
28fb07ece0SStephan Aßmususing std::nothrow;
29fb07ece0SStephan Aßmus
30fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
31fb07ece0SStephan Aßmus// constructor
32fb07ece0SStephan AßmusShapeListener::ShapeListener()
33fb07ece0SStephan Aßmus{
34fb07ece0SStephan Aßmus}
35fb07ece0SStephan Aßmus
36fb07ece0SStephan Aßmus// destructor
37fb07ece0SStephan AßmusShapeListener::~ShapeListener()
38fb07ece0SStephan Aßmus{
39fb07ece0SStephan Aßmus}
40fb07ece0SStephan Aßmus#endif // ICON_O_MATIC
41fb07ece0SStephan Aßmus
42fb07ece0SStephan Aßmus// #pragma mark -
43fb07ece0SStephan Aßmus
44fb07ece0SStephan Aßmus// constructor
45fb07ece0SStephan AßmusShape::Shape(::Style* style)
46fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
47fb07ece0SStephan Aßmus	: IconObject("<shape>"),
48fb07ece0SStephan Aßmus	  Transformable(),
49fb07ece0SStephan Aßmus	  Observer(),
50fb07ece0SStephan Aßmus	  PathContainerListener(),
51fb07ece0SStephan Aßmus#else
52fb07ece0SStephan Aßmus	: Transformable(),
53fb07ece0SStephan Aßmus#endif
54fb07ece0SStephan Aßmus
55fb07ece0SStephan Aßmus	  fPaths(new (nothrow) PathContainer(false)),
56fb07ece0SStephan Aßmus	  fStyle(NULL),
57fb07ece0SStephan Aßmus
58fb07ece0SStephan Aßmus	  fPathSource(fPaths),
59fb07ece0SStephan Aßmus	  fTransformers(4),
60fb07ece0SStephan Aßmus	  fNeedsUpdate(true),
61fb07ece0SStephan Aßmus
62fb07ece0SStephan Aßmus	  fLastBounds(0, 0, -1, -1),
63fb07ece0SStephan Aßmus
64fb07ece0SStephan Aßmus	  fHinting(false),
65fb07ece0SStephan Aßmus	  fMinVisibilityScale(0.0),
662f953b71SStephan Aßmus	  fMaxVisibilityScale(4.0)
67fb07ece0SStephan Aßmus
68fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
69fb07ece0SStephan Aßmus	, fListeners(8)
70fb07ece0SStephan Aßmus#endif
71fb07ece0SStephan Aßmus{
72fb07ece0SStephan Aßmus	SetStyle(style);
73fb07ece0SStephan Aßmus
74fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
75fb07ece0SStephan Aßmus	if (fPaths)
76fb07ece0SStephan Aßmus		fPaths->AddListener(this);
77fb07ece0SStephan Aßmus#endif
78fb07ece0SStephan Aßmus}
79fb07ece0SStephan Aßmus
80fb07ece0SStephan Aßmus// constructor
81fb07ece0SStephan AßmusShape::Shape(const Shape& other)
82fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
83fb07ece0SStephan Aßmus	: IconObject(other),
84fb07ece0SStephan Aßmus	  Transformable(other),
85fb07ece0SStephan Aßmus	  Observer(),
86fb07ece0SStephan Aßmus	  PathContainerListener(),
87fb07ece0SStephan Aßmus#else
88fb07ece0SStephan Aßmus	: Transformable(other),
89fb07ece0SStephan Aßmus#endif
90fb07ece0SStephan Aßmus
91fb07ece0SStephan Aßmus	  fPaths(new (nothrow) PathContainer(false)),
92fb07ece0SStephan Aßmus	  fStyle(NULL),
93fb07ece0SStephan Aßmus
94fb07ece0SStephan Aßmus	  fPathSource(fPaths),
95fb07ece0SStephan Aßmus	  fTransformers(4),
96fb07ece0SStephan Aßmus	  fNeedsUpdate(true),
97fb07ece0SStephan Aßmus
98fb07ece0SStephan Aßmus	  fLastBounds(0, 0, -1, -1),
99fb07ece0SStephan Aßmus
100fb07ece0SStephan Aßmus	  fHinting(other.fHinting),
101fb07ece0SStephan Aßmus	  fMinVisibilityScale(other.fMinVisibilityScale),
102fb07ece0SStephan Aßmus	  fMaxVisibilityScale(other.fMaxVisibilityScale)
103fb07ece0SStephan Aßmus
104fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
105fb07ece0SStephan Aßmus	, fListeners(8)
106fb07ece0SStephan Aßmus#endif
107fb07ece0SStephan Aßmus{
108fb07ece0SStephan Aßmus	SetStyle(other.fStyle);
109fb07ece0SStephan Aßmus
110fb07ece0SStephan Aßmus	if (fPaths) {
111fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
112fb07ece0SStephan Aßmus		fPaths->AddListener(this);
113fb07ece0SStephan Aßmus#endif
114fb07ece0SStephan Aßmus		// copy the path references from
115fb07ece0SStephan Aßmus		// the other shape
116fb07ece0SStephan Aßmus		if (other.fPaths) {
117fb07ece0SStephan Aßmus			int32 count = other.fPaths->CountPaths();
118fb07ece0SStephan Aßmus			for (int32 i = 0; i < count; i++) {
119fb07ece0SStephan Aßmus				if (!fPaths->AddPath(other.fPaths->PathAtFast(i)))
120fb07ece0SStephan Aßmus					break;
121fb07ece0SStephan Aßmus			}
122fb07ece0SStephan Aßmus		}
123fb07ece0SStephan Aßmus	}
124fb07ece0SStephan Aßmus	// clone vertex transformers
125fb07ece0SStephan Aßmus	int32 count = other.CountTransformers();
126fb07ece0SStephan Aßmus	for (int32 i = 0; i < count; i++) {
127fb07ece0SStephan Aßmus		Transformer* original = other.TransformerAtFast(i);
128fb07ece0SStephan Aßmus		Transformer* cloned = original->Clone(fPathSource);
129fb07ece0SStephan Aßmus		if (!AddTransformer(cloned)) {
130fb07ece0SStephan Aßmus			delete cloned;
131fb07ece0SStephan Aßmus			break;
132fb07ece0SStephan Aßmus		}
133fb07ece0SStephan Aßmus	}
134fb07ece0SStephan Aßmus}
135fb07ece0SStephan Aßmus
136fb07ece0SStephan Aßmus// destructor
137fb07ece0SStephan AßmusShape::~Shape()
138fb07ece0SStephan Aßmus{
139fb07ece0SStephan Aßmus	int32 count = fTransformers.CountItems();
140fb07ece0SStephan Aßmus	for (int32 i = 0; i < count; i++) {
141fb07ece0SStephan Aßmus		Transformer* t = (Transformer*)fTransformers.ItemAtFast(i);
142fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
143fb07ece0SStephan Aßmus		t->RemoveObserver(this);
144fb07ece0SStephan Aßmus		_NotifyTransformerRemoved(t);
145fb07ece0SStephan Aßmus#endif
146fb07ece0SStephan Aßmus		delete t;
147fb07ece0SStephan Aßmus	}
148fb07ece0SStephan Aßmus
149fb07ece0SStephan Aßmus	fPaths->MakeEmpty();
150fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
151fb07ece0SStephan Aßmus	fPaths->RemoveListener(this);
152fb07ece0SStephan Aßmus#endif
153fb07ece0SStephan Aßmus	delete fPaths;
154fb07ece0SStephan Aßmus
155fb07ece0SStephan Aßmus	SetStyle(NULL);
156fb07ece0SStephan Aßmus}
157fb07ece0SStephan Aßmus
158fb07ece0SStephan Aßmus// #pragma mark -
159fb07ece0SStephan Aßmus
160fb07ece0SStephan Aßmus// Unarchive
161fb07ece0SStephan Aßmusstatus_t
162fb07ece0SStephan AßmusShape::Unarchive(const BMessage* archive)
163fb07ece0SStephan Aßmus{
1648b8d44bfSMichael Lotz#ifdef ICON_O_MATIC
165fb07ece0SStephan Aßmus	// IconObject properties
166fb07ece0SStephan Aßmus	status_t ret = IconObject::Unarchive(archive);
167fb07ece0SStephan Aßmus	if (ret < B_OK)
168fb07ece0SStephan Aßmus		return ret;
1698b8d44bfSMichael Lotz#else
1708b8d44bfSMichael Lotz	status_t ret;
1718b8d44bfSMichael Lotz#endif
172fb07ece0SStephan Aßmus
173fb07ece0SStephan Aßmus	// recreate transformers
174fb07ece0SStephan Aßmus	BMessage transformerArchive;
175fb07ece0SStephan Aßmus	for (int32 i = 0;
176fb07ece0SStephan Aßmus		 archive->FindMessage("transformer", i,
177fb07ece0SStephan Aßmus		 					  &transformerArchive) == B_OK;
178fb07ece0SStephan Aßmus		 i++) {
179fb07ece0SStephan Aßmus		Transformer* transformer
180fb07ece0SStephan Aßmus			= TransformerFactory::TransformerFor(
181fb07ece0SStephan Aßmus				&transformerArchive, VertexSource());
182fb07ece0SStephan Aßmus		if (!transformer || !AddTransformer(transformer)) {
183fb07ece0SStephan Aßmus			delete transformer;
184fb07ece0SStephan Aßmus		}
185fb07ece0SStephan Aßmus	}
186fb07ece0SStephan Aßmus
187fb07ece0SStephan Aßmus	// read transformation
188fb07ece0SStephan Aßmus	int32 size = Transformable::matrix_size;
189fb07ece0SStephan Aßmus	const void* matrix;
190fb07ece0SStephan Aßmus	ssize_t dataSize = size * sizeof(double);
191fb07ece0SStephan Aßmus	ret = archive->FindData("transformation", B_DOUBLE_TYPE,
192fb07ece0SStephan Aßmus							&matrix, &dataSize);
193fb07ece0SStephan Aßmus	if (ret == B_OK && dataSize == (ssize_t)(size * sizeof(double)))
194fb07ece0SStephan Aßmus		LoadFrom((const double*)matrix);
195fb07ece0SStephan Aßmus
196fb07ece0SStephan Aßmus	// hinting
197fb07ece0SStephan Aßmus	if (archive->FindBool("hinting", &fHinting) < B_OK)
198fb07ece0SStephan Aßmus		fHinting = false;
199fb07ece0SStephan Aßmus
200fb07ece0SStephan Aßmus	// min visibility scale
201fb07ece0SStephan Aßmus	if (archive->FindFloat("min visibility scale",
202fb07ece0SStephan Aßmus						   &fMinVisibilityScale) < B_OK)
203fb07ece0SStephan Aßmus		fMinVisibilityScale = 0.0;
204fb07ece0SStephan Aßmus
205fb07ece0SStephan Aßmus	// max visibility scale
206fb07ece0SStephan Aßmus	if (archive->FindFloat("max visibility scale",
207fb07ece0SStephan Aßmus						   &fMaxVisibilityScale) < B_OK)
2082f953b71SStephan Aßmus		fMaxVisibilityScale = 4.0;
209fb07ece0SStephan Aßmus
210fb07ece0SStephan Aßmus	if (fMinVisibilityScale < 0.0)
211fb07ece0SStephan Aßmus		fMinVisibilityScale = 0.0;
2122f953b71SStephan Aßmus	if (fMinVisibilityScale > 4.0)
2132f953b71SStephan Aßmus		fMinVisibilityScale = 4.0;
214fb07ece0SStephan Aßmus	if (fMaxVisibilityScale < 0.0)
215fb07ece0SStephan Aßmus		fMaxVisibilityScale = 0.0;
2162f953b71SStephan Aßmus	if (fMaxVisibilityScale > 4.0)
2172f953b71SStephan Aßmus		fMaxVisibilityScale = 4.0;
218fb07ece0SStephan Aßmus
219fb07ece0SStephan Aßmus	return B_OK;
220fb07ece0SStephan Aßmus}
221fb07ece0SStephan Aßmus
2228b8d44bfSMichael Lotz#ifdef ICON_O_MATIC
2238b8d44bfSMichael Lotz
224fb07ece0SStephan Aßmus// Archive
225fb07ece0SStephan Aßmusstatus_t
226fb07ece0SStephan AßmusShape::Archive(BMessage* into, bool deep) const
227fb07ece0SStephan Aßmus{
228fb07ece0SStephan Aßmus	status_t ret = IconObject::Archive(into, deep);
229fb07ece0SStephan Aßmus
230fb07ece0SStephan Aßmus	// transformers
231fb07ece0SStephan Aßmus	if (ret == B_OK) {
232fb07ece0SStephan Aßmus		int32 count = CountTransformers();
233fb07ece0SStephan Aßmus		for (int32 i = 0; i < count; i++) {
234fb07ece0SStephan Aßmus			Transformer* transformer = TransformerAtFast(i);
235fb07ece0SStephan Aßmus			BMessage transformerArchive;
236fb07ece0SStephan Aßmus			ret = transformer->Archive(&transformerArchive);
237fb07ece0SStephan Aßmus			if (ret == B_OK)
238fb07ece0SStephan Aßmus				ret = into->AddMessage("transformer", &transformerArchive);
239fb07ece0SStephan Aßmus			if (ret < B_OK)
240fb07ece0SStephan Aßmus				break;
241fb07ece0SStephan Aßmus		}
242fb07ece0SStephan Aßmus	}
243fb07ece0SStephan Aßmus
244fb07ece0SStephan Aßmus	// transformation
245fb07ece0SStephan Aßmus	if (ret == B_OK) {
246fb07ece0SStephan Aßmus		int32 size = Transformable::matrix_size;
247fb07ece0SStephan Aßmus		double matrix[size];
248fb07ece0SStephan Aßmus		StoreTo(matrix);
249fb07ece0SStephan Aßmus		ret = into->AddData("transformation", B_DOUBLE_TYPE,
250fb07ece0SStephan Aßmus							matrix, size * sizeof(double));
251fb07ece0SStephan Aßmus	}
252fb07ece0SStephan Aßmus
253fb07ece0SStephan Aßmus	// hinting
254fb07ece0SStephan Aßmus	if (ret ==B_OK)
255fb07ece0SStephan Aßmus		ret = into->AddBool("hinting", fHinting);
256fb07ece0SStephan Aßmus
257fb07ece0SStephan Aßmus	// min visibility scale
258fb07ece0SStephan Aßmus	if (ret ==B_OK)
259fb07ece0SStephan Aßmus		ret = into->AddFloat("min visibility scale",
260fb07ece0SStephan Aßmus							 fMinVisibilityScale);
261fb07ece0SStephan Aßmus
262fb07ece0SStephan Aßmus	// max visibility scale
263fb07ece0SStephan Aßmus	if (ret ==B_OK)
264fb07ece0SStephan Aßmus		ret = into->AddFloat("max visibility scale",
265fb07ece0SStephan Aßmus							 fMaxVisibilityScale);
266fb07ece0SStephan Aßmus
267fb07ece0SStephan Aßmus	return ret;
268fb07ece0SStephan Aßmus}
269fb07ece0SStephan Aßmus
270fb07ece0SStephan Aßmus// MakePropertyObject
271fb07ece0SStephan AßmusPropertyObject*
272fb07ece0SStephan AßmusShape::MakePropertyObject() const
273fb07ece0SStephan Aßmus{
274fb07ece0SStephan Aßmus	PropertyObject* object = IconObject::MakePropertyObject();
275fb07ece0SStephan Aßmus	if (!object)
276fb07ece0SStephan Aßmus		return NULL;
277fb07ece0SStephan Aßmus
27827dd2109SStephan Aßmus//	object->AddProperty(new BoolProperty(PROPERTY_HINTING, fHinting));
279fb07ece0SStephan Aßmus
280fb07ece0SStephan Aßmus	object->AddProperty(new FloatProperty(PROPERTY_MIN_VISIBILITY_SCALE,
2812f953b71SStephan Aßmus										  fMinVisibilityScale, 0, 4));
282fb07ece0SStephan Aßmus
283fb07ece0SStephan Aßmus	object->AddProperty(new FloatProperty(PROPERTY_MAX_VISIBILITY_SCALE,
2842f953b71SStephan Aßmus										  fMaxVisibilityScale, 0, 4));
285fb07ece0SStephan Aßmus
286fb07ece0SStephan Aßmus	return object;
287fb07ece0SStephan Aßmus}
288fb07ece0SStephan Aßmus
289fb07ece0SStephan Aßmus// SetToPropertyObject
290fb07ece0SStephan Aßmusbool
291fb07ece0SStephan AßmusShape::SetToPropertyObject(const PropertyObject* object)
292fb07ece0SStephan Aßmus{
293fb07ece0SStephan Aßmus	AutoNotificationSuspender _(this);
294fb07ece0SStephan Aßmus	IconObject::SetToPropertyObject(object);
295fb07ece0SStephan Aßmus
296fb07ece0SStephan Aßmus	// hinting
29727dd2109SStephan Aßmus//	SetHinting(object->Value(PROPERTY_HINTING, fHinting));
298fb07ece0SStephan Aßmus
299fb07ece0SStephan Aßmus	// min visibility scale
300fb07ece0SStephan Aßmus	SetMinVisibilityScale(object->Value(PROPERTY_MIN_VISIBILITY_SCALE,
301fb07ece0SStephan Aßmus										fMinVisibilityScale));
302fb07ece0SStephan Aßmus
303fb07ece0SStephan Aßmus	// max visibility scale
304fb07ece0SStephan Aßmus	SetMaxVisibilityScale(object->Value(PROPERTY_MAX_VISIBILITY_SCALE,
305fb07ece0SStephan Aßmus										fMaxVisibilityScale));
306fb07ece0SStephan Aßmus
307fb07ece0SStephan Aßmus	return HasPendingNotifications();
308fb07ece0SStephan Aßmus}
309fb07ece0SStephan Aßmus
310fb07ece0SStephan Aßmus// #pragma mark -
311fb07ece0SStephan Aßmus
312fb07ece0SStephan Aßmus// TransformationChanged
313fb07ece0SStephan Aßmusvoid
314fb07ece0SStephan AßmusShape::TransformationChanged()
315fb07ece0SStephan Aßmus{
316fb07ece0SStephan Aßmus	// TODO: notify appearance change
317fb07ece0SStephan Aßmus	_NotifyRerender();
318fb07ece0SStephan Aßmus}
319fb07ece0SStephan Aßmus
320fb07ece0SStephan Aßmus// #pragma mark -
321fb07ece0SStephan Aßmus
322fb07ece0SStephan Aßmus// ObjectChanged
323fb07ece0SStephan Aßmusvoid
324fb07ece0SStephan AßmusShape::ObjectChanged(const Observable* object)
325fb07ece0SStephan Aßmus{
326fb07ece0SStephan Aßmus	// simply pass on the event for now
327fb07ece0SStephan Aßmus	// (a path, transformer or the style changed,
328fb07ece0SStephan Aßmus	// the shape needs to be re-rendered)
329fb07ece0SStephan Aßmus	_NotifyRerender();
330fb07ece0SStephan Aßmus}
331fb07ece0SStephan Aßmus
332fb07ece0SStephan Aßmus// #pragma mark -
333fb07ece0SStephan Aßmus
334fb07ece0SStephan Aßmus// PathAdded
335fb07ece0SStephan Aßmusvoid
336014c7e94SStephan AßmusShape::PathAdded(VectorPath* path, int32 index)
337fb07ece0SStephan Aßmus{
3380cbb6c11SStephan Aßmus	path->AcquireReference();
339fb07ece0SStephan Aßmus	path->AddListener(this);
340fb07ece0SStephan Aßmus	_NotifyRerender();
341fb07ece0SStephan Aßmus}
342fb07ece0SStephan Aßmus
343fb07ece0SStephan Aßmus// PathRemoved
344fb07ece0SStephan Aßmusvoid
345fb07ece0SStephan AßmusShape::PathRemoved(VectorPath* path)
346fb07ece0SStephan Aßmus{
347fb07ece0SStephan Aßmus	path->RemoveListener(this);
348fb07ece0SStephan Aßmus	_NotifyRerender();
3490cbb6c11SStephan Aßmus	path->ReleaseReference();
350fb07ece0SStephan Aßmus}
351fb07ece0SStephan Aßmus
352fb07ece0SStephan Aßmus// #pragma mark -
353fb07ece0SStephan Aßmus
354fb07ece0SStephan Aßmus// PointAdded
355fb07ece0SStephan Aßmusvoid
356fb07ece0SStephan AßmusShape::PointAdded(int32 index)
357fb07ece0SStephan Aßmus{
358fb07ece0SStephan Aßmus	_NotifyRerender();
359fb07ece0SStephan Aßmus}
360fb07ece0SStephan Aßmus
361fb07ece0SStephan Aßmus// PointRemoved
362fb07ece0SStephan Aßmusvoid
363fb07ece0SStephan AßmusShape::PointRemoved(int32 index)
364fb07ece0SStephan Aßmus{
365fb07ece0SStephan Aßmus	_NotifyRerender();
366fb07ece0SStephan Aßmus}
367fb07ece0SStephan Aßmus
368fb07ece0SStephan Aßmus// PointChanged
369fb07ece0SStephan Aßmusvoid
370fb07ece0SStephan AßmusShape::PointChanged(int32 index)
371fb07ece0SStephan Aßmus{
372fb07ece0SStephan Aßmus	_NotifyRerender();
373fb07ece0SStephan Aßmus}
374fb07ece0SStephan Aßmus
375fb07ece0SStephan Aßmus// PathChanged
376fb07ece0SStephan Aßmusvoid
377fb07ece0SStephan AßmusShape::PathChanged()
378fb07ece0SStephan Aßmus{
379fb07ece0SStephan Aßmus	_NotifyRerender();
380fb07ece0SStephan Aßmus}
381fb07ece0SStephan Aßmus
382fb07ece0SStephan Aßmus// PathClosedChanged
383fb07ece0SStephan Aßmusvoid
384fb07ece0SStephan AßmusShape::PathClosedChanged()
385fb07ece0SStephan Aßmus{
386fb07ece0SStephan Aßmus	_NotifyRerender();
387fb07ece0SStephan Aßmus}
388fb07ece0SStephan Aßmus
389fb07ece0SStephan Aßmus// PathReversed
390fb07ece0SStephan Aßmusvoid
391fb07ece0SStephan AßmusShape::PathReversed()
392fb07ece0SStephan Aßmus{
393fb07ece0SStephan Aßmus	_NotifyRerender();
394fb07ece0SStephan Aßmus}
395fb07ece0SStephan Aßmus
396fb07ece0SStephan Aßmus#endif // ICON_O_MATIC
397fb07ece0SStephan Aßmus
398fb07ece0SStephan Aßmus
399fb07ece0SStephan Aßmus// #pragma mark -
400fb07ece0SStephan Aßmus
401fb07ece0SStephan Aßmus// InitCheck
402fb07ece0SStephan Aßmusstatus_t
403fb07ece0SStephan AßmusShape::InitCheck() const
404fb07ece0SStephan Aßmus{
405fb07ece0SStephan Aßmus	return fPaths ? B_OK : B_NO_MEMORY;
406fb07ece0SStephan Aßmus}
407fb07ece0SStephan Aßmus
408fb07ece0SStephan Aßmus// #pragma mark -
409fb07ece0SStephan Aßmus
410fb07ece0SStephan Aßmus// SetStyle
411fb07ece0SStephan Aßmusvoid
412fb07ece0SStephan AßmusShape::SetStyle(::Style* style)
413fb07ece0SStephan Aßmus{
414fb07ece0SStephan Aßmus	if (fStyle == style)
415fb07ece0SStephan Aßmus		return;
416fb07ece0SStephan Aßmus
4178b8d44bfSMichael Lotz#ifdef ICON_O_MATIC
418fb07ece0SStephan Aßmus	if (fStyle) {
419fb07ece0SStephan Aßmus		fStyle->RemoveObserver(this);
4200cbb6c11SStephan Aßmus		fStyle->ReleaseReference();
421fb07ece0SStephan Aßmus	}
422fb07ece0SStephan Aßmus	::Style* oldStyle = fStyle;
423fb07ece0SStephan Aßmus#endif
424fb07ece0SStephan Aßmus
425fb07ece0SStephan Aßmus	fStyle = style;
426fb07ece0SStephan Aßmus
427fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
428fb07ece0SStephan Aßmus	if (fStyle) {
4290cbb6c11SStephan Aßmus		fStyle->AcquireReference();
430fb07ece0SStephan Aßmus		fStyle->AddObserver(this);
431fb07ece0SStephan Aßmus	}
432fb07ece0SStephan Aßmus
433fb07ece0SStephan Aßmus	_NotifyStyleChanged(oldStyle, fStyle);
434fb07ece0SStephan Aßmus#endif
435fb07ece0SStephan Aßmus}
436fb07ece0SStephan Aßmus
437fb07ece0SStephan Aßmus// #pragma mark -
438fb07ece0SStephan Aßmus
439fb07ece0SStephan Aßmus// Bounds
440fb07ece0SStephan AßmusBRect
441fb07ece0SStephan AßmusShape::Bounds(bool updateLast) const
442fb07ece0SStephan Aßmus{
443fb07ece0SStephan Aßmus	// TODO: what about sub-paths?!?
444fb07ece0SStephan Aßmus	// the problem is that the path ids are
445fb07ece0SStephan Aßmus	// nowhere stored while converting VectorPath
446fb07ece0SStephan Aßmus	// to agg::path_storage, but it is also unclear
447fb07ece0SStephan Aßmus	// if those would mean anything later on in
448fb07ece0SStephan Aßmus	// the Transformer pipeline
449fb07ece0SStephan Aßmus	uint32 pathID[1];
450fb07ece0SStephan Aßmus	pathID[0] = 0;
451fb07ece0SStephan Aßmus	double left, top, right, bottom;
452fb07ece0SStephan Aßmus
453fb07ece0SStephan Aßmus	::VertexSource& source = const_cast<Shape*>(this)->VertexSource();
454fb07ece0SStephan Aßmus	agg::conv_transform< ::VertexSource, Transformable>
455fb07ece0SStephan Aßmus			transformedSource(source, *this);
456fb07ece0SStephan Aßmus	agg::bounding_rect(transformedSource, pathID, 0, 1,
457fb07ece0SStephan Aßmus					   &left, &top, &right, &bottom);
458fb07ece0SStephan Aßmus
459fb07ece0SStephan Aßmus	BRect bounds(left, top, right, bottom);
460fb07ece0SStephan Aßmus
461fb07ece0SStephan Aßmus	if (updateLast)
462fb07ece0SStephan Aßmus		fLastBounds = bounds;
463fb07ece0SStephan Aßmus
464fb07ece0SStephan Aßmus	return bounds;
465fb07ece0SStephan Aßmus}
466fb07ece0SStephan Aßmus
467fb07ece0SStephan Aßmus// VertexSource
468fb07ece0SStephan Aßmus::VertexSource&
469fb07ece0SStephan AßmusShape::VertexSource()
470fb07ece0SStephan Aßmus{
471fb07ece0SStephan Aßmus	::VertexSource* source = &fPathSource;
472fb07ece0SStephan Aßmus
473fb07ece0SStephan Aßmus	int32 count = fTransformers.CountItems();
474fb07ece0SStephan Aßmus	for (int32 i = 0; i < count; i++) {
475fb07ece0SStephan Aßmus		Transformer* t = (Transformer*)fTransformers.ItemAtFast(i);
476fb07ece0SStephan Aßmus		t->SetSource(*source);
477fb07ece0SStephan Aßmus		source = t;
478fb07ece0SStephan Aßmus	}
479fb07ece0SStephan Aßmus
480fb07ece0SStephan Aßmus	if (fNeedsUpdate) {
481fb07ece0SStephan Aßmus		fPathSource.Update(source->WantsOpenPaths(),
482fb07ece0SStephan Aßmus						   source->ApproximationScale());
483fb07ece0SStephan Aßmus		fNeedsUpdate = false;
484fb07ece0SStephan Aßmus	}
485fb07ece0SStephan Aßmus
486fb07ece0SStephan Aßmus	return *source;
487fb07ece0SStephan Aßmus}
488fb07ece0SStephan Aßmus
48912a257d7SStephan Aßmus// SetGlobalScale
49012a257d7SStephan Aßmusvoid
49112a257d7SStephan AßmusShape::SetGlobalScale(double scale)
49212a257d7SStephan Aßmus{
49312a257d7SStephan Aßmus	fPathSource.SetGlobalScale(scale);
49412a257d7SStephan Aßmus}
49512a257d7SStephan Aßmus
496fb07ece0SStephan Aßmus// AddTransformer
497fb07ece0SStephan Aßmusbool
498fb07ece0SStephan AßmusShape::AddTransformer(Transformer* transformer)
499fb07ece0SStephan Aßmus{
500fb07ece0SStephan Aßmus	return AddTransformer(transformer, CountTransformers());
501fb07ece0SStephan Aßmus}
502fb07ece0SStephan Aßmus
503fb07ece0SStephan Aßmus// AddTransformer
504fb07ece0SStephan Aßmusbool
505fb07ece0SStephan AßmusShape::AddTransformer(Transformer* transformer, int32 index)
506fb07ece0SStephan Aßmus{
507fb07ece0SStephan Aßmus	if (!transformer)
508fb07ece0SStephan Aßmus		return false;
509fb07ece0SStephan Aßmus
510fb07ece0SStephan Aßmus	if (!fTransformers.AddItem((void*)transformer, index))
511fb07ece0SStephan Aßmus		return false;
512fb07ece0SStephan Aßmus
513fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
514fb07ece0SStephan Aßmus	transformer->AddObserver(this);
515fb07ece0SStephan Aßmus
516fb07ece0SStephan Aßmus	_NotifyTransformerAdded(transformer, index);
51738c71d13SStephan Aßmus#else
51838c71d13SStephan Aßmus	fNeedsUpdate = true;
519fb07ece0SStephan Aßmus#endif
520fb07ece0SStephan Aßmus	return true;
521fb07ece0SStephan Aßmus}
522fb07ece0SStephan Aßmus
523fb07ece0SStephan Aßmus// RemoveTransformer
524fb07ece0SStephan Aßmusbool
525fb07ece0SStephan AßmusShape::RemoveTransformer(Transformer* transformer)
526fb07ece0SStephan Aßmus{
527fb07ece0SStephan Aßmus	if (fTransformers.RemoveItem((void*)transformer)) {
528fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
529fb07ece0SStephan Aßmus		transformer->RemoveObserver(this);
530fb07ece0SStephan Aßmus
531fb07ece0SStephan Aßmus		_NotifyTransformerRemoved(transformer);
53238c71d13SStephan Aßmus#else
53338c71d13SStephan Aßmus		fNeedsUpdate = true;
534fb07ece0SStephan Aßmus#endif
535fb07ece0SStephan Aßmus		return true;
536fb07ece0SStephan Aßmus	}
537fb07ece0SStephan Aßmus
538fb07ece0SStephan Aßmus	return false;
539fb07ece0SStephan Aßmus}
540fb07ece0SStephan Aßmus
541fb07ece0SStephan Aßmus// #pragma mark -
542fb07ece0SStephan Aßmus
543fb07ece0SStephan Aßmus// CountShapes
544fb07ece0SStephan Aßmusint32
545fb07ece0SStephan AßmusShape::CountTransformers() const
546fb07ece0SStephan Aßmus{
547fb07ece0SStephan Aßmus	return fTransformers.CountItems();
548fb07ece0SStephan Aßmus}
549fb07ece0SStephan Aßmus
550fb07ece0SStephan Aßmus// HasTransformer
551fb07ece0SStephan Aßmusbool
552fb07ece0SStephan AßmusShape::HasTransformer(Transformer* transformer) const
553fb07ece0SStephan Aßmus{
554fb07ece0SStephan Aßmus	return fTransformers.HasItem((void*)transformer);
555fb07ece0SStephan Aßmus}
556fb07ece0SStephan Aßmus
557fb07ece0SStephan Aßmus// IndexOf
558fb07ece0SStephan Aßmusint32
559fb07ece0SStephan AßmusShape::IndexOf(Transformer* transformer) const
560fb07ece0SStephan Aßmus{
561fb07ece0SStephan Aßmus	return fTransformers.IndexOf((void*)transformer);
562fb07ece0SStephan Aßmus}
563fb07ece0SStephan Aßmus
564fb07ece0SStephan Aßmus// TransformerAt
565fb07ece0SStephan AßmusTransformer*
566fb07ece0SStephan AßmusShape::TransformerAt(int32 index) const
567fb07ece0SStephan Aßmus{
568fb07ece0SStephan Aßmus	return (Transformer*)fTransformers.ItemAt(index);
569fb07ece0SStephan Aßmus}
570fb07ece0SStephan Aßmus
571fb07ece0SStephan Aßmus// TransformerAtFast
572fb07ece0SStephan AßmusTransformer*
573fb07ece0SStephan AßmusShape::TransformerAtFast(int32 index) const
574fb07ece0SStephan Aßmus{
575fb07ece0SStephan Aßmus	return (Transformer*)fTransformers.ItemAtFast(index);
576fb07ece0SStephan Aßmus}
577fb07ece0SStephan Aßmus
578fb07ece0SStephan Aßmus// #pragma mark -
579fb07ece0SStephan Aßmus
580fb07ece0SStephan Aßmus// SetHinting
581fb07ece0SStephan Aßmusvoid
582fb07ece0SStephan AßmusShape::SetHinting(bool hinting)
583fb07ece0SStephan Aßmus{
584fb07ece0SStephan Aßmus	if (fHinting == hinting)
585fb07ece0SStephan Aßmus		return;
586fb07ece0SStephan Aßmus
587fb07ece0SStephan Aßmus	fHinting = hinting;
588fb07ece0SStephan Aßmus	Notify();
589fb07ece0SStephan Aßmus}
590fb07ece0SStephan Aßmus
591fb07ece0SStephan Aßmus// SetMinVisibilityScale
592fb07ece0SStephan Aßmusvoid
593fb07ece0SStephan AßmusShape::SetMinVisibilityScale(float scale)
594fb07ece0SStephan Aßmus{
595fb07ece0SStephan Aßmus	if (fMinVisibilityScale == scale)
596fb07ece0SStephan Aßmus		return;
597fb07ece0SStephan Aßmus
598fb07ece0SStephan Aßmus	fMinVisibilityScale = scale;
599fb07ece0SStephan Aßmus	Notify();
600fb07ece0SStephan Aßmus}
601fb07ece0SStephan Aßmus
602fb07ece0SStephan Aßmus// SetMaxVisibilityScale
603fb07ece0SStephan Aßmusvoid
604fb07ece0SStephan AßmusShape::SetMaxVisibilityScale(float scale)
605fb07ece0SStephan Aßmus{
606fb07ece0SStephan Aßmus	if (fMaxVisibilityScale == scale)
607fb07ece0SStephan Aßmus		return;
608fb07ece0SStephan Aßmus
609fb07ece0SStephan Aßmus	fMaxVisibilityScale = scale;
610fb07ece0SStephan Aßmus	Notify();
611fb07ece0SStephan Aßmus}
612fb07ece0SStephan Aßmus
613fb07ece0SStephan Aßmus// #pragma mark -
614fb07ece0SStephan Aßmus
615fb07ece0SStephan Aßmus#ifdef ICON_O_MATIC
616fb07ece0SStephan Aßmus
617fb07ece0SStephan Aßmus// AddListener
618fb07ece0SStephan Aßmusbool
619fb07ece0SStephan AßmusShape::AddListener(ShapeListener* listener)
620fb07ece0SStephan Aßmus{
621fb07ece0SStephan Aßmus	if (listener && !fListeners.HasItem((void*)listener))
622fb07ece0SStephan Aßmus		return fListeners.AddItem((void*)listener);
623fb07ece0SStephan Aßmus	return false;
624fb07ece0SStephan Aßmus}
625fb07ece0SStephan Aßmus
626fb07ece0SStephan Aßmus// RemoveListener
627fb07ece0SStephan Aßmusbool
628fb07ece0SStephan AßmusShape::RemoveListener(ShapeListener* listener)
629fb07ece0SStephan Aßmus{
630fb07ece0SStephan Aßmus	return fListeners.RemoveItem((void*)listener);
631fb07ece0SStephan Aßmus}
632fb07ece0SStephan Aßmus
633fb07ece0SStephan Aßmus// #pragma mark -
634fb07ece0SStephan Aßmus
635fb07ece0SStephan Aßmus// _NotifyTransformerAdded
636fb07ece0SStephan Aßmusvoid
637fb07ece0SStephan AßmusShape::_NotifyTransformerAdded(Transformer* transformer, int32 index) const
638fb07ece0SStephan Aßmus{
639fb07ece0SStephan Aßmus	BList listeners(fListeners);
640fb07ece0SStephan Aßmus	int32 count = listeners.CountItems();
641fb07ece0SStephan Aßmus	for (int32 i = 0; i < count; i++) {
642fb07ece0SStephan Aßmus		ShapeListener* listener
643fb07ece0SStephan Aßmus			= (ShapeListener*)listeners.ItemAtFast(i);
644fb07ece0SStephan Aßmus		listener->TransformerAdded(transformer, index);
645fb07ece0SStephan Aßmus	}
646fb07ece0SStephan Aßmus	// TODO: merge Observable and ShapeListener interface
647fb07ece0SStephan Aßmus	_NotifyRerender();
648fb07ece0SStephan Aßmus}
649fb07ece0SStephan Aßmus
650fb07ece0SStephan Aßmus// _NotifyTransformerRemoved
651fb07ece0SStephan Aßmusvoid
652fb07ece0SStephan AßmusShape::_NotifyTransformerRemoved(Transformer* transformer) const
653fb07ece0SStephan Aßmus{
654fb07ece0SStephan Aßmus	BList listeners(fListeners);
655fb07ece0SStephan Aßmus	int32 count = listeners.CountItems();
656fb07ece0SStephan Aßmus	for (int32 i = 0; i < count; i++) {
657fb07ece0SStephan Aßmus		ShapeListener* listener
658fb07ece0SStephan Aßmus			= (ShapeListener*)listeners.ItemAtFast(i);
659fb07ece0SStephan Aßmus		listener->TransformerRemoved(transformer);
660fb07ece0SStephan Aßmus	}
661fb07ece0SStephan Aßmus	// TODO: merge Observable and ShapeListener interface
662fb07ece0SStephan Aßmus	_NotifyRerender();
663fb07ece0SStephan Aßmus}
664fb07ece0SStephan Aßmus
665fb07ece0SStephan Aßmus// _NotifyStyleChanged
666fb07ece0SStephan Aßmusvoid
667fb07ece0SStephan AßmusShape::_NotifyStyleChanged(::Style* oldStyle, ::Style* newStyle) const
668fb07ece0SStephan Aßmus{
669fb07ece0SStephan Aßmus	BList listeners(fListeners);
670fb07ece0SStephan Aßmus	int32 count = listeners.CountItems();
671fb07ece0SStephan Aßmus	for (int32 i = 0; i < count; i++) {
672fb07ece0SStephan Aßmus		ShapeListener* listener
673fb07ece0SStephan Aßmus			= (ShapeListener*)listeners.ItemAtFast(i);
674fb07ece0SStephan Aßmus		listener->StyleChanged(oldStyle, newStyle);
675fb07ece0SStephan Aßmus	}
676fb07ece0SStephan Aßmus	// TODO: merge Observable and ShapeListener interface
677fb07ece0SStephan Aßmus	_NotifyRerender();
678fb07ece0SStephan Aßmus}
679fb07ece0SStephan Aßmus
680fb07ece0SStephan Aßmus// _NotifyRerender
681fb07ece0SStephan Aßmusvoid
682fb07ece0SStephan AßmusShape::_NotifyRerender() const
683fb07ece0SStephan Aßmus{
684fb07ece0SStephan Aßmus	fNeedsUpdate = true;
685fb07ece0SStephan Aßmus	Notify();
686fb07ece0SStephan Aßmus}
687fb07ece0SStephan Aßmus
688fb07ece0SStephan Aßmus#endif // ICON_O_MATIC
689fb07ece0SStephan Aßmus
690