1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * The reference corresponding to the inkscape:live-effect attribute
4 *
5 * Copyright (C) 2007 Johan Engelen
6 *
7 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
8 */
9
10 #include "live_effects/lpeobject-reference.h"
11
12 #include <cstring>
13
14 #include "bad-uri-exception.h"
15 #include "live_effects/lpeobject.h"
16 #include "object/uri.h"
17
18 namespace Inkscape {
19
20 namespace LivePathEffect {
21
22 static void lpeobjectreference_href_changed(SPObject *old_ref, SPObject *ref, LPEObjectReference *lpeobjref);
23 static void lpeobjectreference_delete_self(SPObject *deleted, LPEObjectReference *lpeobjref);
24 static void lpeobjectreference_source_modified(SPObject *iSource, guint flags, LPEObjectReference *lpeobjref);
25
LPEObjectReference(SPObject * i_owner)26 LPEObjectReference::LPEObjectReference(SPObject* i_owner) : URIReference(i_owner)
27 {
28 owner=i_owner;
29 lpeobject_href = nullptr;
30 lpeobject_repr = nullptr;
31 lpeobject = nullptr;
32 _changed_connection = changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobjectreference_href_changed), this)); // listening to myself, this should be virtual instead
33
34 user_unlink = nullptr;
35 }
36
~LPEObjectReference()37 LPEObjectReference::~LPEObjectReference()
38 {
39 _changed_connection.disconnect(); // to do before unlinking
40
41 quit_listening();
42 unlink();
43 }
44
_acceptObject(SPObject * const obj) const45 bool LPEObjectReference::_acceptObject(SPObject * const obj) const
46 {
47 LivePathEffectObject *lpobj = dynamic_cast<LivePathEffectObject *>(obj);
48 if (lpobj) {
49 return URIReference::_acceptObject(obj);
50 } else {
51 return false;
52 }
53 }
54
55 void
link(const char * to)56 LPEObjectReference::link(const char *to)
57 {
58 if (!to || !to[0]) {
59 quit_listening();
60 unlink();
61 } else {
62 if ( !lpeobject_href || ( strcmp(to, lpeobject_href) != 0 ) ) {
63 if (lpeobject_href) {
64 g_free(lpeobject_href);
65 }
66 lpeobject_href = g_strdup(to);
67 try {
68 attach(Inkscape::URI(to));
69 } catch (Inkscape::BadURIException &e) {
70 /* TODO: Proper error handling as per
71 * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing.
72 */
73 g_warning("%s", e.what());
74 detach();
75 }
76 }
77 }
78 }
79
80 void
unlink()81 LPEObjectReference::unlink()
82 {
83 if (lpeobject_href) {
84 g_free(lpeobject_href);
85 lpeobject_href = nullptr;
86 }
87 detach();
88 }
89
90 void
start_listening(LivePathEffectObject * to)91 LPEObjectReference::start_listening(LivePathEffectObject* to)
92 {
93 if ( to == nullptr ) {
94 return;
95 }
96 lpeobject = to;
97 lpeobject_repr = to->getRepr();
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 }
101
102 void
quit_listening()103 LPEObjectReference::quit_listening()
104 {
105 _modified_connection.disconnect();
106 _delete_connection.disconnect();
107 lpeobject_repr = nullptr;
108 lpeobject = nullptr;
109 }
110
111 static void
lpeobjectreference_href_changed(SPObject *,SPObject *,LPEObjectReference * lpeobjref)112 lpeobjectreference_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, LPEObjectReference *lpeobjref)
113 {
114 lpeobjref->quit_listening();
115 LivePathEffectObject *refobj = dynamic_cast<LivePathEffectObject *>( lpeobjref->getObject() );
116 if ( refobj ) {
117 lpeobjref->start_listening(refobj);
118 }
119 if (lpeobjref->owner) {
120 lpeobjref->owner->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
121 }
122 }
123
124 static void
lpeobjectreference_delete_self(SPObject *,LPEObjectReference * lpeobjref)125 lpeobjectreference_delete_self(SPObject */*deleted*/, LPEObjectReference *lpeobjref)
126 {
127 lpeobjref->quit_listening();
128 lpeobjref->unlink();
129 if (lpeobjref->user_unlink) {
130 lpeobjref->user_unlink(lpeobjref, lpeobjref->owner);
131 }
132 }
133
134 static void
lpeobjectreference_source_modified(SPObject *,guint,LPEObjectReference * lpeobjref)135 lpeobjectreference_source_modified(SPObject */*iSource*/, guint /*flags*/, LPEObjectReference *lpeobjref)
136 {
137 // We dont need to request update when LPE XML is updated
138 // Retain it temporary, drop if no regression
139 // SPObject *owner_obj = lpeobjref->owner;
140 // if (owner_obj) {
141 // lpeobjref->owner->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
142 // }
143 }
144
145 } //namespace LivePathEffect
146
147 } // namespace inkscape
148
149 /*
150 Local Variables:
151 mode:c++
152 c-file-style:"stroustrup"
153 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
154 indent-tabs-mode:nil
155 fill-column:99
156 End:
157 */
158 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
159