* implemented more fine grained listener support in VectorPath

(this separates the notification for shape changes versus other
   properties and improves the performance)
* added affine properties to AffineTransformer (for testing only,
  will need to be implemented more carefully)
* added Width property to ContourTransformer
* changed the way how it is determined that paths need to stay
  open for the StrokeConverter, now it works correctly with
  sub-paths


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18064 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2006-07-07 17:33:14 +00:00
parent bbcfef1f6c
commit 05fd381837
20 changed files with 439 additions and 55 deletions

View File

@ -50,6 +50,22 @@ name_for_id(int32 id)
name = "Closed";
break;
case PROPERTY_TRANSLATION_X:
name = "Translation X";
break;
case PROPERTY_TRANSLATION_Y:
name = "Translation Y";
break;
case PROPERTY_ROTATION:
name = "Rotation";
break;
case PROPERTY_SCALE_X:
name = "Scale X";
break;
case PROPERTY_SCALE_Y:
name = "Scale Y";
break;
default:
name = "<unkown property>";
break;

View File

@ -25,6 +25,12 @@ enum {
PROPERTY_MITER_LIMIT = 'mtlm',
PROPERTY_CLOSED = 'clsd',
PROPERTY_TRANSLATION_X = 'trnx',
PROPERTY_TRANSLATION_Y = 'trny',
PROPERTY_ROTATION = 'rotn',
PROPERTY_SCALE_X = 'sclx',
PROPERTY_SCALE_Y = 'scly',
};

View File

@ -19,7 +19,6 @@
#include "support.h"
#include "CanvasView.h"
#include "VectorPath.h"
#include "AddPointCommand.h"
#include "ChangePointCommand.h"
@ -217,11 +216,14 @@ PathManipulator::PathManipulator(VectorPath* path)
fLastNudgeTime(system_time())//,
// fNudgeCommand(NULL)
{
fPath->AddListener(this);
}
// destructor
PathManipulator::~PathManipulator()
{
fPath->RemoveListener(this);
delete fChangePointCommand;
delete fInsertPointCommand;
delete fAddPointCommand;
@ -900,6 +902,50 @@ PathManipulator::ObjectChanged(const Observable* object)
// #pragma mark -
// PointAdded
void
PathManipulator::PointAdded(int32 index)
{
ObjectChanged(fPath);
}
// PointRemoved
void
PathManipulator::PointRemoved(int32 index)
{
ObjectChanged(fPath);
}
// PointChanged
void
PathManipulator::PointChanged(int32 index)
{
ObjectChanged(fPath);
}
// PathChanged
void
PathManipulator::PathChanged()
{
ObjectChanged(fPath);
}
// PathClosedChanged
void
PathManipulator::PathClosedChanged()
{
ObjectChanged(fPath);
}
// PathReversed
void
PathManipulator::PathReversed()
{
ObjectChanged(fPath);
}
// #pragma mark -
// ControlFlags
uint32
PathManipulator::ControlFlags() const

View File

@ -10,13 +10,13 @@
#define PATH_MANIPULATOR_H
#include "Manipulator.h"
#include "VectorPath.h"
class AddPointCommand;
class CanvasView;
class ChangePointCommand;
class UndoStack;
class InsertPointCommand;
class VectorPath;
//class PathSelection {
// public:
@ -29,7 +29,8 @@ class VectorPath;
// virtual Command* Delete();
//};
class PathManipulator : public Manipulator {
class PathManipulator : public Manipulator,
public PathListener {
public:
PathManipulator(VectorPath* path);
virtual ~PathManipulator();
@ -63,6 +64,14 @@ class PathManipulator : public Manipulator {
// Observer interface (Manipulator)
virtual void ObjectChanged(const Observable* object);
// PathListener interface
virtual void PointAdded(int32 index);
virtual void PointRemoved(int32 index);
virtual void PointChanged(int32 index);
virtual void PathChanged();
virtual void PathClosedChanged();
virtual void PathReversed();
// PathManipulator
uint32 ControlFlags() const;

View File

@ -7,7 +7,6 @@
#include "agg_bounding_rect.h"
#include "Style.h"
#include "VectorPath.h"
using std::nothrow;
@ -110,7 +109,7 @@ void
Shape::PathAdded(VectorPath* path)
{
path->Acquire();
path->AddObserver(this);
path->AddListener(this);
Notify();
}
@ -118,13 +117,57 @@ Shape::PathAdded(VectorPath* path)
void
Shape::PathRemoved(VectorPath* path)
{
path->RemoveObserver(this);
path->RemoveListener(this);
Notify();
path->Release();
}
// #pragma mark -
// PointAdded
void
Shape::PointAdded(int32 index)
{
Notify();
}
// PointRemoved
void
Shape::PointRemoved(int32 index)
{
Notify();
}
// PointChanged
void
Shape::PointChanged(int32 index)
{
Notify();
}
// PathChanged
void
Shape::PathChanged()
{
Notify();
}
// PathClosedChanged
void
Shape::PathClosedChanged()
{
Notify();
}
// PathReversed
void
Shape::PathReversed()
{
Notify();
}
// #pragma mark -
// InitCheck
status_t
Shape::InitCheck() const
@ -186,7 +229,6 @@ Shape::Bounds(bool updateLast) const
::VertexSource&
Shape::VertexSource()
{
fPathSource.Update();
::VertexSource* source = &fPathSource;
int32 count = fTransformers.CountItems();
@ -196,7 +238,7 @@ Shape::VertexSource()
source = t;
}
source->SetLast();
fPathSource.Update(source->WantsOpenPaths());
return *source;
}

View File

@ -8,6 +8,7 @@
#include "Observer.h"
#include "PathContainer.h"
#include "PathSource.h"
#include "VectorPath.h"
class Style;
@ -24,7 +25,8 @@ class ShapeListener {
class Shape : public IconObject,
public Observer, // observing all the paths and the style
public PathContainerListener {
public PathContainerListener,
public PathListener {
public:
Shape(::Style* style);
Shape(const Shape& other);
@ -37,6 +39,14 @@ class Shape : public IconObject,
virtual void PathAdded(VectorPath* path);
virtual void PathRemoved(VectorPath* path);
// PathListener interface
virtual void PointAdded(int32 index);
virtual void PointRemoved(int32 index);
virtual void PointChanged(int32 index);
virtual void PathChanged();
virtual void PathClosedChanged();
virtual void PathReversed();
// Shape
status_t InitCheck() const;

View File

@ -12,6 +12,8 @@
#include <stdio.h>
#include <string.h>
#include <debugger.h>
#include <Bitmap.h>
#include <Message.h>
#include <TypeConstants.h>
@ -67,11 +69,18 @@ get_path_storage(agg::path_storage& path,
return false;
}
// #pragma mark -
PathListener::PathListener() {}
PathListener::~PathListener() {}
// #pragma mark -
// constructor
VectorPath::VectorPath()
: BArchivable(),
IconObject("<path>"),
fListeners(20),
fPath(NULL),
fClosed(false),
fPointCount(0),
@ -84,6 +93,7 @@ VectorPath::VectorPath()
VectorPath::VectorPath(const VectorPath& from)
: BArchivable(),
IconObject(from),
fListeners(20),
fPath(NULL),
fPointCount(0),
fAllocCount(0),
@ -96,6 +106,7 @@ VectorPath::VectorPath(const VectorPath& from)
VectorPath::VectorPath(const BMessage* archive)
: BArchivable(),
IconObject("<path>"/*archive*/),
fListeners(20),
fPath(NULL),
fClosed(false),
fPointCount(0),
@ -134,6 +145,10 @@ VectorPath::~VectorPath()
{
if (fPath)
obj_free(fPath);
if (fListeners.CountItems() > 0)
debugger("VectorPath::~VectorPath() - "
"there are still listeners attached!");
}
// #pragma mark -
@ -251,7 +266,7 @@ VectorPath::AddPoint(BPoint point)
if (_SetPointCount(fPointCount + 1)) {
_SetPoint(index, point);
Notify();
_NotifyPointAdded(index);
return true;
}
@ -278,7 +293,7 @@ VectorPath::AddPoint(BPoint point, int32 index)
}
}
_SetPoint(index, point);
Notify();
_NotifyPointAdded(index);
return true;
}
return false;
@ -303,7 +318,7 @@ VectorPath::RemovePoint(int32 index)
fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);
Notify();
_NotifyPointRemoved(index);
return true;
}
return false;
@ -323,7 +338,7 @@ VectorPath::SetPoint(int32 index, BPoint point)
fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);
Notify();
_NotifyPointChanged(index);
return true;
}
return false;
@ -345,7 +360,7 @@ VectorPath::SetPoint(int32 index, BPoint point,
fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);
Notify();
_NotifyPointChanged(index);
return true;
}
return false;
@ -376,7 +391,7 @@ VectorPath::SetPointIn(int32 i, BPoint point)
fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);
Notify();
_NotifyPointChanged(i);
return true;
}
return false;
@ -411,7 +426,7 @@ VectorPath::SetPointOut(int32 i, BPoint point, bool mirrorDist)
fCachedBounds.Set(0.0, 0.0, -1.0, -1.0);
Notify();
_NotifyPointChanged(i);
return true;
}
return false;
@ -423,7 +438,7 @@ VectorPath::SetInOutConnected(int32 index, bool connected)
{
if (index >= 0 && index < fPointCount) {
fPath[index].connected = connected;
Notify();
_NotifyPointChanged(index);
return true;
}
return false;
@ -646,6 +661,7 @@ VectorPath::SetClosed(bool closed)
{
if (fClosed != closed) {
fClosed = closed;
_NotifyClosedChanged();
Notify();
}
}
@ -808,7 +824,7 @@ VectorPath::CleanUp()
}
if (notify)
Notify();
_NotifyPathChanged();
}
// Reverse
@ -826,7 +842,7 @@ VectorPath::Reverse()
}
*this = temp;
Notify();
_NotifyPathReversed();
}
// PrintToStream
@ -849,6 +865,26 @@ VectorPath::GetAGGPathStorage(agg::path_storage& path) const
return get_path_storage(path, fPath, fPointCount, fClosed);
}
// #pragma mark -
// AddListener
bool
VectorPath::AddListener(PathListener* listener)
{
if (listener && !fListeners.HasItem((void*)listener))
return fListeners.AddItem((void*)listener);
return false;
}
// RemoveListener
bool
VectorPath::RemoveListener(PathListener* listener)
{
return fListeners.RemoveItem((void*)listener);
}
// #pragma mark -
// _SetPoint
void
VectorPath::_SetPoint(int32 index, BPoint point)
@ -892,3 +928,78 @@ VectorPath::_SetPointCount(int32 count)
return fPath != NULL;
}
// #pragma mark -
// _NotifyPointAdded
void
VectorPath::_NotifyPointAdded(int32 index) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
PathListener* listener = (PathListener*)listeners.ItemAtFast(i);
listener->PointAdded(index);
}
}
// _NotifyPointChanged
void
VectorPath::_NotifyPointChanged(int32 index) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
PathListener* listener = (PathListener*)listeners.ItemAtFast(i);
listener->PointChanged(index);
}
}
// _NotifyPointRemoved
void
VectorPath::_NotifyPointRemoved(int32 index) const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
PathListener* listener = (PathListener*)listeners.ItemAtFast(i);
listener->PointRemoved(index);
}
}
// _NotifyPathChanged
void
VectorPath::_NotifyPathChanged() const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
PathListener* listener = (PathListener*)listeners.ItemAtFast(i);
listener->PathChanged();
}
}
// _NotifyClosedChanged
void
VectorPath::_NotifyClosedChanged() const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
PathListener* listener = (PathListener*)listeners.ItemAtFast(i);
listener->PathClosedChanged();
}
}
// _NotifyPathReversed
void
VectorPath::_NotifyPathReversed() const
{
BList listeners(fListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
PathListener* listener = (PathListener*)listeners.ItemAtFast(i);
listener->PathReversed();
}
}

