summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2008-03-28 19:31:06 +0000
committerjohanengelen <johanengelen@users.sourceforge.net>2008-03-28 19:31:06 +0000
commitc2601db18bc9913a926593de6aed6d52fdf7d165 (patch)
tree9881e0ae7214ad8563e29b315341ae31252b9771 /src
parent- Created a SPLPEItem class that handles applying a LPE to an Item (diff)
downloadinkscape-c2601db18bc9913a926593de6aed6d52fdf7d165.tar.gz
inkscape-c2601db18bc9913a926593de6aed6d52fdf7d165.zip
Add two files that were forgotten in last commit
(bzr r5220)
Diffstat (limited to 'src')
-rw-r--r--src/sp-lpe-item.cpp451
-rw-r--r--src/sp-lpe-item.h69
2 files changed, 520 insertions, 0 deletions
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
new file mode 100644
index 000000000..373d641cb
--- /dev/null
+++ b/src/sp-lpe-item.cpp
@@ -0,0 +1,451 @@
+#define __SP_LPE_ITEM_CPP__
+
+/** \file
+ * Base class for live path effect items
+ */
+/*
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
+ * Bastien Bouclet <bgkweb@gmail.com>
+ *
+ * Copyright (C) 2008 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "live_effects/effect.h"
+#include "live_effects/lpeobject.h"
+#include "live_effects/lpeobject-reference.h"
+
+#include "sp-path.h"
+#include "sp-item-group.h"
+#include "macros.h"
+#include "attributes.h"
+#include "sp-lpe-item.h"
+#include "xml/repr.h"
+#include "uri.h"
+
+/* LPEItem base class */
+
+static void sp_lpe_item_class_init(SPLPEItemClass *klass);
+static void sp_lpe_item_init(SPLPEItem *lpe_item);
+static void sp_lpe_item_finalize(GObject *object);
+
+static void sp_lpe_item_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
+static void sp_lpe_item_release(SPObject *object);
+static void sp_lpe_item_set(SPObject *object, unsigned int key, gchar const *value);
+static void sp_lpe_item_update(SPObject *object, SPCtx *ctx, guint flags);
+static void sp_lpe_item_modified (SPObject *object, unsigned int flags);
+static Inkscape::XML::Node *sp_lpe_item_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+
+static void sp_lpe_item_child_added (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * ref);
+static void sp_lpe_item_remove_child (SPObject * object, Inkscape::XML::Node * child);
+
+static void lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPLPEItem *lpeitem);
+static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeitem);
+
+static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem);
+static void sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem);
+
+static SPItemClass *parent_class;
+
+GType
+sp_lpe_item_get_type()
+{
+ static GType lpe_item_type = 0;
+
+ if (!lpe_item_type) {
+ GTypeInfo lpe_item_info = {
+ sizeof(SPLPEItemClass),
+ NULL, NULL,
+ (GClassInitFunc) sp_lpe_item_class_init,
+ NULL, NULL,
+ sizeof(SPLPEItem),
+ 16,
+ (GInstanceInitFunc) sp_lpe_item_init,
+ NULL, /* value_table */
+ };
+ lpe_item_type = g_type_register_static(SP_TYPE_ITEM, "SPLPEItem", &lpe_item_info, (GTypeFlags)0);
+ }
+ return lpe_item_type;
+}
+
+static void
+sp_lpe_item_class_init(SPLPEItemClass *klass)
+{
+ GObjectClass *gobject_class;
+ SPObjectClass *sp_object_class;
+
+ gobject_class = (GObjectClass *) klass;
+ sp_object_class = (SPObjectClass *) klass;
+ parent_class = (SPItemClass *)g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = sp_lpe_item_finalize;
+
+ sp_object_class->build = sp_lpe_item_build;
+ sp_object_class->release = sp_lpe_item_release;
+ sp_object_class->set = sp_lpe_item_set;
+ sp_object_class->update = sp_lpe_item_update;
+ sp_object_class->modified = sp_lpe_item_modified;
+ sp_object_class->write = sp_lpe_item_write;
+ sp_object_class->child_added = sp_lpe_item_child_added;
+ sp_object_class->remove_child = sp_lpe_item_remove_child;
+
+ klass->update_patheffect = NULL;
+}
+
+static void
+sp_lpe_item_init(SPLPEItem *lpeitem)
+{
+ lpeitem->path_effect_ref = new Inkscape::LivePathEffect::LPEObjectReference(SP_OBJECT(lpeitem));
+ new (&lpeitem->lpe_modified_connection) sigc::connection();
+}
+
+static void
+sp_lpe_item_finalize(GObject *object)
+{
+ if (((GObjectClass *) (parent_class))->finalize) {
+ (* ((GObjectClass *) (parent_class))->finalize)(object);
+ }
+}
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPLPEItem variables. For this to get called,
+ * our name must be associated with a repr via "sp_object_type_register". Best done through
+ * sp-object-repr.cpp's repr_name_entries array.
+ */
+static void
+sp_lpe_item_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
+{
+ SP_LPE_ITEM(object)->path_effect_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobject_ref_changed), SP_LPE_ITEM(object)));
+
+ sp_object_read_attr(object, "inkscape:path-effect");
+
+ if (((SPObjectClass *) parent_class)->build) {
+ ((SPObjectClass *) parent_class)->build(object, document, repr);
+ }
+}
+
+/**
+ * Drops any allocated memory.
+ */
+static void
+sp_lpe_item_release(SPObject *object)
+{
+ SPLPEItem *lpeitem;
+ lpeitem = (SPLPEItem *) object;
+
+ lpeitem->path_effect_ref->detach();
+
+ lpeitem->lpe_modified_connection.disconnect();
+ lpeitem->lpe_modified_connection.~connection();
+
+ if (((SPObjectClass *) parent_class)->release)
+ ((SPObjectClass *) parent_class)->release(object);
+}
+
+/**
+ * Sets a specific value in the SPLPEItem.
+ */
+static void
+sp_lpe_item_set(SPObject *object, unsigned int key, gchar const *value)
+{
+ SPLPEItem *lpeitem = (SPLPEItem *) object;
+
+ switch (key) {
+ case SP_ATTR_INKSCAPE_PATH_EFFECT:
+ if ( value && lpeitem->path_effect_ref->lpeobject_href
+ && ( strcmp(value, lpeitem->path_effect_ref->lpeobject_href) == 0 ) ) {
+ /* No change, do nothing. */
+ } else {
+ if (value) {
+ // Now do the attaching, which emits the changed signal.
+ try {
+ lpeitem->path_effect_ref->link((gchar*)value);
+ } catch (Inkscape::BadURIException &e) {
+ g_warning("%s", e.what());
+ lpeitem->path_effect_ref->detach();
+ }
+ } else {
+ // Detach, which emits the changed signal.
+ lpeitem->path_effect_ref->detach();
+ }
+ }
+ break;
+ default:
+ if (((SPObjectClass *) parent_class)->set) {
+ ((SPObjectClass *) parent_class)->set(object, key, value);
+ }
+ break;
+ }
+}
+
+/**
+ * Receives update notifications.
+ */
+static void
+sp_lpe_item_update(SPObject *object, SPCtx *ctx, guint flags)
+{
+ if (((SPObjectClass *) parent_class)->update) {
+ ((SPObjectClass *) parent_class)->update(object, ctx, flags);
+ }
+}
+
+/**
+ * Sets modified flag for all sub-item views.
+ */
+static void
+sp_lpe_item_modified (SPObject *object, unsigned int flags)
+{
+ if (((SPObjectClass *) (parent_class))->modified) {
+ (* ((SPObjectClass *) (parent_class))->modified) (object, flags);
+ }
+}
+
+/**
+ * Writes its settings to an incoming repr object, if any.
+ */
+static Inkscape::XML::Node *
+sp_lpe_item_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+{
+ SPLPEItem *lpeitem = (SPLPEItem *) object;
+
+ if ( sp_lpe_item_has_path_effect(lpeitem) ) {
+ repr->setAttribute("inkscape:path-effect", lpeitem->path_effect_ref->lpeobject_href);
+ } else {
+ repr->setAttribute("inkscape:path-effect", NULL);
+ }
+
+ if (((SPObjectClass *)(parent_class))->write) {
+ ((SPObjectClass *)(parent_class))->write(object, repr, flags);
+ }
+
+ return repr;
+}
+
+
+LivePathEffectObject *
+sp_lpe_item_get_livepatheffectobject(SPLPEItem *lpeitem) {
+ if (!lpeitem) return NULL;
+
+ if (sp_lpe_item_has_path_effect(lpeitem)) {
+ return lpeitem->path_effect_ref->lpeobject;
+ } else {
+ return NULL;
+ }
+}
+
+Inkscape::LivePathEffect::Effect *
+sp_lpe_item_get_livepatheffect(SPLPEItem *lpeitem) {
+ if (!lpeitem) return NULL;
+
+ LivePathEffectObject * lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
+ if (lpeobj)
+ return lpeobj->lpe;
+ else
+ return NULL;
+}
+
+void sp_lpe_item_perform_path_effect(SPLPEItem *lpeitem, SPCurve *curve) {
+ if (!lpeitem) return;
+ if (!curve) return;
+
+ if (sp_lpe_item_has_path_effect(lpeitem)) {
+ LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
+ lpeobj->lpe->doEffect(curve);
+ }
+
+ SPObject *parent = lpeitem->parent;
+ if (parent && SP_IS_LPE_ITEM(parent))
+ sp_lpe_item_perform_path_effect(SP_LPE_ITEM(parent), curve);
+}
+
+/**
+ * Calls any registered handlers for the update_patheffect action
+ */
+void
+sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool write)
+{
+#ifdef SHAPE_VERBOSE
+ g_message("sp_lpe_item_update_patheffect: %p\n", lpeitem);
+#endif
+ g_return_if_fail (lpeitem != NULL);
+ g_return_if_fail (SP_IS_LPE_ITEM (lpeitem));
+
+ if (sp_lpe_item_has_path_effect(lpeitem)) {
+ LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
+ lpeobj->lpe->doBeforeEffect(lpeitem);
+ }
+
+ if (SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (lpeitem))->update_patheffect) {
+ SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (lpeitem))->update_patheffect (lpeitem, write);
+ }
+}
+
+/**
+ * Gets called when (re)attached to another lpeobject.
+ */
+static void
+lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPLPEItem *lpeitem)
+{
+ if (old_ref) {
+ sp_signal_disconnect_by_data(old_ref, lpeitem);
+ }
+ if ( IS_LIVEPATHEFFECT(ref) && ref != lpeitem )
+ {
+ lpeitem->lpe_modified_connection.disconnect();
+ lpeitem->lpe_modified_connection = ref->connectModified(sigc::bind(sigc::ptr_fun(&lpeobject_ref_modified), lpeitem));
+ lpeobject_ref_modified(ref, 0, lpeitem);
+ }
+}
+
+/**
+ * Gets called when lpeobject repr contents change: i.e. parameter change.
+ */
+static void
+lpeobject_ref_modified(SPObject */*href*/, guint /*flags*/, SPLPEItem *lpeitem)
+{
+ sp_lpe_item_update_patheffect (lpeitem, true);
+}
+
+static void
+sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem)
+{
+ if (SP_IS_GROUP(lpeitem)) {
+ GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
+ for ( GSList const *iter = item_list; iter; iter = iter->next ) {
+ SPObject *subitem = static_cast<SPObject *>(iter->data);
+ if (SP_IS_LPE_ITEM(subitem)) {
+ sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(subitem));
+ }
+ }
+ }
+ else if (SP_IS_PATH(lpeitem)) {
+ Inkscape::XML::Node *pathrepr = SP_OBJECT_REPR(lpeitem);
+ if ( !pathrepr->attribute("inkscape:original-d") ) {
+ pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d"));
+ }
+ }
+}
+
+static void
+sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem)
+{
+ if (SP_IS_GROUP(lpeitem)) {
+ GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
+ for ( GSList const *iter = item_list; iter; iter = iter->next ) {
+ SPObject *subitem = static_cast<SPObject *>(iter->data);
+ if (SP_IS_LPE_ITEM(subitem)) {
+ sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(subitem));
+ }
+ }
+ }
+ else if (SP_IS_PATH(lpeitem)) {
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(lpeitem);
+ if (!sp_lpe_item_has_path_effect_recursive(lpeitem)
+ && repr->attribute("inkscape:original-d")) {
+ repr->setAttribute("d", repr->attribute("inkscape:original-d"));
+ repr->setAttribute("inkscape:original-d", NULL);
+ }
+ else {
+ sp_lpe_item_update_patheffect(lpeitem, true);
+ }
+ }
+}
+
+void sp_lpe_item_set_path_effect(SPLPEItem *lpeitem, gchar *value)
+{
+ if (!value) {
+ sp_lpe_item_remove_path_effect(lpeitem, false);
+ } else {
+ SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", value);
+
+ // make sure there is an original-d for paths!!!
+ sp_lpe_item_create_original_path_recursive(lpeitem);
+ }
+}
+
+void sp_lpe_item_set_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * new_lpeobj)
+{
+ const gchar * repr_id = SP_OBJECT_REPR(new_lpeobj)->attribute("id");
+ gchar *hrefstr = g_strdup_printf("#%s", repr_id);
+ sp_lpe_item_set_path_effect(lpeitem, hrefstr);
+ g_free(hrefstr);
+}
+
+void sp_lpe_item_remove_path_effect(SPLPEItem *lpeitem, bool keep_paths)
+{
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(lpeitem);
+ repr->setAttribute("inkscape:path-effect", NULL);
+
+ if (!keep_paths) {
+ sp_lpe_item_cleanup_original_path_recursive(lpeitem);
+ }
+}
+
+bool sp_lpe_item_has_path_effect(SPLPEItem *lpeitem)
+{
+ return lpeitem->path_effect_ref && lpeitem->path_effect_ref->lpeobject;
+}
+
+bool sp_lpe_item_has_path_effect_recursive(SPLPEItem *lpeitem)
+{
+ SPObject *parent = lpeitem->parent;
+ if (parent && SP_IS_LPE_ITEM(parent)) {
+ return sp_lpe_item_has_path_effect(lpeitem) || sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(parent));
+ }
+ else {
+ return sp_lpe_item_has_path_effect(lpeitem);
+ }
+}
+
+void sp_lpe_item_edit_next_param_oncanvas(SPLPEItem *lpeitem, SPDesktop *dt)
+{
+ LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
+ if (lpeobj && lpeobj->lpe) {
+ lpeobj->lpe->editNextParamOncanvas(SP_ITEM(lpeitem), dt);
+ }
+}
+
+static void
+sp_lpe_item_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
+{
+ if (((SPObjectClass *) (parent_class))->child_added)
+ (* ((SPObjectClass *) (parent_class))->child_added) (object, child, ref);
+
+ if (SP_IS_LPE_ITEM(object) && sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(object))) {
+ SPObject *ochild = sp_object_get_child_by_repr(object, child);
+ if ( ochild && SP_IS_LPE_ITEM(ochild) ) {
+ sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(ochild));
+ }
+ }
+}
+
+static void
+sp_lpe_item_remove_child (SPObject * object, Inkscape::XML::Node * child)
+{
+ if (SP_IS_LPE_ITEM(object) && sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(object))) {
+ SPObject *ochild = sp_object_get_child_by_repr(object, child);
+ if ( ochild && SP_IS_LPE_ITEM(ochild) ) {
+ sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(ochild));
+ }
+ }
+
+ if (((SPObjectClass *) (parent_class))->remove_child)
+ (* ((SPObjectClass *) (parent_class))->remove_child) (object, child);
+}
+
+/*
+ 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:encoding=utf-8:textwidth=99 :
diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h
new file mode 100644
index 000000000..a818eeb53
--- /dev/null
+++ b/src/sp-lpe-item.h
@@ -0,0 +1,69 @@
+#ifndef SP_LPE_ITEM_H_SEEN
+#define SP_LPE_ITEM_H_SEEN
+
+/** \file
+ * Base class for live path effect items
+ */
+/*
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
+ * Bastien Bouclet <bgkweb@gmail.com>
+ *
+ * Copyright (C) 2008 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "sp-item.h"
+#include "display/curve.h"
+
+#define SP_TYPE_LPE_ITEM (sp_lpe_item_get_type())
+#define SP_LPE_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_LPE_ITEM, SPLPEItem))
+#define SP_LPE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_LPE_ITEM, SPLPEItemClass))
+#define SP_IS_LPE_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), SP_TYPE_LPE_ITEM))
+#define SP_IS_LPE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_LPE_ITEM))
+
+struct LivePathEffectObject;
+namespace Inkscape{
+namespace LivePathEffect{
+ class LPEObjectReference;
+ class Effect;
+};
+};
+
+struct SPLPEItem : public SPItem {
+ Inkscape::LivePathEffect::LPEObjectReference *path_effect_ref;
+ sigc::connection lpe_modified_connection;
+};
+
+struct SPLPEItemClass {
+ SPItemClass parent_class;
+
+ void (* update_patheffect) (SPLPEItem *lpeitem, bool write);
+};
+
+GType sp_lpe_item_get_type();
+
+LivePathEffectObject * sp_lpe_item_get_livepatheffectobject(SPLPEItem *lpeitem);
+Inkscape::LivePathEffect::Effect * sp_lpe_item_get_livepatheffect(SPLPEItem *lpeitem);
+void sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool write);
+void sp_lpe_item_perform_path_effect(SPLPEItem *lpeitem, SPCurve *curve);
+void sp_lpe_item_set_path_effect(SPLPEItem *lpeitem, gchar *value);
+void sp_lpe_item_set_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * new_lpeobj);
+void sp_lpe_item_remove_path_effect(SPLPEItem *lpeitem, bool keep_paths);
+bool sp_lpe_item_has_path_effect(SPLPEItem *lpeitem);
+bool sp_lpe_item_has_path_effect_recursive(SPLPEItem *lpeitem);
+void sp_lpe_item_edit_next_param_oncanvas(SPLPEItem *lpeitem, SPDesktop *dt);
+
+#endif /* !SP_LPE_ITEM_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:encoding=utf-8:textwidth=99 :