57
56
static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable);
59
static void lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPLPEItem *lpeitem);
60
58
static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeitem);
62
60
static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem);
120
118
lpeitem->path_effect_list = new PathEffectList();
121
119
lpeitem->current_path_effect = NULL;
123
new (&lpeitem->lpe_modified_connection) sigc::connection();
121
lpeitem->lpe_modified_connection_list = new std::list<sigc::connection>();
155
153
SPLPEItem *lpeitem = (SPLPEItem *) object;
157
lpeitem->lpe_modified_connection.disconnect();
158
lpeitem->lpe_modified_connection.~connection();
155
// disconnect all modified listeners:
156
for (std::list<sigc::connection>::iterator mod_it = lpeitem->lpe_modified_connection_list->begin();
157
mod_it != lpeitem->lpe_modified_connection_list->end(); ++mod_it)
159
mod_it->disconnect();
161
delete lpeitem->lpe_modified_connection_list;
162
lpeitem->lpe_modified_connection_list = NULL;
160
164
PathEffectList::iterator it = lpeitem->path_effect_list->begin();
161
165
while ( it != lpeitem->path_effect_list->end() ) {
165
169
it = lpeitem->path_effect_list->erase(it);
167
171
// delete the list itself
168
delete SP_LPE_ITEM(object)->path_effect_list;
172
delete lpeitem->path_effect_list;
173
lpeitem->path_effect_list = NULL;
170
175
if (((SPObjectClass *) parent_class)->release)
171
176
((SPObjectClass *) parent_class)->release(object);
187
192
// Disable the path effects while populating the LPE list
188
193
sp_lpe_item_enable_path_effects(lpeitem, false);
195
// disconnect all modified listeners:
196
for ( std::list<sigc::connection>::iterator mod_it = lpeitem->lpe_modified_connection_list->begin();
197
mod_it != lpeitem->lpe_modified_connection_list->end();
200
mod_it->disconnect();
202
lpeitem->lpe_modified_connection_list->clear();
190
203
// Clear the path effect list
191
204
PathEffectList::iterator it = lpeitem->path_effect_list->begin();
192
205
while ( it != lpeitem->path_effect_list->end() )
202
215
std::string href;
203
216
while (std::getline(iss, href, ';'))
205
Inkscape::LivePathEffect::LPEObjectReference *path_effect_ref = new Inkscape::LivePathEffect::LPEObjectReference(SP_OBJECT(lpeitem));
206
path_effect_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobject_ref_changed), SP_LPE_ITEM(object)));
207
// Now do the attaching, which emits the changed signal.
208
// Fixme, it should not do this changed signal and updating before all effects are added to the path_effect_list
218
Inkscape::LivePathEffect::LPEObjectReference *path_effect_ref = new Inkscape::LivePathEffect::LPEObjectReference(object);
210
220
path_effect_ref->link(href.c_str());
211
221
} catch (Inkscape::BadURIException e) {
218
228
lpeitem->path_effect_list->push_back(path_effect_ref);
219
if ( !(path_effect_ref->lpeobject && path_effect_ref->lpeobject->get_lpe()) ) {
229
if ( path_effect_ref->lpeobject && path_effect_ref->lpeobject->get_lpe() ) {
230
// connect modified-listener
231
lpeitem->lpe_modified_connection_list->push_back(
232
path_effect_ref->lpeobject->connectModified(sigc::bind(sigc::ptr_fun(&lpeobject_ref_modified), lpeitem)) );
220
234
// something has gone wrong in finding the right patheffect.
221
235
g_warning("Unknown LPE type specified, LPE stack effectively disabled");
222
236
// keep the effect in the lpestack, so the whole stack is effectively disabled but maintained
248
262
// update the helperpaths of all LPEs applied to the item
249
// TODO: is there a more canonical place for this, since we don't have instant access to the item's nodepath?
250
// FIXME: this is called multiple (at least 3) times; how can we avoid this?
252
// FIXME: ditch inkscape_active_event_context()
253
SPEventContext *ec = inkscape_active_event_context();
254
if (!SP_IS_NODE_CONTEXT(ec)) return;
255
ShapeEditor *sh = ec->shape_editor;
257
if (!sh->has_nodepath()) return;
259
Inkscape::NodePath::Path *np = sh->get_nodepath();
260
sp_nodepath_update_helperpaths(np);
263
// TODO: re-add for the new node tool
380
383
if (dynamic_cast<Inkscape::LivePathEffect::LPEPathLength *>(lpe)) {
381
384
if (!lpe->isVisible()) {
382
385
// we manually disable text for LPEPathLength
383
dynamic_cast<Inkscape::LivePathEffect::LPEPathLength *>(lpe)->hideCanvasText();
386
// use static_cast, because we already checked for the right type above
387
static_cast<Inkscape::LivePathEffect::LPEPathLength *>(lpe)->hideCanvasText();
410
* Gets called when (re)attached to another lpeobject.
413
lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPLPEItem *lpeitem)
416
sp_signal_disconnect_by_data(old_ref, lpeitem);
418
if ( IS_LIVEPATHEFFECT(ref) && ref != lpeitem )
420
lpeitem->lpe_modified_connection.disconnect();
421
lpeitem->lpe_modified_connection = ref->connectModified(sigc::bind(sigc::ptr_fun(&lpeobject_ref_modified), lpeitem));
422
lpeobject_ref_modified(ref, 0, lpeitem);
427
* Gets called when lpeobject repr contents change: i.e. parameter change.
414
* Gets called when any of the lpestack's lpeobject repr contents change: i.e. parameter change in any of the stacked LPEs
430
417
lpeobject_ref_modified(SPObject */*href*/, guint /*flags*/, SPLPEItem *lpeitem)
420
g_message("lpeobject_ref_modified");
432
422
sp_lpe_item_update_patheffect (lpeitem, true, true);
754
744
Inkscape::LivePathEffect::LPEObjectReference* sp_lpe_item_get_current_lpereference(SPLPEItem *lpeitem)
756
if (!lpeitem->current_path_effect && !lpeitem->path_effect_list->empty())
746
if (!lpeitem->current_path_effect && !lpeitem->path_effect_list->empty()) {
757
747
sp_lpe_item_set_current_path_effect(lpeitem, lpeitem->path_effect_list->back());
759
750
return lpeitem->current_path_effect;
774
765
for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); it++) {
775
766
if ((*it)->lpeobject_repr == lperef->lpeobject_repr) {
776
lpeobject_ref_changed(NULL, (*it)->lpeobject, SP_LPE_ITEM(lpeitem)); // FIXME: explain why this is here?
777
767
lpeitem->current_path_effect = (*it); // current_path_effect should always be a pointer from the path_effect_list !
785
void sp_lpe_item_replace_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * old_lpeobj,
786
LivePathEffectObject * new_lpeobj)
776
* Writes a new "inkscape:path-effect" string to xml, where the old_lpeobjects are substituted by the new ones.
777
* Note that this method messes up the item's \c PathEffectList.
779
void SPLPEItem::replacePathEffects( std::vector<LivePathEffectObject const *> const old_lpeobjs,
780
std::vector<LivePathEffectObject const *> const new_lpeobjs )
788
782
HRefList hreflist;
789
for (PathEffectList::const_iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
783
for (PathEffectList::const_iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it)
791
if ((*it)->lpeobject == old_lpeobj) {
792
const gchar * repr_id = SP_OBJECT_REPR(new_lpeobj)->attribute("id");
785
LivePathEffectObject const * current_lpeobj = (*it)->lpeobject;
786
std::vector<LivePathEffectObject const *>::const_iterator found_it(std::find(old_lpeobjs.begin(), old_lpeobjs.end(), current_lpeobj));
787
if ( found_it != old_lpeobjs.end() ) {
788
std::vector<LivePathEffectObject const *>::difference_type found_index = std::distance (old_lpeobjs.begin(), found_it);
789
const gchar * repr_id = SP_OBJECT_REPR(new_lpeobjs[found_index])->attribute("id");
793
790
gchar *hrefstr = g_strdup_printf("#%s", repr_id);
794
791
hreflist.push_back( std::string(hrefstr) );
801
798
std::string r = hreflist_write_svg(hreflist);
802
SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", r.c_str());
799
SP_OBJECT_REPR(this)->setAttribute("inkscape:path-effect", r.c_str());
803
* Check all effects in the stack if they are used by other items, and fork them if so.
804
* It is not recommended to fork the effects by yourself calling LivePathEffectObject::fork_private_if_necessary,
805
* use this method instead.
806
* Returns true if one or more effects were forked; returns false if nothing was done.
808
bool sp_lpe_item_fork_path_effects_if_necessary(SPLPEItem *lpeitem, unsigned int nr_of_allowed_users)
812
if ( sp_lpe_item_has_path_effect(lpeitem) ) {
813
// If one of the path effects is used by 2 or more items, fork it
814
// so that each object has its own independent copy of the effect.
815
// Note: replacing path effects messes up the path effect list
817
// Clones of the LPEItem will increase the refcount of the lpeobjects.
818
// Therefore, nr_of_allowed_users should be increased with the number of clones (i.e. refs to the lpeitem)
819
nr_of_allowed_users += SP_OBJECT(lpeitem)->hrefcount;
821
std::vector<LivePathEffectObject const *> old_lpeobjs, new_lpeobjs;
822
PathEffectList effect_list = sp_lpe_item_get_effect_list(lpeitem);
823
for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++)
825
LivePathEffectObject *lpeobj = (*it)->lpeobject;
827
LivePathEffectObject *forked_lpeobj = lpeobj->fork_private_if_necessary(nr_of_allowed_users);
828
if (forked_lpeobj != lpeobj) {
830
old_lpeobjs.push_back(lpeobj);
831
new_lpeobjs.push_back(forked_lpeobj);
837
lpeitem->replacePathEffects(old_lpeobjs, new_lpeobjs);
805
844
// Enable or disable the path effects of the item.