View File

@ -10,6 +10,7 @@
#define VECTOR_PATH_H
#include <Archivable.h>
#include <List.h>
#include <Rect.h>
#include <String.h>
@ -28,6 +29,19 @@ struct control_point {
bool connected; // if all 3 points should be on one line
};
class PathListener {
public:
PathListener();
virtual ~PathListener();
virtual void PointAdded(int32 index) = 0;
virtual void PointRemoved(int32 index) = 0;
virtual void PointChanged(int32 index) = 0;
virtual void PathChanged() = 0;
virtual void PathClosedChanged() = 0;
virtual void PathReversed() = 0;
};
class VectorPath : public BArchivable,
public IconObject {
public:
@ -126,13 +140,24 @@ class VectorPath : public BArchivable,
bool GetAGGPathStorage(agg::path_storage& path) const;
bool AddListener(PathListener* listener);
bool RemoveListener(PathListener* listener);
private:
BRect _Bounds() const;
void _SetPoint(int32 index, BPoint point);
bool _SetPointCount(int32 count);
control_point* fPath;
void _NotifyPointAdded(int32 index) const;
void _NotifyPointChanged(int32 index) const;
void _NotifyPointRemoved(int32 index) const;
void _NotifyPathChanged() const;
void _NotifyClosedChanged() const;
void _NotifyPathReversed() const;
BList fListeners;
control_point* fPath;
bool fClosed;
int32 fPointCount;

View File

@ -8,6 +8,10 @@
#include "AffineTransformer.h"
#include "CommonPropertyIDs.h"
#include "Property.h"
#include "PropertyObject.h"
// constructor
AffineTransformer::AffineTransformer(VertexSource& source)
: Transformer(source, "Transformation"),
@ -42,10 +46,79 @@ AffineTransformer::SetSource(VertexSource& source)
Affine::attach(source);
}
// SetLast
void
AffineTransformer::SetLast()
// #pragma mark -
// MakePropertyObject
PropertyObject*
AffineTransformer::MakePropertyObject() const
{
fSource.SetLast();
PropertyObject* object = Transformer::MakePropertyObject();
if (!object)
return NULL;
// translation
double tx;
double ty;
translation(&tx, &ty);
object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_X, tx));
object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_Y, ty));
// rotation
object->AddProperty(new FloatProperty(PROPERTY_ROTATION,
agg::rad2deg(rotation())));
// scale
double scaleX;
double scaleY;
scaling(&scaleX, &scaleY);
object->AddProperty(new FloatProperty(PROPERTY_SCALE_X, scaleX));
object->AddProperty(new FloatProperty(PROPERTY_SCALE_Y, scaleY));
return object;
}
// SetToPropertyObject
bool
AffineTransformer::SetToPropertyObject(const PropertyObject* object)
{
AutoNotificationSuspender _(this);
Transformer::SetToPropertyObject(object);
// current affine parameters
double tx;
double ty;
translation(&tx, &ty);
double r = rotation();
double scaleX;
double scaleY;
scaling(&scaleX, &scaleY);
// properties
double newTX = object->Value(PROPERTY_TRANSLATION_X, (float)tx);
double newTY = object->Value(PROPERTY_TRANSLATION_Y, (float)ty);
double newR = object->Value(PROPERTY_ROTATION,
(float)agg::rad2deg(r));
newR = agg::deg2rad(newR);
double newScaleX = object->Value(PROPERTY_SCALE_X, (float)scaleX);
double newScaleY = object->Value(PROPERTY_SCALE_Y, (float)scaleY);
if (newTX != tx || newTY != ty
|| newR != r
|| newScaleX != scaleX
|| newScaleY != scaleY) {
reset();
multiply(agg::trans_affine_scaling(newScaleX, newScaleY));
multiply(agg::trans_affine_rotation(newR));
multiply(agg::trans_affine_translation(newTX, newTY));
Notify();
}
return HasPendingNotifications();
}

View File

@ -29,7 +29,11 @@ class AffineTransformer : public Transformer,
virtual unsigned vertex(double* x, double* y);
virtual void SetSource(VertexSource& source);
virtual void SetLast();
// IconObject interface
virtual PropertyObject* MakePropertyObject() const;
virtual bool SetToPropertyObject(
const PropertyObject* object);
};
#endif // AFFINE_TRANSFORMER_H

View File

@ -8,6 +8,10 @@
#include "ContourTransformer.h"
#include "CommonPropertyIDs.h"
#include "Property.h"
#include "PropertyObject.h"
// constructor
ContourTransformer::ContourTransformer(VertexSource& source)
: Transformer(source, "Contour"),
@ -42,10 +46,38 @@ ContourTransformer::SetSource(VertexSource& source)
Contour::attach(source);
}
// SetLast
void
ContourTransformer::SetLast()
// #pragma mark -
// MakePropertyObject
PropertyObject*
ContourTransformer::MakePropertyObject() const
{
fSource.SetLast();
PropertyObject* object = Transformer::MakePropertyObject();
if (!object)
return NULL;
// width
object->AddProperty(new FloatProperty(PROPERTY_WIDTH, width()));
return object;
}
// SetToPropertyObject
bool
ContourTransformer::SetToPropertyObject(const PropertyObject* object)
{
AutoNotificationSuspender _(this);
Transformer::SetToPropertyObject(object);
// width
float w = object->Value(PROPERTY_WIDTH, (float)width());
if (w != width()) {
width(w);
Notify();
}
return HasPendingNotifications();
}

View File

@ -26,7 +26,11 @@ class ContourTransformer : public Transformer,
virtual unsigned vertex(double* x, double* y);
virtual void SetSource(VertexSource& source);
virtual void SetLast();
// IconObject interface
virtual PropertyObject* MakePropertyObject() const;
virtual bool SetToPropertyObject(
const PropertyObject* object);
};
#endif // CONTOUR_TRANSFORMER_H

View File

@ -39,21 +39,23 @@ PathSource::vertex(double* x, double* y)
return fAGGCurvedPath.vertex(x, y);
}
// SetLast
void
PathSource::SetLast()
{
fAGGPath.close_polygon();
}
// Update
void
PathSource::Update()
PathSource::Update(bool leavePathsOpen)
{
fAGGPath.remove_all();
int32 count = fPaths->CountPaths();
for (int32 i = 0; i < count; i++)
for (int32 i = 0; i < count; i++) {
fPaths->PathAtFast(i)->GetAGGPathStorage(fAGGPath);
if (!leavePathsOpen)
fAGGPath.close_polygon();
}
}
// WantsOpenPaths
bool
PathSource::WantsOpenPaths() const
{
return false;
}

View File

@ -28,9 +28,10 @@ class PathSource : public VertexSource {
virtual void rewind(unsigned path_id);
virtual unsigned vertex(double* x, double* y);
virtual void SetLast();
virtual bool WantsOpenPaths() const;
void Update();
// PathSource
void Update(bool leavePathsOpen);
private:
PathContainer* fPaths;

View File

@ -42,12 +42,6 @@ PerspectiveTransformer::SetSource(VertexSource& source)
Perspective::attach(source);
}
// SetLast
void
PerspectiveTransformer::SetLast()
{
fSource.SetLast();
}

View File

@ -29,7 +29,6 @@ class PerspectiveTransformer : public Transformer,
virtual unsigned vertex(double* x, double* y);
virtual void SetSource(VertexSource& source);
virtual void SetLast();
};
#endif // PERSPECTIVE_TRANSFORMER_H

View File

@ -47,6 +47,13 @@ StrokeTransformer::SetSource(VertexSource& source)
Stroke::attach(source);
}
// WantsOpenPaths
bool
StrokeTransformer::WantsOpenPaths() const
{
return true;
}
// #pragma mark -
// MakePropertyObject

View File

@ -26,6 +26,7 @@ class StrokeTransformer : public Transformer,
virtual unsigned vertex(double* x, double* y);
virtual void SetSource(VertexSource& source);
virtual bool WantsOpenPaths() const;
// IconObject interface
virtual PropertyObject* MakePropertyObject() const;

View File

@ -18,12 +18,6 @@ VertexSource::~VertexSource()
{
}
// Finish
void
VertexSource::SetLast()
{
}
// #pragma mark -
// constructor
@ -59,4 +53,10 @@ Transformer::SetSource(VertexSource& source)
fSource = source;
}
// WantsOpenPaths
bool
Transformer::WantsOpenPaths() const
{
return fSource.WantsOpenPaths();
}

View File

@ -19,7 +19,7 @@ class VertexSource {
virtual void rewind(unsigned path_id) = 0;
virtual unsigned vertex(double* x, double* y) = 0;
virtual void SetLast();
virtual bool WantsOpenPaths() const = 0;
};
@ -35,6 +35,8 @@ class Transformer : public VertexSource,
virtual void SetSource(VertexSource& source);
virtual bool WantsOpenPaths() const;
protected:
VertexSource& fSource;
};