1 /*
2 * The reference corresponding to the inkscape:live-effect attribute
3 *
4 * Copyright (C) 2007 Johan Engelen
5 *
6 * Released under GNU GPL, read the file 'COPYING' for more information.
7 */
9 #include <string.h>
11 #include "enums.h"
12 #include "live_effects/lpeobject-reference.h"
13 #include "live_effects/lpeobject.h"
14 #include "uri.h"
16 namespace Inkscape {
18 namespace LivePathEffect {
20 static void lpeobjectreference_href_changed(SPObject *old_ref, SPObject *ref, LPEObjectReference *lpeobjref);
21 static void lpeobjectreference_delete_self(SPObject *deleted, LPEObjectReference *lpeobjref);
22 static void lpeobjectreference_source_modified(SPObject *iSource, guint flags, LPEObjectReference *lpeobjref);
24 LPEObjectReference::LPEObjectReference(SPObject* i_owner) : URIReference(i_owner)
25 {
26 owner=i_owner;
27 lpeobject_href = NULL;
28 lpeobject_repr = NULL;
29 lpeobject = NULL;
30 _changed_connection = changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobjectreference_href_changed), this)); // listening to myself, this should be virtual instead
32 user_unlink = NULL;
33 }
35 LPEObjectReference::~LPEObjectReference(void)
36 {
37 _changed_connection.disconnect(); // to do before unlinking
39 quit_listening();
40 unlink();
41 }
43 bool LPEObjectReference::_acceptObject(SPObject * const obj) const
44 {
45 if (IS_LIVEPATHEFFECT(obj)) {
46 SPObject * const owner = getOwner();
47 /* Refuse references to us or to an ancestor. */
48 for ( SPObject *iter = owner ; iter ; iter = SP_OBJECT_PARENT(iter) ) {
49 if ( iter == obj ) {
50 return false;
51 }
52 }
53 return true;
54 } else {
55 return false;
56 }
57 }
59 void
60 LPEObjectReference::link(const char *to)
61 {
62 if ( to == NULL ) {
63 quit_listening();
64 unlink();
65 } else {
66 if ( !lpeobject_href || ( strcmp(to, lpeobject_href) != 0 ) ) {
67 g_free(lpeobject_href);
68 lpeobject_href = g_strdup(to);
69 try {
70 attach(Inkscape::URI(to));
71 } catch (Inkscape::BadURIException &e) {
72 /* TODO: Proper error handling as per
73 * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing.
74 */
75 g_warning("%s", e.what());
76 detach();
77 }
78 }
79 }
80 }
82 void
83 LPEObjectReference::unlink(void)
84 {
85 g_free(lpeobject_href);
86 lpeobject_href = NULL;
87 detach();
88 }
90 void
91 LPEObjectReference::start_listening(LivePathEffectObject* to)
92 {
93 if ( to == NULL ) {
94 return;
95 }
96 lpeobject = to;
97 lpeobject_repr = SP_OBJECT_REPR(to);
98 _delete_connection = to->connectDelete(sigc::bind(sigc::ptr_fun(&lpeobjectreference_delete_self), this));
99 _modified_connection = to->connectModified(sigc::bind<2>(sigc::ptr_fun(&lpeobjectreference_source_modified), this));
100 }
102 void
103 LPEObjectReference::quit_listening(void)
104 {
105 if ( lpeobject == NULL ) {
106 return;
107 }
108 _modified_connection.disconnect();
109 _delete_connection.disconnect();
110 lpeobject_repr = NULL;
111 lpeobject = NULL;
112 }
114 static void
115 lpeobjectreference_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, LPEObjectReference *lpeobjref)
116 {
117 lpeobjref->quit_listening();
118 LivePathEffectObject *refobj = LIVEPATHEFFECT( lpeobjref->getObject() );
119 if ( refobj ) {
120 lpeobjref->start_listening(refobj);
121 }
123 lpeobjref->owner->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
124 }
126 static void
127 lpeobjectreference_delete_self(SPObject */*deleted*/, LPEObjectReference *lpeobjref)
128 {
129 lpeobjref->quit_listening();
130 lpeobjref->unlink();
131 if (lpeobjref->user_unlink)
132 lpeobjref->user_unlink(lpeobjref, lpeobjref->owner);
133 }
135 static void
136 lpeobjectreference_source_modified(SPObject */*iSource*/, guint /*flags*/, LPEObjectReference *lpeobjref)
137 {
138 lpeobjref->owner->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
139 }
141 } //namespace LivePathEffect
143 } // namespace inkscape
145 /*
146 Local Variables:
147 mode:c++
148 c-file-style:"stroustrup"
149 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
150 indent-tabs-mode:nil
151 fill-column:99
152 End:
153 */
154 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :