diff options
Diffstat (limited to 'src/sp-object.cpp')
| -rw-r--r-- | src/sp-object.cpp | 359 |
1 files changed, 116 insertions, 243 deletions
diff --git a/src/sp-object.cpp b/src/sp-object.cpp index b5c93e792..895b36e1c 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -25,7 +25,7 @@ #include "document.h" #include "preferences.h" #include "style.h" -#include "sp-object-repr.h" +#include "sp-factory.h" #include "sp-paint-server.h" #include "sp-root.h" #include "sp-style-elem.h" @@ -101,121 +101,54 @@ public: } }; -static void sp_object_child_added(SPObject *object, - Inkscape::XML::Node *child, - Inkscape::XML::Node *ref); - -static void sp_object_finalize(GObject *object); - -static void sp_object_remove_child(SPObject *object, - Inkscape::XML::Node *child); - -static void sp_object_order_changed(SPObject *object, - Inkscape::XML::Node *child, - Inkscape::XML::Node *old_ref, - Inkscape::XML::Node *new_ref); - -static void sp_object_release(SPObject *object); -static void sp_object_build(SPObject *object, - SPDocument *document, - Inkscape::XML::Node *repr); - -static void sp_object_private_set(SPObject *object, - unsigned int key, - gchar const *value); - -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); -G_DEFINE_TYPE(SPObject, sp_object, G_TYPE_OBJECT); - -/** - * Initializes the SPObject vtable. - */ -static void -sp_object_class_init(SPObjectClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - - object_class->finalize = sp_object_finalize; - - klass->child_added = sp_object_child_added; - klass->remove_child = sp_object_remove_child; - klass->order_changed = sp_object_order_changed; - klass->release = sp_object_release; - klass->build = sp_object_build; - klass->set = sp_object_private_set; - klass->write = sp_object_private_write; -} - -/** - * Callback to initialize the SPObject object. - */ -static void -sp_object_init(SPObject *object) +SPObject::SPObject() + : cloned(0), uflags(0), mflags(0), hrefcount(0), _total_hrefcount(0), + document(NULL), parent(NULL), children(NULL), _last_child(NULL), + next(NULL), id(NULL), repr(NULL), refCount(1), + _successor(NULL), _collection_policy(SPObject::COLLECT_WITH_PARENT), + _label(NULL), _default_label(NULL) { - debug("id=%x, typename=%s",object, g_type_name_from_instance((GTypeInstance*)object)); - - object->hrefcount = 0; - object->_total_hrefcount = 0; - object->document = NULL; - object->children = object->_last_child = NULL; - object->parent = object->next = NULL; + debug("id=%x, typename=%s",this, g_type_name_from_instance((GTypeInstance*)object)); //used XML Tree here. - object->getRepr(); // TODO check why this call is made + this->getRepr(); // TODO check why this call is made - SPObjectImpl::setIdNull(object); - - object->_collection_policy = SPObject::COLLECT_WITH_PARENT; - - new (&object->_release_signal) sigc::signal<void, SPObject *>(); - new (&object->_modified_signal) sigc::signal<void, SPObject *, unsigned int>(); - new (&object->_delete_signal) sigc::signal<void, SPObject *>(); - new (&object->_position_changed_signal) sigc::signal<void, SPObject *>(); - object->_successor = NULL; + SPObjectImpl::setIdNull(this); // FIXME: now we create style for all objects, but per SVG, only the following can have style attribute: // vg, g, defs, desc, title, symbol, use, image, switch, path, rect, circle, ellipse, line, polyline, // polygon, text, tspan, tref, textPath, altGlyph, glyphRef, marker, linearGradient, radialGradient, // stop, pattern, clipPath, mask, filter, feImage, a, font, glyph, missing-glyph, foreignObject - object->style = sp_style_new_from_object(object); - - object->_label = NULL; - object->_default_label = NULL; + this->style = sp_style_new_from_object(this); } -/** - * Callback to destroy all members and connections of object and itself. - */ -static void -sp_object_finalize(GObject *object) -{ - SPObject *spobject = (SPObject *)object; +SPObject::~SPObject() { + g_free(this->_label); + g_free(this->_default_label); - g_free(spobject->_label); - g_free(spobject->_default_label); - spobject->_label = NULL; - spobject->_default_label = NULL; + this->_label = NULL; + this->_default_label = NULL; - if (spobject->_successor) { - sp_object_unref(spobject->_successor, NULL); - spobject->_successor = NULL; + if (this->_successor) { + sp_object_unref(this->_successor, NULL); + this->_successor = NULL; } +} + +// CPPIFY: make pure virtual +void SPObject::read_content() { + //throw; +} - spobject->_release_signal.~signal(); - spobject->_modified_signal.~signal(); - spobject->_delete_signal.~signal(); - spobject->_position_changed_signal.~signal(); +void SPObject::update(SPCtx* ctx, unsigned int flags) { + //throw; +} - if (((GObjectClass *) (sp_object_parent_class))->finalize) { - (* ((GObjectClass *) (sp_object_parent_class))->finalize)(object); - } +void SPObject::modified(unsigned int flags) { + //throw; } namespace { @@ -272,7 +205,8 @@ SPObject *sp_object_ref(SPObject *object, SPObject *owner) g_return_val_if_fail(!owner || SP_IS_OBJECT(owner), NULL); Inkscape::Debug::EventTracker<RefEvent> tracker(object); - g_object_ref(G_OBJECT(object)); + //g_object_ref(G_OBJECT(object)); + object->refCount++; return object; } @@ -283,7 +217,13 @@ SPObject *sp_object_unref(SPObject *object, SPObject *owner) g_return_val_if_fail(!owner || SP_IS_OBJECT(owner), NULL); Inkscape::Debug::EventTracker<UnrefEvent> tracker(object); - g_object_unref(G_OBJECT(object)); + //g_object_unref(G_OBJECT(object)); + object->refCount--; + + if (object->refCount < 0) { + delete object; + } + return NULL; } @@ -419,7 +359,7 @@ GSList *SPObject::childList(bool add_ref, Action) { GSList *l = NULL; for ( SPObject *child = firstChild() ; child; child = child->getNext() ) { if (add_ref) { - g_object_ref (G_OBJECT (child)); + sp_object_ref (child); } l = g_slist_prepend (l, child); @@ -634,59 +574,38 @@ SPObject *SPObject::get_child_by_repr(Inkscape::XML::Node *repr) return result; } -/** - * 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) -{ - GType type = sp_repr_type_lookup(child); - if (!type) { - return; - } - SPObject *ochild = SP_OBJECT(g_object_new(type, 0)); - SPObject *prev = ref ? object->get_child_by_repr(ref) : NULL; - object->attach(ochild, prev); - sp_object_unref(ochild, NULL); +void SPObject::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) { + SPObject* object = this; + + try { + const std::string typeString = NodeTraits::get_type_string(*child); - ochild->invoke_build(object->document, child, object->cloned); + SPObject* ochild = SPFactory::instance().createObject(typeString); + + SPObject *prev = ref ? object->get_child_by_repr(ref) : NULL; + object->attach(ochild, prev); + sp_object_unref(ochild, NULL); + + ochild->invoke_build(object->document, child, object->cloned); + } catch (const FactoryExceptions::TypeNotRegistered& e) { + if (std::string(e.what()) != "rdf:RDF") { // temporary special case + g_warning("TypeNotRegistered exception: %s", e.what()); + } + } } -/** - * 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) -{ +void SPObject::release() { + SPObject* object = this; + debug("id=%x, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object)); while (object->children) { object->detach(object->children); } } -/** - * 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) -{ +void SPObject::remove_child(Inkscape::XML::Node* child) { + SPObject* object = this; + debug("id=%x, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object)); SPObject *ochild = object->get_child_by_repr(child); g_return_if_fail (ochild != NULL || !strcmp("comment", child->name())); // comments have no objects @@ -695,18 +614,9 @@ sp_object_remove_child(SPObject *object, } } -/** - * 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) -{ +void SPObject::order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node * old_ref, Inkscape::XML::Node *new_ref) { + SPObject* object = this; + SPObject *ochild = object->get_child_by_repr(child); g_return_if_fail(ochild != NULL); SPObject *prev = new_ref ? object->get_child_by_repr(new_ref) : NULL; @@ -714,22 +624,9 @@ sp_object_order_changed(SPObject *object, ochild->_position_changed_signal.emit(ochild); } -/** - * 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 release() - */ -static void -sp_object_build(SPObject *object, - SPDocument *document, - Inkscape::XML::Node *repr) -{ +void SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) { + SPObject* object = this; + /* Nothing specific here */ debug("id=%x, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object)); @@ -738,14 +635,28 @@ sp_object_build(SPObject *object, object->readAttr("inkscape:collect"); for (Inkscape::XML::Node *rchild = repr->firstChild() ; rchild != NULL; rchild = rchild->next()) { - GType type = sp_repr_type_lookup(rchild); - if (!type) { - continue; +// GType type = sp_repr_type_lookup(rchild); +// if (!type) { +// continue; +// } +// SPObject *child = SP_OBJECT(g_object_new(type, 0)); + +// SPObject* child = SPFactory::instance().createObject(*rchild); +// if (!child) { +// continue; +// } + + try { + const std::string typeString = NodeTraits::get_type_string(*rchild); + + SPObject* child = SPFactory::instance().createObject(typeString); + + object->attach(child, object->lastChild()); + sp_object_unref(child, NULL); + child->invoke_build(document, rchild, object->cloned); + } catch (const FactoryExceptions::TypeNotRegistered& e) { + //g_warning("TypeNotRegistered exception: %s", e.what()); } - SPObject *child = SP_OBJECT(g_object_new(type, 0)); - object->attach(child, object->lastChild()); - sp_object_unref(child, NULL); - child->invoke_build(document, rchild, object->cloned); } } @@ -805,9 +716,7 @@ void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, uns } /* Invoke derived methods, if any */ - if (((SPObjectClass *) G_OBJECT_GET_CLASS(this))->build) { - (*((SPObjectClass *) G_OBJECT_GET_CLASS(this))->build)(this, document, repr); - } + this->build(document, repr); /* Signalling (should be connected AFTER processing derived methods */ sp_repr_add_listener(repr, &object_event_vector, this); @@ -816,7 +725,7 @@ void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, uns int SPObject::getIntAttribute(char const *key, int def) { sp_repr_get_int(getRepr(),key,&def); - return def; + return def; } unsigned SPObject::getPosition(){ @@ -845,10 +754,8 @@ void SPObject::releaseReferences() { sp_repr_remove_listener_by_data(this->repr, this); this->_release_signal.emit(this); - SPObjectClass *klass=(SPObjectClass *)G_OBJECT_GET_CLASS(this); - if (klass->release) { - klass->release(this); - } + + this->release(); /* all hrefs should be released by the "release" handlers */ g_assert(this->hrefcount == 0); @@ -894,38 +801,28 @@ void SPObject::repr_child_added(Inkscape::XML::Node * /*repr*/, Inkscape::XML::N { SPObject *object = SP_OBJECT(data); - if (((SPObjectClass *) G_OBJECT_GET_CLASS(object))->child_added) { - (*((SPObjectClass *)G_OBJECT_GET_CLASS(object))->child_added)(object, child, ref); - } + object->child_added(child, ref); } void SPObject::repr_child_removed(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node * /*ref*/, gpointer data) { SPObject *object = SP_OBJECT(data); - if (((SPObjectClass *) G_OBJECT_GET_CLASS(object))->remove_child) { - (* ((SPObjectClass *)G_OBJECT_GET_CLASS(object))->remove_child)(object, child); - } + object->remove_child(child); } void SPObject::repr_order_changed(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *newer, gpointer data) { SPObject *object = SP_OBJECT(data); - if (((SPObjectClass *) G_OBJECT_GET_CLASS(object))->order_changed) { - (* ((SPObjectClass *)G_OBJECT_GET_CLASS(object))->order_changed)(object, child, old, newer); - } + object->order_changed(child, old, newer); } -/** - * Callback for set event. - */ -static void sp_object_private_set(SPObject *object, - unsigned int key, - gchar const *value) -{ +void SPObject::set(unsigned int key, gchar const* value) { g_assert(key != SP_ATTR_INVALID); + SPObject* object = this; + switch (key) { case SP_ATTR_ID: @@ -1012,9 +909,7 @@ void SPObject::setKeyValue(unsigned int key, gchar const *value) //g_assert(object != NULL); //g_assert(SP_IS_OBJECT(object)); - if (((SPObjectClass *) G_OBJECT_GET_CLASS(this))->set) { - ((SPObjectClass *) G_OBJECT_GET_CLASS(this))->set(this, key, value); - } + this->set(key, value); } void SPObject::readAttr(gchar const *key) @@ -1052,9 +947,7 @@ void SPObject::repr_content_changed(Inkscape::XML::Node * /*repr*/, gchar const { SPObject *object = SP_OBJECT(data); - if (((SPObjectClass *) G_OBJECT_GET_CLASS(object))->read_content) { - (*((SPObjectClass *) G_OBJECT_GET_CLASS(object))->read_content)(object); - } + object->read_content(); } /** @@ -1072,15 +965,9 @@ static gchar const *sp_xml_get_space_string(unsigned int space) } } -/** - * Callback for write event. - */ -static Inkscape::XML::Node* -sp_object_private_write(SPObject *object, - Inkscape::XML::Document *doc, - Inkscape::XML::Node *repr, - guint flags) -{ +Inkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) { + SPObject* object = this; + if (!repr && (flags & SP_OBJECT_WRITE_BUILD)) { repr = object->getRepr()->duplicate(doc); if (!( flags & SP_OBJECT_WRITE_EXT )) { @@ -1180,23 +1067,12 @@ Inkscape::XML::Node * SPObject::updateRepr(Inkscape::XML::Document *doc, Inkscap /* cloned objects have no repr */ return NULL; } - if (((SPObjectClass *) G_OBJECT_GET_CLASS(this))->write) { - if (!(flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = getRepr(); - } - return ((SPObjectClass *) G_OBJECT_GET_CLASS(this))->write(this, doc, repr, flags); - } else { - g_warning("Class %s does not implement ::write", G_OBJECT_TYPE_NAME(this)); - if (!repr) { - if (flags & SP_OBJECT_WRITE_BUILD) { - repr = getRepr()->duplicate(doc); - } - /// \todo FIXME: else probably error (Lauris) */ - } else { - repr->mergeFrom(getRepr(), "id"); - } - return repr; + + if (!(flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = getRepr(); } + return this->write(doc, repr, flags); + } /* Modification */ @@ -1262,9 +1138,7 @@ void SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) try { - if (((SPObjectClass *) G_OBJECT_GET_CLASS(this))->update) { - ((SPObjectClass *) G_OBJECT_GET_CLASS(this))->update(this, ctx, flags); - } + this->update(ctx, flags); } catch(...) { @@ -1320,13 +1194,12 @@ void SPObject::emitModified(unsigned int flags) * themselves. */ this->mflags = 0; - g_object_ref(G_OBJECT(this)); - SPObjectClass *klass=(SPObjectClass *)G_OBJECT_GET_CLASS(this); - if (klass->modified) { - klass->modified(this, flags); - } + sp_object_ref(this); + + this->modified(flags); + _modified_signal.emit(this, flags); - g_object_unref(G_OBJECT(this)); + sp_object_unref(this); } gchar const *SPObject::getTagName(SPException *ex) const |
