summaryrefslogtreecommitdiffstats
path: root/kig/objects/object_calcer.h
diff options
context:
space:
mode:
Diffstat (limited to 'kig/objects/object_calcer.h')
-rw-r--r--kig/objects/object_calcer.h301
1 files changed, 301 insertions, 0 deletions
diff --git a/kig/objects/object_calcer.h b/kig/objects/object_calcer.h
new file mode 100644
index 00000000..6df94fe8
--- /dev/null
+++ b/kig/objects/object_calcer.h
@@ -0,0 +1,301 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301, USA.
+
+#ifndef KIG_OBJECTS_OBJECT_CALCER_H
+#define KIG_OBJECTS_OBJECT_CALCER_H
+
+#include "common.h"
+#include "../misc/boost_intrusive_pointer.hpp"
+
+class ObjectCalcer;
+
+void intrusive_ptr_add_ref( ObjectCalcer* p );
+void intrusive_ptr_release( ObjectCalcer* p );
+
+/**
+ * An ObjectCalcer is an object that represents an algorithm for
+ * calculating an ObjectImp from other ObjectImp's. It is also a node
+ * in the dependency graph of a certain document. E.g. a LineImp can
+ * be calculated from the two PointImp's it has to go through; every
+ * time either of them moves, this calculation is redone. In this
+ * case, there would be an ObjectCalcer that keeps a reference to its
+ * two parents ( the ObjectCalcer's representing the points ), and
+ * that will calculate its ObjectImp value every time it is asked to
+ * do so ( i.e. every time one of its parents moves.. ).
+ *
+ * Each ObjectHolder keeps its ObjectImp itself, and recalculates it
+ * from its parents in its calc() method ( if necessary ).
+ *
+ * Because of the complex relations that ObjectCalcer's hold to other
+ * ObjectCalcer's and to other classes, they have been made
+ * reference-counted. This means that they keep a count internally of
+ * how much times a pointer to them is held. If this count reaches 0,
+ * this means that nobody needs them anymore, and they delete
+ * themselves. E.g. an ObjectCalcer always keeps a reference to its
+ * parents, to ensure that those aren't deleted before it is deleted.
+ *
+ * At runtime, there will be an entire graph of ObjectCalcer that
+ * depend on their parents.. At the bottom, there are Calcer's that
+ * the user is aware of, and that are held by ObjectHolder's. At the
+ * top, there are Calcer's without parents that serve only to hold
+ * some data. Those are most likely ObjectConstCalcer's. There are
+ * some algorithms to work with the dependency graph in various ways
+ * in ../misc/calcpath.h
+ *
+ * ObjectCalcer's also decide how an object should be allowed to
+ * move. If the user selects a point, and tries to move it, then its
+ * ObjectCalcer will be asked whether it can move, and if so, will be
+ * asked to move. See below with the canMove(), move() and
+ * moveReferencePoint() methods..
+ */
+class ObjectCalcer
+{
+protected:
+ /**
+ * ObjectCalcer's are reference counted.. They all take a reference
+ * to their parents, and some other classes like ObjectHolder take a
+ * reference to some ObjectCalcer's that they don't want to see
+ * deleted..
+ */
+ friend void intrusive_ptr_add_ref( ObjectCalcer* p );
+ friend void intrusive_ptr_release( ObjectCalcer* p );
+ int refcount;
+ void ref();
+ void deref();
+
+ // we keep track of our children, so algorithms can easily walk over
+ // the dependency graph..
+
+ std::vector<ObjectCalcer*> mchildren;
+
+ ObjectCalcer();
+public:
+ /**
+ * a calcer should call this to register itself as a child of this
+ * calcer. This automatically takes a reference.
+ */
+ void addChild( ObjectCalcer* c );
+ /**
+ * a calcer should call this in its destructor, to inform its parent
+ * that it is no longer a child of this calcer. This will release
+ * the reference taken in addChild..
+ */
+ void delChild( ObjectCalcer* c );
+
+ // use this pointer type to keep a reference to an ObjectCalcer...
+ typedef myboost::intrusive_ptr<ObjectCalcer> shared_ptr;
+
+ /**
+ * Returns the child ObjectCalcer's of this ObjectCalcer.
+ */
+ std::vector<ObjectCalcer*> children() const;
+
+ virtual ~ObjectCalcer();
+ /**
+ * Returns the parent ObjectCalcer's of this ObjectCalcer.
+ */
+ virtual std::vector<ObjectCalcer*> parents() const = 0;
+ /**
+ * Returns the ObjectImp of this ObjectCalcer.
+ */
+ virtual const ObjectImp* imp() const = 0;
+ /**
+ * Makes the ObjectCalcer recalculate its ObjectImp from its
+ * parents.
+ */
+ virtual void calc( const KigDocument& ) = 0;
+
+ /**
+ * An ObjectCalcer expects its parents to have an ObjectImp of a
+ * certain type. This method returns the ObjectImpType that \p o
+ * should have. \p os is a list of all the parents in order, and
+ * \p o is part of it. This method will return the ObjectImpType
+ * that the parent should *at least* be. For example, a Translated
+ * object can translate any sort of object, so it will return
+ * ObjectImp::stype() here ( the topmost ObjectImpType, that all
+ * other ObjectImpType's inherit ).
+ */
+ virtual const ObjectImpType* impRequirement(
+ ObjectCalcer* o, const std::vector<ObjectCalcer*>& os ) const = 0;
+
+ /**
+ * Returns whether this ObjectCalcer supports moving.
+ */
+ virtual bool canMove() const;
+ /**
+ * Returns whether this ObjectCalcer can be translated at any position
+ * in the coordinate plane. Note that a ConstrainedPointType can be
+ * moved, but cannot be moved everywhere.
+ */
+ virtual bool isFreelyTranslatable() const;
+ /**
+ * Moving an object most of the time signifies invoking changes in
+ * some of its parents. This method returns the set of parents that
+ * will be changed in the move() method. The object itself should
+ * not be included.
+ */
+ virtual std::vector<ObjectCalcer*> movableParents() const;
+ /**
+ * In order to support simultaneously moving objects that are in
+ * different locations, we need for each object a location that it
+ * is assumed to be at, at the moment the moving starts. This
+ * method returns such a point.
+ */
+ virtual Coordinate moveReferencePoint() const;
+ /**
+ * This is the method that does the real moving work. It will be
+ * invoked to tell the object to move to the new location to. After
+ * this, the calc() method will be calced, so you only need to do
+ * the real changes in this method, updating the ObjectImp should be
+ * done in the calc() method, not here.
+ */
+ virtual void move( const Coordinate& to, const KigDocument& doc );
+
+ /**
+ * If this ObjectCalcer represents a curve, return true if the given
+ * point is by construction on this curve. If this ObjectCalcer
+ * represents a point, return true if this point is by construction
+ * on the given curve.
+ */
+ virtual bool isDefinedOnOrThrough( const ObjectCalcer* o ) const = 0;
+};
+
+/**
+ * This is an ObjectCalcer that uses one of the various ObjectType's
+ * to calculate its ObjectImp. It basically forwards all of its
+ * functionality to the ObjectType that it holds a pointer to.
+ */
+class ObjectTypeCalcer
+ : public ObjectCalcer
+{
+ std::vector<ObjectCalcer*> mparents;
+ const ObjectType* mtype;
+ ObjectImp* mimp;
+public:
+ typedef myboost::intrusive_ptr<ObjectTypeCalcer> shared_ptr;
+ /**
+ * Construct a new ObjectTypeCalcer with a given type and parents.
+ */
+// ObjectTypeCalcer( const ObjectType* type, const std::vector<ObjectCalcer*>& parents );
+ /**
+ * the sort boolean tells whether the sortArgs method should be invoked or not;
+ * if not present
+ */
+ ObjectTypeCalcer( const ObjectType* type, const std::vector<ObjectCalcer*>& parents, bool sort=true );
+ ~ObjectTypeCalcer();
+
+ const ObjectImp* imp() const;
+ std::vector<ObjectCalcer*> parents() const;
+ void calc( const KigDocument& doc );
+
+ /**
+ * Set the parents of this ObjectTypeCalcer to np. This object will
+ * release the reference it had to its old parents, and take a new
+ * one on the new parents.
+ */
+ void setParents( const std::vector<ObjectCalcer*> np );
+ void setType( const ObjectType* t );
+
+ const ObjectType* type() const;
+
+ const ObjectImpType* impRequirement(
+ ObjectCalcer* o, const std::vector<ObjectCalcer*>& os ) const;
+ bool isDefinedOnOrThrough( const ObjectCalcer* o ) const;
+ bool canMove() const;
+ bool isFreelyTranslatable() const;
+ std::vector<ObjectCalcer*> movableParents() const;
+ Coordinate moveReferencePoint() const;
+ void move( const Coordinate& to, const KigDocument& doc );
+};
+
+/**
+ * This is an ObjectCalcer that keeps an ObjectImp, and never
+ * calculates a new one. It is a trivial, but very useful
+ * ObjectCalcer. It is used often in Kig, for holding data to be used
+ * by other ObjectCalcer's.
+ */
+class ObjectConstCalcer
+ : public ObjectCalcer
+{
+ ObjectImp* mimp;
+public:
+ typedef myboost::intrusive_ptr<ObjectConstCalcer> shared_ptr;
+
+ /**
+ * Construct a new ObjectConstCalcer with the given imp as the
+ * stored ObjectImp.
+ *
+ * This class takes ownership of the imp you pass it, it should have
+ * been constructed using new, and this class is responsible for
+ * deleting it.
+ */
+ ObjectConstCalcer( ObjectImp* imp );
+ ~ObjectConstCalcer();
+
+ const ObjectImp* imp() const;
+ void calc( const KigDocument& doc );
+ std::vector<ObjectCalcer*> parents() const;
+
+ /**
+ * Set the ObjectImp of this ObjectConstCalcer to the given
+ * newimp. The old one will be deleted.
+ */
+ void setImp( ObjectImp* newimp );
+ /**
+ * Set the ObjectImp of this ObjectConstCalcer to the given
+ * newimp. The old one will not be deleted, but returned.
+ */
+ ObjectImp* switchImp( ObjectImp* newimp );
+
+ const ObjectImpType* impRequirement(
+ ObjectCalcer* o, const std::vector<ObjectCalcer*>& os ) const;
+ bool isDefinedOnOrThrough( const ObjectCalcer* o ) const;
+};
+
+/**
+ * This is an ObjectCalcer that has a single parent, and gets a
+ * certain property from it in its calc() method.
+ *
+ * \see ObjectImp::property
+ */
+class ObjectPropertyCalcer
+ : public ObjectCalcer
+{
+ ObjectImp* mimp;
+ ObjectCalcer* mparent;
+ int mpropid;
+public:
+ /**
+ * Construct a new ObjectPropertyCalcer, that will get the property
+ * from parent with number propid.
+ */
+ ObjectPropertyCalcer( ObjectCalcer* parent, int propid );
+ ~ObjectPropertyCalcer();
+
+ const ObjectImp* imp() const;
+ std::vector<ObjectCalcer*> parents() const;
+ void calc( const KigDocument& doc );
+
+ int propId() const;
+ ObjectCalcer* parent() const;
+
+ const ObjectImpType* impRequirement(
+ ObjectCalcer* o, const std::vector<ObjectCalcer*>& os ) const;
+ bool isDefinedOnOrThrough( const ObjectCalcer* o ) const;
+};
+
+#endif