#ifndef SP_OBJECT_H_SEEN #define SP_OBJECT_H_SEEN /* * Authors: * Lauris Kaplinski * Jon A. Cruz * Abhishek Sharma * * Copyright (C) 1999-2002 authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL, read the file 'COPYING' for more information */ /* SPObject flags */ class SPObject; class SPObjectClass; #define SP_TYPE_OBJECT (SPObject::sp_object_get_type ()) #define SP_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_OBJECT, SPObject)) #define SP_OBJECT_CLASS(clazz) (G_TYPE_CHECK_CLASS_CAST((clazz), SP_TYPE_OBJECT, SPObjectClass)) #define SP_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_OBJECT)) /* Async modification flags */ #define SP_OBJECT_MODIFIED_FLAG (1 << 0) #define SP_OBJECT_CHILD_MODIFIED_FLAG (1 << 1) #define SP_OBJECT_PARENT_MODIFIED_FLAG (1 << 2) #define SP_OBJECT_STYLE_MODIFIED_FLAG (1 << 3) #define SP_OBJECT_VIEWPORT_MODIFIED_FLAG (1 << 4) #define SP_OBJECT_USER_MODIFIED_FLAG_A (1 << 5) #define SP_OBJECT_USER_MODIFIED_FLAG_B (1 << 6) #define SP_OBJECT_USER_MODIFIED_FLAG_C (1 << 7) /* Conveneience */ #define SP_OBJECT_FLAGS_ALL 0xff /* Flags that mark object as modified */ /* Object, Child, Style, Viewport, User */ #define SP_OBJECT_MODIFIED_STATE (SP_OBJECT_FLAGS_ALL & ~(SP_OBJECT_PARENT_MODIFIED_FLAG)) /* Flags that will propagate downstreams */ /* Parent, Style, Viewport, User */ #define SP_OBJECT_MODIFIED_CASCADE (SP_OBJECT_FLAGS_ALL & ~(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG)) /* Write flags */ #define SP_OBJECT_WRITE_BUILD (1 << 0) #define SP_OBJECT_WRITE_EXT (1 << 1) #define SP_OBJECT_WRITE_ALL (1 << 2) #include #include #include #include #include #include "version.h" #include "util/forward-pointer-iterator.h" #include "desktop-style.h" namespace Inkscape { namespace XML { class Node; class Document; } } typedef enum { SP_NO_EXCEPTION, SP_INDEX_SIZE_ERR, SP_DOMSTRING_SIZE_ERR, SP_HIERARCHY_REQUEST_ERR, SP_WRONG_DOCUMENT_ERR, SP_INVALID_CHARACTER_ERR, SP_NO_DATA_ALLOWED_ERR, SP_NO_MODIFICATION_ALLOWED_ERR, SP_NOT_FOUND_ERR, SP_NOT_SUPPORTED_ERR, SP_INUSE_ATTRIBUTE_ERR, SP_INVALID_STATE_ERR, SP_SYNTAX_ERR, SP_INVALID_MODIFICATION_ERR, SP_NAMESPACE_ERR, SP_INVALID_ACCESS_ERR } SPExceptionType; class SPException; /// An attempt to implement exceptions, unused? struct SPException { SPExceptionType code; }; #define SP_EXCEPTION_INIT(ex) {(ex)->code = SP_NO_EXCEPTION;} #define SP_EXCEPTION_IS_OK(ex) (!(ex) || ((ex)->code == SP_NO_EXCEPTION)) class SPCtx; /// Unused struct SPCtx { unsigned int flags; }; enum { SP_XML_SPACE_DEFAULT, SP_XML_SPACE_PRESERVE }; class SPDocument; class SPIXmlSpace; class SPObject; /// Internal class consisting of two bits. struct SPIXmlSpace { guint set : 1; guint value : 1; }; /* * Refcounting * * Owner is here for debug reasons, you can set it to NULL safely * Ref should return object, NULL is error, unref return always NULL */ /** * Increase reference count of object, with possible debugging. * * @param owner If non-NULL, make debug log entry. * @return object, NULL is error. * \pre object points to real object * @todo need to move this to be a member of SPObject. */ SPObject *sp_object_ref(SPObject *object, SPObject *owner=NULL); /** * Decrease reference count of object, with possible debugging and * finalization. * * @param owner If non-NULL, make debug log entry. * @return always NULL * \pre object points to real object * @todo need to move this to be a member of SPObject. */ SPObject *sp_object_unref(SPObject *object, SPObject *owner=NULL); /** * Increase weak refcount. * * Hrefcount is used for weak references, for example, to * determine whether any graphical element references a certain gradient * node. * @param owner Ignored. * @return object, NULL is error * \pre object points to real object * @todo need to move this to be a member of SPObject. */ SPObject *sp_object_href(SPObject *object, gpointer owner); /** * Decrease weak refcount. * * Hrefcount is used for weak references, for example, to determine whether * any graphical element references a certain gradient node. * @param owner Ignored. * @return always NULL * \pre object points to real object and hrefcount>0 * @todo need to move this to be a member of SPObject. */ SPObject *sp_object_hunref(SPObject *object, gpointer owner); /** * SPObject is an abstract base class of all of the document nodes at the * SVG document level. Each SPObject subclass implements a certain SVG * element node type, or is an abstract base class for different node * types. The SPObject layer is bound to the SPRepr layer, closely * following the SPRepr mutations via callbacks. During creation, * SPObject parses and interprets all textual attributes and CSS style * strings of the SPRepr, and later updates the internal state whenever * it receives a signal about a change. The opposite is not true - there * are methods manipulating SPObjects directly and such changes do not * propagate to the SPRepr layer. This is important for implementation of * the undo stack, animations and other features. * * SPObjects are bound to the higher-level container SPDocument, which * provides document level functionality such as the undo stack, * dictionary and so on. Source: doc/architecture.txt * * @todo need to remove redundant sp_object_... prefixing on methods. */ class SPObject : public GObject { public: enum CollectionPolicy { COLLECT_WITH_PARENT, ALWAYS_COLLECT }; unsigned int cloned : 1; unsigned int uflags : 8; unsigned int mflags : 8; SPIXmlSpace xml_space; unsigned int hrefcount; /* number of xlink:href references */ unsigned int _total_hrefcount; /* our hrefcount + total descendants */ SPDocument *document; /* Document we are part of */ SPObject *parent; /* Our parent (only one allowed) */ SPObject *children; /* Our children */ SPObject *_last_child; /* Remembered last child */ SPObject *next; /* Next object in linked list */ private: gchar *id; /* Our very own unique id */ Inkscape::XML::Node *repr; /* Our xml representation */ public: /** * Returns the objects current ID string. */ gchar const* getId() const; /** * Returns the XML representation of tree */ //Inkscape::XML::Node const* getRepr() const; //protected: Inkscape::XML::Node * getRepr(); /** * Returns the XML representation of tree */ Inkscape::XML::Node const* getRepr() const; public: /** * Cleans up an SPObject, releasing its references and * requesting that references to it be released */ void releaseReferences(); /** * Connects to the release request signal * * @param slot the slot to connect * * @return the sigc::connection formed */ sigc::connection connectRelease(sigc::slot slot) { return _release_signal.connect(slot); } /** * Represents the style properties, whether from presentation attributes, the style * attribute, or inherited. * * sp_object_private_set doesn't handle SP_ATTR_STYLE or any presentation attributes at the * time of writing, so this is probably NULL for all SPObject's that aren't an SPItem. * * However, this gives rise to the bugs mentioned in sp_object_get_style_property. * Note that some non-SPItem SPObject's, such as SPStop, do need styling information, * and need to inherit properties even through other non-SPItem parents like \. */ SPStyle *style; /// Switch containing next() method. struct ParentIteratorStrategy { static SPObject const *next(SPObject const *object) { return object->parent; } }; /// Switch containing next() method. struct SiblingIteratorStrategy { static SPObject const *next(SPObject const *object) { return object->next; } }; typedef Inkscape::Util::ForwardPointerIterator ParentIterator; typedef Inkscape::Util::ForwardPointerIterator ConstParentIterator; typedef Inkscape::Util::ForwardPointerIterator SiblingIterator; typedef Inkscape::Util::ForwardPointerIterator ConstSiblingIterator; bool isSiblingOf(SPObject const *object) const { g_return_val_if_fail(object != NULL, false); return this->parent && this->parent == object->parent; } /** * True if object is non-NULL and this is some in/direct parent of object. */ bool isAncestorOf(SPObject const *object) const; /** * Returns youngest object being parent to this and object. */ SPObject const *nearestCommonAncestor(SPObject const *object) const; /* A non-const version can be similarly constructed if you want one. * (Don't just cast away the constness, which would be ill-formed.) */ SPObject *getNext() {return next;} SPObject const *getNext() const {return next;} /** * Returns previous object in sibling list or NULL. */ SPObject *getPrev(); bool hasChildren() const { return ( children != NULL ); } SPObject *firstChild() { return children; } SPObject const *firstChild() const { return children; } SPObject *lastChild() { return _last_child; } SPObject const *lastChild() const { return _last_child; } enum Action { ActionGeneral, ActionBBox, ActionUpdate, ActionShow }; /** * Retrieves the children as a GSList object, optionally ref'ing the children * in the process, if add_ref is specified. */ GSList *childList(bool add_ref, Action action = ActionGeneral); /** * Append repr as child of this object. * \pre this is not a cloned object */ SPObject *appendChildRepr(Inkscape::XML::Node *repr); /** * Gets the author-visible label property for the object or a default if * no label is defined. */ gchar const *label() const; /** * Returns a default label property for this object. */ gchar const *defaultLabel() const; /** * Sets the author-visible label for this object. * * @param label the new label. */ void setLabel(gchar const *label); /** * Returns the title of this object, or NULL if there is none. * The caller must free the returned string using g_free() - see comment * for getTitleOrDesc() below. */ gchar *title() const; /** * Sets the title of this object. * A NULL first argument is interpreted as meaning that the existing title * (if any) should be deleted. * The second argument is optional - @see setTitleOrDesc() below for details. */ bool setTitle(gchar const *title, bool verbatim = false); /** * Returns the description of this object, or NULL if there is none. * The caller must free the returned string using g_free() - see comment * for getTitleOrDesc() below. */ gchar *desc() const; /** * Sets the description of this object. * A NULL first argument is interpreted as meaning that the existing * description (if any) should be deleted. * The second argument is optional - @see setTitleOrDesc() below for details. */ bool setDesc(gchar const *desc, bool verbatim=false); /** * Set the policy under which this object will be orphan-collected. * * Orphan-collection is the process of deleting all objects which no longer have * hyper-references pointing to them. The policy determines when this happens. Many objects * should not be deleted simply because they are no longer referred to; other objects (like * "intermediate" gradients) are more or less throw-away and should always be collected when no * longer in use. * * Along these lines, there are currently two orphan-collection policies: * * COLLECT_WITH_PARENT - don't worry about the object's hrefcount; * if its parent is collected, this object * will be too * * COLLECT_ALWAYS - always collect the object as soon as its * hrefcount reaches zero * * @return the current collection policy in effect for this object */ CollectionPolicy collectionPolicy() const { return _collection_policy; } /** * Sets the orphan-collection policy in effect for this object. * * @param policy the new policy to adopt * * @see SPObject::collectionPolicy */ void setCollectionPolicy(CollectionPolicy policy) { _collection_policy = policy; } /** * Requests a later automatic call to collectOrphan(). * * This method requests that collectOrphan() be called during the document update cycle, * deleting the object if it is no longer used. * * If the current collection policy is COLLECT_WITH_PARENT, this function has no effect. * * @see SPObject::collectOrphan */ void requestOrphanCollection(); /** * Unconditionally delete the object if it is not referenced. * * Unconditionally delete the object if there are no outstanding hyper-references to it. * Observers are not notified of the object's deletion (at the SPObject level; XML tree * notifications still fire). * * @see SPObject::deleteObject */ void collectOrphan() { if ( _total_hrefcount == 0 ) { deleteObject(false); } } /** * Check if object is referenced by any other object. */ bool isReferenced() { return ( _total_hrefcount > 0 ); } /** * Deletes an object, unparenting it from its parent. * * Detaches the object's repr, and optionally sends notification that the object has been * deleted. * * @param propagate If it is set to true, it emits a delete signal. * * @param propagate_descendants If it is is true, it recursively sends the delete signal to children. */ void deleteObject(bool propagate, bool propagate_descendants); /** * Deletes on object. * * @param propagate Notify observers of this object and its children that they have been * deleted? */ void deleteObject(bool propagate = true) { deleteObject(propagate, propagate); } /** * Connects a slot to be called when an object is deleted. * * This connects a slot to an object's internal delete signal, which is invoked when the object * is deleted * * The signal is mainly useful for e.g. knowing when to break hrefs or dissociate clones. * * @param slot the slot to connect * * @see SPObject::deleteObject */ sigc::connection connectDelete(sigc::slot slot) { return _delete_signal.connect(slot); } sigc::connection connectPositionChanged(sigc::slot slot) { return _position_changed_signal.connect(slot); } /** * Returns the object which supercedes this one (if any). * * This is mainly useful for ensuring we can correctly perform a series of moves or deletes, * even if the objects in question have been replaced in the middle of the sequence. */ SPObject *successor() { return _successor; } /** * Indicates that another object supercedes this one. */ void setSuccessor(SPObject *successor) { g_assert(successor != NULL); g_assert(_successor == NULL); g_assert(successor->_successor == NULL); sp_object_ref(successor, NULL); _successor = successor; } /* modifications; all three sets of methods should probably ultimately be protected, as they * are not really part of its public interface. However, other parts of the code to * occasionally use them at present. */ /* the no-argument version of updateRepr() is intended to be a bit more public, however -- it * essentially just flushes any changes back to the backing store (the repr layer); maybe it * should be called something else and made public at that point. */ /** * Updates the object's repr based on the object's state. * * This method updates the the repr attached to the object to reflect the object's current * state; see the three-argument version for details. * * @param flags object write flags that apply to this update * * @return the updated repr */ Inkscape::XML::Node *updateRepr(unsigned int flags = SP_OBJECT_WRITE_EXT); /** * Updates the given repr based on the object's state. * * Used both to create reprs in the original document, and to create reprs * in another document (e.g. a temporary document used when saving as "Plain SVG". * * This method updates the given repr to reflect the object's current state. There are * several flags that affect this: * * SP_OBJECT_WRITE_BUILD - create new reprs * * SP_OBJECT_WRITE_EXT - write elements and attributes * which are not part of pure SVG * (i.e. the Inkscape and Sodipodi * namespaces) * * SP_OBJECT_WRITE_ALL - create all nodes and attributes, * even those which might be redundant * * @param repr the repr to update * @param flags object write flags that apply to this update * * @return the updated repr */ Inkscape::XML::Node *updateRepr(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags); /** * Queues an deferred update of this object's display. * * This method sets flags to indicate updates to be performed later, during the idle loop. * * There are several flags permitted here: * * SP_OBJECT_MODIFIED_FLAG - the object has been modified * * SP_OBJECT_CHILD_MODIFIED_FLAG - a child of the object has been * modified * * SP_OBJECT_STYLE_MODIFIED_FLAG - the object's style has been * modified * * There are also some subclass-specific modified flags which are hardly ever used. * * One of either MODIFIED or CHILD_MODIFIED is required. * * @param flags flags indicating what to update */ void requestDisplayUpdate(unsigned int flags); /** * Updates the object's display immediately * * This method is called during the idle loop by SPDocument in order to update the object's * display. * * One additional flag is legal here: * * SP_OBJECT_PARENT_MODIFIED_FLAG - the parent has been * modified * * @param ctx an SPCtx which accumulates various state * during the recursive update -- beware! some * subclasses try to cast this to an SPItemCtx * * * @param flags flags indicating what to update (in addition * to any already set flags) */ void updateDisplay(SPCtx *ctx, unsigned int flags); /** * Requests that a modification notification signal * be emitted later (e.g. during the idle loop) * * Request modified always bubbles *up* the tree, as opposed to * request display update, which trickles down and relies on the * flags set during this pass... * * @param flags flags indicating what has been modified */ void requestModified(unsigned int flags); /** * Emits the MODIFIED signal with the object's flags. * The object's mflags are the original set aside during the update pass for * later delivery here. Once emitModified() is called, those flags don't * need to be stored any longer. * * @param flags indicating what has been modified. */ void emitModified(unsigned int flags); /** * Connects to the modification notification signal * * @param slot the slot to connect * * @return the connection formed thereby */ sigc::connection connectModified( sigc::slot slot ) { return _modified_signal.connect(slot); } /** Sends the delete signal to all children of this object recursively */ void _sendDeleteSignalRecursive(); /** * Adds increment to _total_hrefcount of object and its parents. */ void _updateTotalHRefCount(int increment); void _requireSVGVersion(unsigned major, unsigned minor) { _requireSVGVersion(Inkscape::Version(major, minor)); } /** * Lifts SVG version of all root objects to version. */ void _requireSVGVersion(Inkscape::Version version); sigc::signal _release_signal; sigc::signal _delete_signal; sigc::signal _position_changed_signal; sigc::signal _modified_signal; SPObject *_successor; CollectionPolicy _collection_policy; gchar *_label; mutable gchar *_default_label; // WARNING: // Methods below should not be used outside of the SP tree, // as they operate directly on the XML representation. // In future, they will be made protected. /** * Put object into object tree, under parent, and behind prev; * also update object's XML space. */ void attach(SPObject *object, SPObject *prev); /** * In list of object's siblings, move object behind prev. */ void reorder(SPObject *prev); /** * Remove object from parent's children, release and unref it. */ void detach(SPObject *object); /** * Return object's child whose node pointer equals repr. */ SPObject *get_child_by_repr(Inkscape::XML::Node *repr); void invoke_build(SPDocument *document, Inkscape::XML::Node *repr, unsigned int cloned); long long int getIntAttribute(char const *key, long long int def); unsigned getPosition(); gchar const * getAttribute(gchar const *name,SPException *ex=0) const; void appendChild(Inkscape::XML::Node *child); void addChild(Inkscape::XML::Node *child,Inkscape::XML::Node *prev=0); /** * Call virtual set() function of object. */ void setKeyValue(unsigned int key, gchar const *value); void setAttribute(gchar const *key, gchar const *value, SPException *ex=0); /** * Read value of key attribute from XML node into object. */ void readAttr(gchar const *key); gchar const *getTagName(SPException *ex) const; void removeAttribute(gchar const *key, SPException *ex=0); /** * Returns an object style property. * * \todo * fixme: Use proper CSS parsing. The current version is buggy * in a number of situations where key is a substring of the * style string other than as a property name (including * where key is a substring of a property name), and is also * buggy in its handling of inheritance for properties that * aren't inherited by default. It also doesn't allow for * the case where the property is specified but with an invalid * value (in which case I believe the CSS2 error-handling * behaviour applies, viz. behave as if the property hadn't * been specified). Also, the current code doesn't use CRSelEng * stuff to take a value from stylesheets. Also, we aren't * setting any hooks to force an update for changes in any of * the inputs (i.e., in any of the elements that this function * queries). * * \par * Given that the default value for a property depends on what * property it is (e.g., whether to inherit or not), and given * the above comment about ignoring invalid values, and that the * repr parent isn't necessarily the right element to inherit * from (e.g., maybe we need to inherit from the referencing * element instead), we should probably make the caller * responsible for ascending the repr tree as necessary. */ gchar const *getStyleProperty(gchar const *key, gchar const *def) const; void setCSS(SPCSSAttr *css, gchar const *attr); void changeCSS(SPCSSAttr *css, gchar const *attr); bool storeAsDouble( gchar const *key, double *val ) const; private: // Private member functions used in the definitions of setTitle(), // setDesc(), title() and desc(). /** * Sets or deletes the title or description of this object. * A NULL 'value' argument causes the title or description to be deleted. * * 'verbatim' parameter: * If verbatim==true, then the title or description is set to exactly the * specified value. If verbatim==false then two exceptions are made: * (1) If the specified value is just whitespace, then the title/description * is deleted. * (2) If the specified value is the same as the current value except for * mark-up, then the current value is left unchanged. * This is usually the desired behaviour, so 'verbatim' defaults to false for * setTitle() and setDesc(). * * The return value is true if a change was made to the title/description, * and usually false otherwise. */ bool setTitleOrDesc(gchar const *value, gchar const *svg_tagname, bool verbatim); /** * Returns the title or description of this object, or NULL if there is none. * * The SVG spec allows 'title' and 'desc' elements to contain text marked up * using elements from other namespaces. Therefore, this function cannot * in general just return a pointer to an existing string - it must instead * construct a string containing the title or description without the mark-up. * Consequently, the return value is a newly allocated string (or NULL), and * must be freed (using g_free()) by the caller. */ gchar * getTitleOrDesc(gchar const *svg_tagname) const; /** * Find the first child of this object with a given tag name, * and return it. Returns NULL if there is no matching child. */ SPObject * findFirstChild(gchar const *tagname) const; /** * Return the full textual content of an element (typically all the * content except the tags). * Must not be used on anything except elements. */ GString * textualContent() const; /** * Callback to initialize the SPObject object. */ static void sp_object_init(SPObject *object); /** * Callback to destroy all members and connections of object and itself. */ static void sp_object_finalize(GObject *object); /** * Callback for child_added event. * Invoked whenever the given mutation event happens in the XML tree. */ static void sp_object_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref); /** * Remove object's child whose node equals repr, release and * unref it. * * Invoked whenever the given mutation event happens in the XML * tree, BEFORE removal from the XML tree happens, so grouping * objects can safely release the child data. */ static void sp_object_remove_child(SPObject *object, Inkscape::XML::Node *child); /** * Move object corresponding to child after sibling object corresponding * to new_ref. * Invoked whenever the given mutation event happens in the XML tree. * @param old_ref Ignored */ static void sp_object_order_changed(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref); /** * Removes, releases and unrefs all children of object. * * This is the opposite of build. It has to be invoked as soon as the * object is removed from the tree, even if it is still alive according * to reference count. The frontend unregisters the object from the * document and releases the SPRepr bindings; implementations should free * state data and release all child objects. Invoking release on * SPRoot destroys the whole document tree. * @see sp_object_build() */ static void sp_object_release(SPObject *object); /** * Virtual build callback. * * This has to be invoked immediately after creation of an SPObject. The * frontend method ensures that the new object is properly attached to * the document and repr; implementation then will parse all of the attributes, * generate the children objects and so on. Invoking build on the SPRoot * object results in creation of the whole document tree (this is, what * SPDocument does after the creation of the XML tree). * @see sp_object_release() */ static void sp_object_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); /** * Callback for set event. */ static void sp_object_private_set(SPObject *object, unsigned int key, gchar const *value); /** * Callback for write event. */ static Inkscape::XML::Node *sp_object_private_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static gchar *sp_object_get_unique_id(SPObject *object, gchar const *defid); /* Real handlers of repr signals */ public: /** * Registers the SPObject class with Gdk and returns its type number. */ static GType sp_object_get_type(); /** * Callback for attr_changed node event. */ static void sp_object_repr_attr_changed(Inkscape::XML::Node *repr, gchar const *key, gchar const *oldval, gchar const *newval, bool is_interactive, gpointer data); /** * Callback for content_changed node event. */ static void sp_object_repr_content_changed(Inkscape::XML::Node *repr, gchar const *oldcontent, gchar const *newcontent, gpointer data); /** * Callback for child_added node event. */ static void sp_object_repr_child_added(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data); /** * Callback for remove_child node event. */ static void sp_object_repr_child_removed(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, void *data); /** * Callback for order_changed node event. * * \todo fixme: */ static void sp_object_repr_order_changed(Inkscape::XML::Node *repr, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *newer, gpointer data); friend class SPObjectClass; friend class SPObjectImpl; }; /// The SPObject vtable. class SPObjectClass { public: GObjectClass parent_class; void (* build) (SPObject *object, SPDocument *doc, Inkscape::XML::Node *repr); void (* release) (SPObject *object); /* Virtual handlers of repr signals */ void (* child_added) (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref); void (* remove_child) (SPObject *object, Inkscape::XML::Node *child); void (* order_changed) (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *new_repr); void (* set) (SPObject *object, unsigned int key, gchar const *value); void (* read_content) (SPObject *object); /* Update handler */ void (* update) (SPObject *object, SPCtx *ctx, unsigned int flags); /* Modification handler */ void (* modified) (SPObject *object, unsigned int flags); Inkscape::XML::Node * (* write) (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags); private: static GObjectClass *static_parent_class; /** * Initializes the SPObject vtable. */ static void sp_object_class_init(SPObjectClass *klass); friend class SPObject; }; /** * Compares height of objects in tree. * * Works for different-parent objects, so long as they have a common ancestor. * \return \verbatim * 0 positions are equivalent * 1 first object's position is greater than the second * -1 first object's position is less than the second \endverbatim */ int sp_object_compare_position(SPObject const *first, SPObject const *second); #endif // SP_OBJECT_H_SEEN /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :