From 59db2c5bfb49604bc4a1ae45f3723f2b8803bbaf Mon Sep 17 00:00:00 2001 From: johanengelen Date: Fri, 28 Mar 2008 19:31:06 +0000 Subject: [PATCH] Add two files that were forgotten in last commit --- src/sp-lpe-item.cpp | 451 ++++++++++++++++++++++++++++++++++++++++++++ src/sp-lpe-item.h | 69 +++++++ 2 files changed, 520 insertions(+) create mode 100644 src/sp-lpe-item.cpp create mode 100644 src/sp-lpe-item.h 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 + * Bastien Bouclet + * + * 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(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(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 + * Bastien Bouclet + * + * 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 : -- 2.30.2