summaryrefslogtreecommitdiffstats
path: root/src/sp-object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sp-object.cpp')
-rw-r--r--src/sp-object.cpp359
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