From: johanengelen Date: Thu, 27 Mar 2008 23:02:23 +0000 (+0000) Subject: add linking to other paths to lpe-PathParam X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=43f848b15ee40a6c108ae9d965cf06f055ecb7a5;p=inkscape.git add linking to other paths to lpe-PathParam --- diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert index f56000fce..484060384 100644 --- a/src/live_effects/parameter/Makefile_insert +++ b/src/live_effects/parameter/Makefile_insert @@ -17,6 +17,8 @@ live_effects_parameter_liblpeparam_a_SOURCES = \ live_effects/parameter/pointparam-knotholder.cpp \ live_effects/parameter/pointparam-knotholder.h \ live_effects/parameter/enum.h \ + live_effects/parameter/path-reference.cpp \ + live_effects/parameter/path-reference.h \ live_effects/parameter/path.cpp \ live_effects/parameter/path.h diff --git a/src/live_effects/parameter/path-reference.cpp b/src/live_effects/parameter/path-reference.cpp new file mode 100644 index 000000000..6a48f446b --- /dev/null +++ b/src/live_effects/parameter/path-reference.cpp @@ -0,0 +1,53 @@ +/* + * The reference corresponding to href of LPE Path parameter. + * + * Copyright (C) 2008 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information. + */ + +#include "live_effects/parameter/path-reference.h" + +#include +#include +#include + +#include "enums.h" + +#include "display/curve.h" +#include "livarot/Path.h" +#include "prefs-utils.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "uri.h" + +namespace Inkscape { +namespace LivePathEffect { + +bool PathReference::_acceptObject(SPObject * const obj) const +{ + if (SP_IS_SHAPE(obj) || SP_IS_TEXT(obj)) { + /* Refuse references to lpeobject */ + if (obj == getOwner()) { + return false; + } + // TODO: check whether the referred path has this LPE applied, if so: deny deny deny! + return true; + } else { + return false; + } +} + +} // namespace LivePathEffect +} // namespace Inkscape + +/* + 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 : diff --git a/src/live_effects/parameter/path-reference.h b/src/live_effects/parameter/path-reference.h new file mode 100644 index 000000000..88147d908 --- /dev/null +++ b/src/live_effects/parameter/path-reference.h @@ -0,0 +1,60 @@ +#ifndef SEEN_LPE_PATH_REFERENCE_H +#define SEEN_LPE_PATH_REFERENCE_H + +/* + * The reference corresponding to href of LPE PathParam. + * + * Copyright (C) 2008 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information. + */ + +#include +#include +#include + +class Path; + +namespace Inkscape { + +namespace XML { + struct Node; +} + +namespace LivePathEffect { + + +class PathReference : public Inkscape::URIReference { +public: + PathReference(SPObject *owner) : URIReference(owner) {} + + SPItem *getObject() const { + return (SPItem *)URIReference::getObject(); + } + +protected: + virtual bool _acceptObject(SPObject * const obj) const; + +private: + PathReference(const PathReference&); + PathReference& operator=(const PathReference&); +}; + +} // namespace LivePathEffect + +} // namespace Inkscape + + + +#endif /* !SEEN_LPE_PATH_REFERENCE_H */ + +/* + 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 : diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp index db4102635..be26006c7 100644 --- a/src/live_effects/parameter/path.cpp +++ b/src/live_effects/parameter/path.cpp @@ -34,6 +34,12 @@ #include "nodepath.h" // clipboard support #include "ui/clipboard.h" +// required for linking to other paths +#include "uri.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "display/curve.h" + namespace Inkscape { @@ -46,15 +52,21 @@ PathParam::PathParam( const Glib::ustring& label, const Glib::ustring& tip, _pathvector(), _pwd2(), must_recalculate_pwd2(false), - href(NULL) + href(NULL), + ref( (SPObject*)effect->getLPEObj() ) { defvalue = g_strdup(default_value); param_readSVGValue(defvalue); oncanvas_editable = true; + + ref_changed_connection = ref.changedSignal().connect(sigc::mem_fun(*this, &PathParam::ref_changed)); + } PathParam::~PathParam() { + remove_link(); + g_free(defvalue); } @@ -88,16 +100,22 @@ PathParam::param_readSVGValue(const gchar * strvalue) { if (strvalue) { _pathvector.clear(); - if (href) { - g_free(href); - href = NULL; - } + remove_link(); must_recalculate_pwd2 = true; - if (false /*if strvalue is xlink*/) { + if (strvalue[0] == '#') { + if (href) + g_free(href); href = g_strdup(strvalue); - update_from_referred(); - // TODO: add listener, because we must update when referred updates. we must always be up-to-date with referred path data + + // Now do the attaching, which emits the changed signal. + try { + ref.attach(Inkscape::URI(href)); + } catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + ref.detach(); + _pathvector = SVGD_to_2GeomPath(defvalue); + } } else { _pathvector = SVGD_to_2GeomPath(strvalue); } @@ -112,8 +130,12 @@ PathParam::param_readSVGValue(const gchar * strvalue) gchar * PathParam::param_writeSVGValue() const { - gchar * svgd = SVGD_from_2GeomPath( _pathvector ); - return svgd; + if (href) { + return href; + } else { + gchar * svgd = SVGD_from_2GeomPath( _pathvector ); + return svgd; + } } Gtk::Widget * @@ -155,6 +177,16 @@ PathParam::param_newWidget(Gtk::Tooltips * tooltips) static_cast(_widget)->pack_start(*pButton, true, true); tooltips->set_tip(*pButton, _("Paste path")); + pIcon = Gtk::manage( sp_icon_get_icon( "edit_clone", Inkscape::ICON_SIZE_BUTTON) ); + pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_link_button_click)); + static_cast(_widget)->pack_start(*pButton, true, true); + tooltips->set_tip(*pButton, _("Link to path")); + static_cast(_widget)->show_all_children(); return dynamic_cast (_widget); @@ -187,8 +219,9 @@ PathParam::param_setup_nodepath(Inkscape::NodePath::Path *np) void PathParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/) { - // TODO: recode this to apply transform to _pathvector instead? if (!href) { + // TODO: recode this to apply transform to _pathvector instead? + // only apply transform when not referring to other path ensure_pwd2(); param_set_and_write_new_value( _pwd2 * postmul ); @@ -198,6 +231,7 @@ PathParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/) void PathParam::param_set_and_write_new_value (Geom::Piecewise > const & newpath) { + remove_link(); _pathvector = Geom::path_from_piecewise(newpath, LPE_CONVERSION_TOLERANCE); gchar * svgd = SVGD_from_2GeomPath( _pathvector ); param_write_to_repr(svgd); @@ -221,16 +255,71 @@ PathParam::ensure_pwd2() } void -PathParam::update_from_referred() +PathParam::start_listening(SPObject * to) { - if (!href) { - g_warning("PathParam::update_from_referred - logical error, this should not possible"); + if ( to == NULL ) { return; } + linked_delete_connection = to->connectDelete(sigc::mem_fun(*this, &PathParam::linked_delete)); + linked_modified_connection = to->connectModified(sigc::mem_fun(*this, &PathParam::linked_modified)); + linked_modified(to, SP_OBJECT_MODIFIED_FLAG); // simulate linked_modified signal, so that path data is updated +} - // TODO: implement! - - // optimize, only update from referred when referred changed. +void +PathParam::quit_listening(void) +{ + linked_modified_connection.disconnect(); + linked_delete_connection.disconnect(); +} + +void +PathParam::ref_changed(SPObject */*old_ref*/, SPObject *new_ref) +{ + quit_listening(); + if ( new_ref ) { + start_listening(new_ref); + } +} + +void +PathParam::remove_link() +{ + if (href) { + ref.detach(); + g_free(href); + href = NULL; + } +} + +void +PathParam::linked_delete(SPObject */*deleted*/) +{ +// don't know what to do yet. not acting probably crashes inkscape. + g_message("PathParam::linked_delete"); +} + +void +PathParam::linked_modified(SPObject *linked_obj, guint /*flags*/) +{ + SPCurve *curve = NULL; + if (SP_IS_SHAPE(linked_obj)) { + curve = sp_shape_get_curve(SP_SHAPE(linked_obj)); + } + if (SP_IS_TEXT(linked_obj)) { + curve = SP_TEXT(linked_obj)->getNormalizedBpath(); + } + + if (curve == NULL) { + // curve invalid, set default value + _pathvector = SVGD_to_2GeomPath(defvalue); + } else { + _pathvector = BPath_to_2GeomPath(SP_CURVE_BPATH(curve)); + sp_curve_unref(curve); + } + + must_recalculate_pwd2 = true; + signal_path_changed.emit(); + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); } /* CALLBACK FUNCTIONS FOR THE BUTTONS */ @@ -249,7 +338,8 @@ PathParam::on_paste_button_click() Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); Glib::ustring svgd = cm->getPathParameter(); - if (svgd == "") return; + if (svgd == "") + return; // Temporary hack until 2Geom supports arcs in SVGD if (svgd.find('A') != Glib::ustring::npos) { @@ -257,6 +347,9 @@ PathParam::on_paste_button_click() _("This effect does not support arcs yet, try to convert to path.") ); return; } else { + // remove possible link to path + remove_link(); + param_write_to_repr(svgd.data()); signal_path_pasted.emit(); sp_document_done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, @@ -271,6 +364,32 @@ PathParam::on_copy_button_click() cm->copyPathParameter(this); } +void +PathParam::on_link_button_click() +{ + Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); + Glib::ustring pathid = cm->getShapeOrTextObjectId(); + + if (pathid == "") { + return; + } + + // add '#' at start to make it an uri. + pathid.insert(pathid.begin(), '#'); + if ( href && strcmp(pathid.c_str(), href) == 0 ) { + // no change, do nothing + return; + } else { + // TODO: + // check if id really exists in document, or only in clipboard document: if only in clipboard then invalid + // check if linking to object to which LPE is applied (maybe delegated to PathReference + + param_write_to_repr(pathid.c_str()); + sp_document_done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Link path parameter to path")); + } +} + } /* namespace LivePathEffect */ } /* namespace Inkscape */ diff --git a/src/live_effects/parameter/path.h b/src/live_effects/parameter/path.h index b294c0d2e..1f2be32c8 100644 --- a/src/live_effects/parameter/path.h +++ b/src/live_effects/parameter/path.h @@ -15,7 +15,7 @@ #include #include "live_effects/parameter/parameter.h" - +#include "live_effects/parameter/path-reference.h" #include namespace Inkscape { @@ -60,11 +60,21 @@ protected: void ensure_pwd2(); // ensures _pwd2 is up to date gchar * href; // contains link to other object, e.g. "#path2428", NULL if PathParam contains pathdata itself - void update_from_referred(); // updates path data by looking up refered path + PathReference ref; + sigc::connection ref_changed_connection; + sigc::connection linked_delete_connection; + sigc::connection linked_modified_connection; + void ref_changed(SPObject *old_ref, SPObject *new_ref); + void remove_link(); + void start_listening(SPObject * to); + void quit_listening(void); + void linked_delete(SPObject *deleted); + void linked_modified(SPObject *linked_obj, guint flags); void on_edit_button_click(); void on_paste_button_click(); void on_copy_button_click(); + void on_link_button_click(); gchar * defvalue; diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 31a943365..081657cf0 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -95,7 +95,7 @@ public: virtual bool pasteSize(bool, bool, bool); virtual bool pastePathEffect(); virtual Glib::ustring getPathParameter(); - virtual Glib::ustring getPathObjectId(); + virtual Glib::ustring getShapeOrTextObjectId(); ClipboardManagerImpl(); ~ClipboardManagerImpl(); @@ -439,25 +439,28 @@ Glib::ustring ClipboardManagerImpl::getPathParameter() /** - * @brief Get path object id from the clipboard - * @return The retrieved path id string (contents of the id attribute), or "" if no path was found + * @brief Get object id of a shape or text item from the clipboard + * @return The retrieved id string (contents of the id attribute), or "" if no shape or text item was found */ -Glib::ustring ClipboardManagerImpl::getPathObjectId() +Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId() { SPDocument *tempdoc = _retrieveClipboard(); // any target will do here if ( tempdoc == NULL ) { _userWarn(SP_ACTIVE_DESKTOP, _("Nothing on the clipboard.")); return ""; } - Inkscape::XML::Node - *root = sp_document_repr_root(tempdoc), - *path = sp_repr_lookup_name(root, "svg:path", -1); // unlimited search depth - if ( path == NULL ) { + Inkscape::XML::Node *root = sp_document_repr_root(tempdoc); + + Inkscape::XML::Node *repr = sp_repr_lookup_name(root, "svg:path", -1); // unlimited search depth + if ( repr == NULL ) + repr = sp_repr_lookup_name(root, "svg:text", -1); + + if ( repr == NULL ) { _userWarn(SP_ACTIVE_DESKTOP, _("Clipboard does not contain a path.")); sp_document_unref(tempdoc); return ""; } - gchar const *svgd = path->attribute("id"); + gchar const *svgd = repr->attribute("id"); return svgd; } diff --git a/src/ui/clipboard.h b/src/ui/clipboard.h index bb214dbf7..609f2a93c 100644 --- a/src/ui/clipboard.h +++ b/src/ui/clipboard.h @@ -46,7 +46,7 @@ public: virtual bool pasteSize(bool separately, bool apply_x, bool apply_y) = 0; virtual bool pastePathEffect() = 0; virtual Glib::ustring getPathParameter() = 0; - virtual Glib::ustring getPathObjectId() = 0; + virtual Glib::ustring getShapeOrTextObjectId() = 0; static ClipboardManager *get(); protected: