Same as before but for Rectangle and Star Tools.
[synfig.git] / synfig-studio / src / synfigapp / canvasinterface.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file canvasinterface.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007, 2008 Chris Moore
10 **      Copyright (c) 2009 Carlos A. Sosa Navarro
11 **
12 **      This package is free software; you can redistribute it and/or
13 **      modify it under the terms of the GNU General Public License as
14 **      published by the Free Software Foundation; either version 2 of
15 **      the License, or (at your option) any later version.
16 **
17 **      This package is distributed in the hope that it will be useful,
18 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
19 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 **      General Public License for more details.
21 **      \endlegal
22 */
23 /* ========================================================================= */
24
25 /* === H E A D E R S ======================================================= */
26
27 #ifdef USING_PCH
28 #       include "pch.h"
29 #else
30 #ifdef HAVE_CONFIG_H
31 #       include <config.h>
32 #endif
33
34 //#include <iostream>
35
36 #include <ETL/clock>
37 #include <synfig/valuenode_scale.h>
38 #include <synfig/valuenode_timedswap.h>
39 #include <synfig/valuenode_composite.h>
40 #include <synfig/valuenode_subtract.h>
41 #include <synfig/valuenode_linear.h>
42 #include <synfig/valuenode_reference.h>
43 #include <synfig/valuenode_twotone.h>
44 #include <synfig/valuenode_stripes.h>
45 #include <synfig/valuenode_bline.h>
46
47 #include <synfig/waypoint.h>
48 #include <synfig/loadcanvas.h>
49 #include <synfig/importer.h>
50 #include <synfig/guidset.h>
51
52 #include "canvasinterface.h"
53 #include "instance.h"
54
55 #include "actions/layeradd.h"
56 #include "actions/layerremove.h"
57 #include "actions/valuedescconvert.h"
58 #include "actions/valuenodeadd.h"
59 #include "actions/editmodeset.h"
60 #include "action_system.h"
61
62 #include "main.h"
63
64 #include <synfig/gradient.h>
65
66 #include "general.h"
67
68 #endif
69
70 /* === U S I N G =========================================================== */
71
72 using namespace std;
73 using namespace etl;
74 using namespace synfig;
75 using namespace synfigapp;
76
77 /* === M A C R O S ========================================================= */
78
79 /* === G L O B A L S ======================================================= */
80
81 /* === P R O C E D U R E S ================================================= */
82
83 /* === M E T H O D S ======================================================= */
84
85 CanvasInterface::CanvasInterface(etl::loose_handle<Instance> instance,etl::handle<synfig::Canvas> canvas):
86         instance_(instance),
87         canvas_(canvas),
88         cur_time_(canvas->rend_desc().get_frame_start()),
89         mode_(MODE_NORMAL|MODE_ANIMATE_PAST|MODE_ANIMATE_FUTURE)
90 {
91         set_selection_manager(get_instance()->get_selection_manager());
92         set_ui_interface(get_instance()->get_ui_interface());
93 }
94
95 CanvasInterface::~CanvasInterface()
96 {
97         if (getenv("SYNFIG_DEBUG_DESTRUCTORS"))
98                 synfig::info("CanvasInterface::~CanvasInterface(): Deleted");
99 }
100
101 void
102 CanvasInterface::set_time(synfig::Time x)
103 {
104         if(get_canvas()->rend_desc().get_frame_rate())
105         {
106                 float fps(get_canvas()->rend_desc().get_frame_rate());
107                 Time r(x.round(fps));
108                 //synfig::info("CanvasInterface::set_time(): %s rounded to %s\n",x.get_string(fps).c_str(),r.get_string(fps).c_str());
109                 x=r;
110         }
111         if(cur_time_.is_equal(x))
112                 return;
113         get_canvas()->set_time(cur_time_=x);
114
115         // update the time in all the child canvases
116         Canvas::Children children = get_canvas()->get_root()->children();
117         handle<CanvasInterface> interface;
118         for (Canvas::Children::iterator iter = children.begin(); iter != children.end(); iter++)
119                 if ((interface = get_instance()->find_canvas_interface(*iter)) != this)
120                         interface->set_time(interface->get_canvas()->get_time());
121
122         signal_time_changed()();
123         signal_dirty_preview()();
124 }
125
126 synfig::Time
127 CanvasInterface::get_time()const
128 {
129         return cur_time_;
130 }
131
132 void
133 CanvasInterface::refresh_current_values()
134 {
135         get_canvas()->set_time(cur_time_);
136         signal_time_changed()();
137         signal_dirty_preview()();
138 }
139
140 etl::handle<CanvasInterface>
141 CanvasInterface::create(etl::loose_handle<Instance> instance, etl::handle<synfig::Canvas> canvas)
142 {
143         etl::handle<CanvasInterface> intrfc;
144         intrfc=new CanvasInterface(instance,canvas);
145         instance->canvas_interface_list().push_front(intrfc);
146         return intrfc;
147 }
148
149 void
150 CanvasInterface::set_mode(Mode x)
151 {
152         Action::Handle  action(Action::EditModeSet::create());
153
154         assert(action);
155
156         action->set_param("canvas",get_canvas());
157         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
158         action->set_param("edit_mode",x);
159
160         if(!action->is_ready())
161         {
162                 get_ui_interface()->error(_("Action Not Ready, unable to change mode"));
163                 assert(0);
164                 return;
165         }
166
167         if(!get_instance()->perform_action(action))
168                 get_ui_interface()->error(_("Unable to change mode"));
169
170 //      mode_=x;
171 //      signal_mode_changed_(x);
172 }
173
174 CanvasInterface::Mode
175 CanvasInterface::get_mode()const
176 {
177         return mode_;
178 }
179
180
181
182 Layer::Handle
183 CanvasInterface::add_layer_to(synfig::String name, synfig::Canvas::Handle canvas, int depth)
184 {
185         synfigapp::Action::PassiveGrouper group(get_instance().get(),_("Add Layer To"));
186
187         Layer::Handle   layer(Layer::create(name));
188
189         assert(layer);
190
191         if(!layer)
192                 return 0;
193
194         if(canvas!=get_canvas() && !canvas->is_inline())
195         {
196                 synfig::error("Bad canvas passed to \"add_layer_to\"");
197                 return 0;
198         }
199
200         // automatically export the Index parameter of new Duplicate layers
201         if (name == "duplicate")
202                 for (int i = 1; ; i++)
203                 {
204                         String name = strprintf(_("Index %d"), i);
205                         try
206                         {
207                                 canvas->find_value_node(name);
208                         }
209                         catch (Exception::IDNotFound x)
210                         {
211                                 add_value_node(layer->dynamic_param_list().find("index")->second, name);
212                                 break;
213                         }
214                 }
215
216         layer->set_canvas(canvas);
217
218         // Apply some defaults
219         if(layer->set_param("fg",synfigapp::Main::get_outline_color()))
220                 layer->set_param("bg",synfigapp::Main::get_fill_color());
221         else if (name == "outline")
222                 layer->set_param("color",synfigapp::Main::get_outline_color());
223         else
224                 layer->set_param("color",synfigapp::Main::get_fill_color());
225
226         layer->set_param("width",synfigapp::Main::get_bline_width().units(get_canvas()->rend_desc()));
227         layer->set_param("gradient",synfigapp::Main::get_gradient());
228         if(name!="zoom")
229                 layer->set_param("amount",synfigapp::Main::get_opacity());
230         layer->set_param("blend_method",synfigapp::Main::get_blend_method());
231
232         {
233                 // Grab the layer's list of parameters
234                 Layer::ParamList paramlist=layer->get_param_list();
235                 Layer::ParamList::iterator iter;
236
237                 // loop through the static parameters
238                 for(iter=paramlist.begin();iter!=paramlist.end();++iter)
239                 {
240                         ValueNode::Handle value_node;
241
242                         // if we find any which are list values then make them
243                         // into dynamic list valuenodes, unless every element of
244                         // the list is a blinepoint, in which case convert it to a
245                         // bline
246                         if(iter->second.get_type()==ValueBase::TYPE_LIST)
247                         {
248                                 // check whether it's a list of blinepoints only
249                                 vector<ValueBase> list(iter->second.get_list());
250                                 if (list.size())
251                                 {
252                                         vector<ValueBase>::iterator iter2;
253                                         for (iter2 = list.begin(); iter2 != list.end(); iter2++)
254                                                 if (iter2->get_type() != ValueBase::TYPE_BLINEPOINT)
255                                                         break;
256                                         if (iter2 == list.end())
257                                         {
258                                                 value_node=LinkableValueNode::create("bline",iter->second);
259                                                 ValueNode_BLine::Handle::cast_dynamic(value_node)->set_member_canvas(canvas);
260                                         }
261                                 }
262
263                                 if (!value_node)
264                                         value_node=LinkableValueNode::create("dynamic_list",iter->second);
265                         }
266                         // otherwise, if it's a type that can be converted to
267                         // 'composite' (other than the types that can be radial
268                         // composite) then do so
269                         else if(LinkableValueNode::check_type("composite",iter->second.get_type()) &&
270                                          (iter->second.get_type()!=ValueBase::TYPE_COLOR &&
271                                           iter->second.get_type()!=ValueBase::TYPE_VECTOR))
272                                 value_node=LinkableValueNode::create("composite",iter->second);
273
274                         if(value_node)
275                                 layer->connect_dynamic_param(iter->first,value_node);
276                 }
277         }
278
279         // Action to add the layer
280         Action::Handle  action(Action::LayerAdd::create());
281
282         assert(action);
283         if(!action)
284                 return 0;
285
286         action->set_param("canvas",canvas);
287         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
288         action->set_param("new",layer);
289
290         if(!action->is_ready())
291         {
292                 get_ui_interface()->error(_("Action Not Ready"));
293                 return 0;
294         }
295
296         if(!get_instance()->perform_action(action))
297         {
298                 get_ui_interface()->error(_("Action Failed."));
299                 return 0;
300         }
301
302         // synfig::info("DEPTH=%d",depth);
303
304         // Action to move the layer (if necessary)
305         if(depth>0)
306         {
307                 Action::Handle  action(Action::create("LayerMove"));
308
309                 assert(action);
310                 if(!action)
311                         return 0;
312
313                 action->set_param("canvas",canvas);
314                 action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
315                 action->set_param("layer",layer);
316                 action->set_param("new_index",depth);
317
318                 if(!action->is_ready())
319                 {
320                         get_ui_interface()->error(_("Move Action Not Ready"));
321                         return 0;
322                 }
323
324                 if(!get_instance()->perform_action(action))
325                 {
326                         get_ui_interface()->error(_("Move Action Failed."));
327                         return 0;
328                 }
329         }
330
331
332         return layer;
333 }
334
335
336 bool
337 CanvasInterface::convert(ValueDesc value_desc, synfig::String type)
338 {
339         Action::Handle  action(Action::ValueDescConvert::create());
340
341         assert(action);
342         if(!action)
343                 return 0;
344
345         action->set_param("canvas",get_canvas());
346         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
347         action->set_param("value_desc",value_desc);
348         action->set_param("type",type);
349         action->set_param("time",get_time());
350
351         if(!action->is_ready())
352         {
353                 get_ui_interface()->error(_("Action Not Ready"));
354                 return 0;
355         }
356
357         if(get_instance()->perform_action(action))
358                 return true;
359
360         get_ui_interface()->error(_("Action Failed."));
361         return false;
362 }
363
364 bool
365 CanvasInterface::add_value_node(synfig::ValueNode::Handle value_node, synfig::String name)
366 {
367         if(name.empty())
368         {
369                 get_ui_interface()->error(_("Empty name!"));
370                 return false;
371         }
372
373         Action::Handle  action(Action::ValueNodeAdd::create());
374
375         assert(action);
376         if(!action)
377                 return 0;
378
379         action->set_param("canvas",get_canvas());
380         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
381         action->set_param("new",value_node);
382         action->set_param("name",name);
383
384         if(!action->is_ready())
385         {
386                 get_ui_interface()->error(_("Action Not Ready"));
387                 return 0;
388         }
389
390         if(get_instance()->perform_action(action))
391                 return true;
392
393         get_ui_interface()->error(_("Action Failed."));
394         return false;
395 }
396
397 Action::ParamList
398 CanvasInterface::generate_param_list(const ValueDesc &value_desc)
399 {
400         synfigapp::Action::ParamList param_list;
401         param_list.add("time",get_time());
402         param_list.add("canvas_interface",etl::handle<CanvasInterface>(this));
403         param_list.add("canvas",get_canvas());
404
405         param_list.add("value_desc",value_desc);
406
407         if(value_desc.parent_is_value_node())
408                 param_list.add("parent_value_node",value_desc.get_parent_value_node());
409
410         if(value_desc.is_value_node())
411                 param_list.add("value_node",value_desc.get_value_node());
412
413         if(value_desc.is_const())
414         {
415                 // Fix 1868911: if we put a ValueBase holding a Canvas handle
416                 // into the param_list and then export the canvas, the handle
417                 // will miss out of having its reference count reduced,
418                 // because by the time the handle is destructed the canvas
419                 // will no longer be inline.  So let's not propogate that
420                 // ValueBase any further than here.
421                 if (value_desc.get_value_type() == ValueBase::TYPE_CANVAS)
422                         param_list.add("value",Canvas::LooseHandle(value_desc.get_value().get(Canvas::LooseHandle())));
423                 else
424                         param_list.add("value",value_desc.get_value());
425         }
426
427         if(value_desc.parent_is_layer_param())
428         {
429                 param_list.add("parent_layer",value_desc.get_layer());
430                 param_list.add("parent_layer_param",value_desc.get_param_name());
431         }
432
433         {
434                 synfigapp::SelectionManager::ChildrenList children_list;
435                 children_list=get_selection_manager()->get_selected_children();
436                 if(!value_desc.parent_is_canvas() && children_list.size()==1)
437                 {
438                         param_list.add("dest",value_desc);
439                         param_list.add("src",children_list.front().get_value_node());
440                 }
441         }
442         return param_list;
443 }
444
445 Action::ParamList
446 CanvasInterface::generate_param_list(const std::list<synfigapp::ValueDesc> &value_desc_list)
447 {
448         synfigapp::Action::ParamList param_list;
449         param_list.add("time",get_time());
450         param_list.add("canvas_interface",etl::handle<CanvasInterface>(this));
451         param_list.add("canvas",get_canvas());
452
453         std::list<synfigapp::ValueDesc>::const_iterator iter;
454         for(iter=value_desc_list.begin();iter!=value_desc_list.end();++iter)
455         {
456                 param_list.add("value_desc",*iter);
457                 if(iter->is_value_node())
458                 {
459                         param_list.add("value_node",iter->get_value_node());
460                 }
461         }
462
463
464         return param_list;
465 }
466
467 void
468 CanvasInterface::set_rend_desc(const synfig::RendDesc &rend_desc)
469 {
470         Action::Handle  action(Action::create("CanvasRendDescSet"));
471
472         assert(action);
473         if(!action)
474                 return;
475
476         action->set_param("canvas",get_canvas());
477         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
478         action->set_param("rend_desc",rend_desc);
479
480         if(!get_instance()->perform_action(action))
481                 get_ui_interface()->error(_("Action Failed."));
482 }
483
484 void
485 CanvasInterface::set_name(const synfig::String &x)
486 {
487         Action::Handle  action(Action::create("CanvasNameSet"));
488
489         assert(action);
490         if(!action)
491                 return;
492
493         action->set_param("canvas",get_canvas());
494         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
495         action->set_param("name",x);
496
497         if(!get_instance()->perform_action(action))
498                 get_ui_interface()->error(_("Action Failed."));
499
500         signal_id_changed_();
501 }
502
503 void
504 CanvasInterface::set_description(const synfig::String &x)
505 {
506         Action::Handle  action(Action::create("CanvasDescriptionSet"));
507
508         assert(action);
509         if(!action)
510                 return;
511
512         action->set_param("canvas",get_canvas());
513         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
514         action->set_param("description",x);
515
516         if(!get_instance()->perform_action(action))
517                 get_ui_interface()->error(_("Action Failed."));
518 }
519
520 void
521 CanvasInterface::set_id(const synfig::String &x)
522 {
523         Action::Handle  action(Action::create("CanvasIdSet"));
524
525         assert(action);
526         if(!action)
527                 return;
528
529         action->set_param("canvas",get_canvas());
530         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
531         action->set_param("id",x);
532
533         if(!get_instance()->perform_action(action))
534                 get_ui_interface()->error(_("Action Failed."));
535
536         signal_id_changed_();
537 }
538
539
540 void
541 CanvasInterface::jump_to_next_keyframe()
542 {
543         synfig::info("Current time: %s",get_time().get_string().c_str());
544         try
545         {
546                 synfig::Keyframe keyframe(*get_canvas()->keyframe_list().find_next(get_time()));
547                 synfig::info("Jumping to keyframe \"%s\" at %s",keyframe.get_description().c_str(),keyframe.get_time().get_string().c_str());
548                 set_time(keyframe.get_time());
549         }
550         catch(...) { synfig::warning("Unable to find next keyframe"); }
551 }
552
553 void
554 CanvasInterface::jump_to_prev_keyframe()
555 {
556         synfig::info("Current time: %s",get_time().get_string().c_str());
557         try
558         {
559                 synfig::Keyframe keyframe(*get_canvas()->keyframe_list().find_prev(get_time()));
560                 synfig::info("Jumping to keyframe \"%s\" at %s",keyframe.get_description().c_str(),keyframe.get_time().get_string().c_str());
561                 set_time(keyframe.get_time());
562         }
563         catch(...) { synfig::warning("Unable to find prev keyframe"); }
564 }
565
566 bool
567 CanvasInterface::import(const synfig::String &filename, synfig::String &errors, synfig::String &warnings, bool resize_image)
568 {
569         Action::PassiveGrouper group(get_instance().get(),_("Import Image"));
570
571         synfig::info("Attempting to import "+filename);
572
573         if (filename_extension(filename) == "")
574         {
575                 get_ui_interface()->error(_("Filename must have an extension!"));
576                 return false;
577         }
578
579         String ext(filename_extension(filename));
580         if (ext.size()) ext = ext.substr(1); // skip initial '.'
581         std::transform(ext.begin(),ext.end(),ext.begin(),&::tolower);
582
583         if(ext=="svg"){//I don't like it, but worse is nothing
584                 Layer::Handle _new_layer(add_layer_to("PasteCanvas",get_canvas()));
585                 Layer::Handle _aux_layer(add_layer_to("svg_layer",get_canvas()));
586                 if(_aux_layer){
587                         _aux_layer->set_param("filename",ValueBase(filename));
588                         _new_layer->set_param("canvas",ValueBase(_aux_layer->get_param("canvas")));
589                         //remove aux layer
590                         Action::Handle  action(Action::LayerRemove::create());
591                         assert(action);
592                         if(!action)
593                                 return 0;
594                         action->set_param("canvas",get_canvas());
595                         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
596                         action->set_param("layer",_aux_layer);
597                         if(!action->is_ready()){
598                                 get_ui_interface()->error(_("Action Not Ready"));
599                                 return 0;
600                         }
601                         if(!get_instance()->perform_action(action)){
602                                 get_ui_interface()->error(_("Action Failed."));
603                                 return 0;
604                         }
605                 }
606                 signal_layer_new_description()(_new_layer,filename);
607                 return true;
608         }
609
610         // If this is a SIF file, then we need to do things slightly differently
611         if(ext=="sif" || ext=="sifz")try
612         {
613                 Canvas::Handle outside_canvas(synfig::open_canvas(filename, errors, warnings));
614                 if(!outside_canvas)
615                         throw String(_("Unable to open this composition")) + ":\n\n" + errors;
616
617                 Layer::Handle layer(add_layer_to("PasteCanvas",get_canvas()));
618                 if(!layer)
619                         throw String(_("Unable to create \"Paste Canvas\" layer"));
620                 if(!layer->set_param("canvas",ValueBase(outside_canvas)))
621                         throw int();
622                 get_canvas()->register_external_canvas(filename, outside_canvas);
623
624                 //layer->set_description(basename(filename));
625                 signal_layer_new_description()(layer,filename);
626                 return true;
627         }
628         catch(String x)
629         {
630                 get_ui_interface()->error(filename + ": " + x);
631                 return false;
632         }
633         catch(...)
634         {
635                 get_ui_interface()->error(_("Uncaught exception when attempting\nto open this composition -- ")+filename);
636                 return false;
637         }
638
639         if(!Importer::book().count(ext))
640         {
641                 get_ui_interface()->error(_("I don't know how to open images of this type -- ")+ext);
642                 return false;
643         }
644
645         try
646         {
647                 Layer::Handle layer(add_layer_to("Import",get_canvas()));
648                 int w,h;
649                 if(!layer)
650                         throw int();
651                 if(!layer->set_param("filename",ValueBase(filename)))
652                         throw int();
653                 w=layer->get_param("_width").get(int());
654                 h=layer->get_param("_height").get(int());
655                 if(w&&h)
656                 {
657                         Vector x, size=ValueBase(get_canvas()->rend_desc().get_br()-get_canvas()->rend_desc().get_tl());
658
659                         // vector from top left of canvas to bottom right
660                         if (resize_image)
661                         {
662                                 if(abs(size[0])<abs(size[1]))   // if canvas is tall and thin
663                                 {
664                                         x[0]=size[0];   // use full width
665                                         x[1]=size[0]/w*h; // and scale for height
666                                         if((size[0]<0) ^ (size[1]<0))
667                                                 x[1]=-x[1];
668                                 }
669                                 else                            // else canvas is short and fat (or maybe square)
670                                 {
671                                         x[1]=size[1];   // use full height
672                                         x[0]=size[1]/h*w; // and scale for width
673                                         if((size[0]<0) ^ (size[1]<0))
674                                                 x[0]=-x[0];
675                                 }
676                         }
677                         else
678                         {
679                                 x[0] = w/60.0;
680                                 x[1] = h/60.0;
681                                 if((size[0]<0)) x[0]=-x[0];
682                                 if((size[1]<0)) x[1]=-x[1];
683                         }
684
685                         if(!layer->set_param("tl",ValueBase(-x/2)))
686                                 throw int();
687                         if(!layer->set_param("br",ValueBase(x/2)))
688                                 throw int();
689                 }
690                 else
691                 {
692                         if(!layer->set_param("tl",ValueBase(get_canvas()->rend_desc().get_tl())))
693                                 throw int();
694                         if(!layer->set_param("br",ValueBase(get_canvas()->rend_desc().get_br())))
695                                 throw int();
696                 }
697
698                 layer->set_description(basename(filename));
699                 signal_layer_new_description()(layer,filename);
700
701                 return true;
702         }
703         catch(...)
704         {
705                 get_ui_interface()->error("Unable to import "+filename);
706                 group.cancel();
707                 return false;
708         }
709 }
710
711
712 void
713 CanvasInterface::waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)
714 {
715         ValueNode::Handle value_node();
716         waypoint_duplicate(value_desc.get_value_node(), waypoint);
717 }
718
719 void
720 CanvasInterface::waypoint_duplicate(ValueNode::Handle value_node,synfig::Waypoint waypoint)
721 {
722         Action::Handle  action(Action::create("WaypointSetSmart"));
723
724         assert(action);
725         if(!action)
726                 return;
727
728         waypoint.make_unique();
729         waypoint.set_time(get_time());
730
731         action->set_param("canvas",get_canvas());
732         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
733         action->set_param("waypoint",waypoint);
734         action->set_param("time",get_time());
735         action->set_param("value_node",value_node);
736
737         if(!get_instance()->perform_action(action))
738                 get_ui_interface()->error(_("Action Failed."));
739 }
740
741 void
742 CanvasInterface::waypoint_remove(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)
743 {
744         ValueNode::Handle value_node();
745         waypoint_remove(value_desc.get_value_node(), waypoint);
746 }
747
748 void
749 CanvasInterface::waypoint_remove(ValueNode::Handle value_node,synfig::Waypoint waypoint)
750 {
751         Action::Handle  action(Action::create("WaypointRemove"));
752
753         assert(action);
754         if(!action)
755                 return;
756
757         action->set_param("canvas",get_canvas());
758         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
759         action->set_param("waypoint",waypoint);
760         action->set_param("value_node",value_node);
761
762         if(!get_instance()->perform_action(action))
763                 get_ui_interface()->error(_("Action Failed."));
764 }
765
766
767 void
768 CanvasInterface::auto_export(synfig::ValueNode::Handle /*value_node*/)
769 {
770 /*
771         // Check to see if we are already exported.
772         if(value_node->is_exported())
773                 return;
774
775         Action::Handle  action(Action::create("ValueNodeAdd"));
776
777         assert(action);
778         if(!action)
779                 return;
780
781         String name(strprintf(_("Unnamed%08d"),synfig::UniqueID().get_uid()));
782
783         action->set_param("canvas",get_canvas());
784         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
785         action->set_param("new",value_node);
786         action->set_param("name",name);
787
788         if(!get_instance()->perform_action(action))
789                 get_ui_interface()->error(_("Action Failed."));
790 */
791 }
792
793 void
794 CanvasInterface::auto_export(const ValueDesc& /*value_desc*/)
795 {
796         // THIS FUNCTION IS DEPRECATED, AND IS NOW A STUB.
797 #if 0
798         // Check to see if we are already exported.
799         if(value_desc.is_exported())
800                 return;
801
802         Action::Handle  action(Action::create("ValueDescExport"));
803
804         assert(action);
805         if(!action)
806                 return;
807
808         String name(strprintf(_("Unnamed%08d"),synfig::UniqueID().get_uid()));
809
810         action->set_param("canvas",get_canvas());
811         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
812         action->set_param("value_desc",value_desc);
813         action->set_param("name",name);
814
815         if(!get_instance()->perform_action(action))
816                 get_ui_interface()->error(_("Action Failed."));
817 #endif
818 }
819
820 bool
821 CanvasInterface::change_value(synfigapp::ValueDesc value_desc,synfig::ValueBase new_value)
822 {
823         // If this isn't really a change, then don't bother
824         if(new_value==value_desc.get_value(get_time()))
825                 return true;
826
827         // If this change needs to take place elsewhere, then so be it.
828         if(value_desc.get_canvas())
829         {
830                 if (value_desc.get_canvas()->get_root() != get_canvas()->get_root())
831                 {
832                         etl::handle<Instance> instance;
833                         instance=find_instance(value_desc.get_canvas()->get_root());
834
835                         if(instance)
836                                 return instance->find_canvas_interface(value_desc.get_canvas())->change_value(value_desc,new_value);
837                         else
838                         {
839                                 get_ui_interface()->error(_("The value you are trying to edit is in a composition\nwhich doesn't seem to be open. Open that composition and you\nshould be able to edit this value as normal."));
840                                 return false;
841                         }
842                 }
843         }
844 #ifdef _DEBUG
845         else
846         { synfig::warning("Can't get canvas from value desc...?"); }
847 #endif
848
849         synfigapp::Action::Handle action(synfigapp::Action::create("ValueDescSet"));
850         if(!action)
851         {
852                 return false;
853         }
854
855         action->set_param("canvas",get_canvas());
856         action->set_param("canvas_interface",etl::loose_handle<CanvasInterface>(this));
857         action->set_param("time",get_time());
858         action->set_param("value_desc",value_desc);
859         action->set_param("new_value",new_value);
860
861         return get_instance()->perform_action(action);
862 }
863
864 void
865 CanvasInterface::set_meta_data(const synfig::String& key,const synfig::String& data)
866 {
867         get_canvas()->set_meta_data(key,data);
868 }
869
870
871 // this function goes with find_important_value_descs()
872 static int
873 _process_value_desc(const synfigapp::ValueDesc& value_desc,std::vector<synfigapp::ValueDesc>& out, synfig::GUIDSet& guid_set)
874 {
875         int ret(0);
876
877         if(value_desc.get_value_type()==ValueBase::TYPE_CANVAS)
878         {
879                 Canvas::Handle canvas;
880                 canvas=value_desc.get_value().get(canvas);
881                 if(!canvas || !canvas->is_inline())
882                         return ret;
883                 ret+=CanvasInterface::find_important_value_descs(canvas,out,guid_set);
884         }
885
886         if(value_desc.is_value_node())
887         {
888                 ValueNode::Handle value_node(value_desc.get_value_node());
889
890                 if(guid_set.count(value_node->get_guid()))
891                         return ret;
892                 guid_set.insert(value_node->get_guid());
893
894                 if(LinkableValueNode::Handle::cast_dynamic(value_node))
895                 {
896                         if(ValueNode_DynamicList::Handle::cast_dynamic(value_node))
897                         {
898                                 out.push_back(value_desc);
899                                 ret++;
900                         }
901                         // Process the linkable ValueNode's children
902                         LinkableValueNode::Handle value_node_copy(LinkableValueNode::Handle::cast_dynamic(value_node));
903                         int i;
904                         for(i=0;i<value_node_copy->link_count();i++)
905                         {
906                                 ValueNode::Handle link(value_node_copy->get_link(i));
907                                 if(!link->is_exported())
908                                         ret+=_process_value_desc(ValueDesc(value_node_copy,i),out,guid_set);
909                         }
910                 }
911                 else if(ValueNode_Animated::Handle::cast_dynamic(value_node))
912                 {
913                         out.push_back(value_desc);
914                         ret++;
915                 }
916         }
917
918         return ret;
919 }
920
921 int
922 CanvasInterface::find_important_value_descs(synfig::Canvas::Handle canvas,std::vector<synfigapp::ValueDesc>& out,synfig::GUIDSet& guid_set)
923 {
924         int ret(0);
925         if(!canvas->is_inline())
926         {
927                 ValueNodeList::const_iterator iter;
928
929                 for(
930                         iter=canvas->value_node_list().begin();
931                         iter!=canvas->value_node_list().end();
932                         ++iter)
933                         ret+=_process_value_desc(ValueDesc(canvas,(*iter)->get_id()),out,guid_set);
934         }
935
936         Canvas::const_iterator iter;
937
938         for(iter=canvas->begin();iter!=canvas->end();++iter)
939         {
940                 Layer::Handle layer(*iter);
941
942                 Layer::DynamicParamList::const_iterator iter;
943                 for(
944                         iter=layer->dynamic_param_list().begin();
945                         iter!=layer->dynamic_param_list().end();
946                         ++iter)
947                 {
948                         if(!iter->second->is_exported())
949                                 ret+=_process_value_desc(ValueDesc(layer,iter->first),out,guid_set);
950                 }
951                 ValueBase value(layer->get_param("canvas"));
952                 if(value.is_valid())
953                         ret+=_process_value_desc(ValueDesc(layer,"canvas"),out,guid_set);
954         }
955
956         return ret;
957 }
958
959 int
960 CanvasInterface::find_important_value_descs(std::vector<synfigapp::ValueDesc>& out)
961 {
962         synfig::GUIDSet tmp;
963         return find_important_value_descs(get_canvas(),out,tmp);
964 }
965
966 void
967 CanvasInterface::seek_frame(int frames)
968 {
969         if(!frames)
970                 return;
971         float fps(get_canvas()->rend_desc().get_frame_rate());
972         Time newtime(get_time()+(float)frames/fps);
973         newtime=newtime.round(fps);
974
975         if(newtime<=get_canvas()->rend_desc().get_time_start())
976                 newtime=get_canvas()->rend_desc().get_time_start();
977         if(newtime>=get_canvas()->rend_desc().get_time_end())
978                 newtime=get_canvas()->rend_desc().get_time_end();
979         set_time(newtime);
980 }
981
982 void
983 CanvasInterface::seek_time(synfig::Time time)
984 {
985         if(!time)
986                 return;
987
988         float fps(get_canvas()->rend_desc().get_frame_rate());
989
990         if(time>=synfig::Time::end())
991         {
992                 set_time(get_canvas()->rend_desc().get_time_end());
993                 return;
994         }
995         if(time<=synfig::Time::begin())
996         {
997                 set_time(get_canvas()->rend_desc().get_time_start());
998                 return;
999         }
1000
1001         Time newtime(get_time()+time);
1002         newtime=newtime.round(fps);
1003
1004         if(newtime<=get_canvas()->rend_desc().get_time_start())
1005                 newtime=get_canvas()->rend_desc().get_time_start();
1006         if(newtime>=get_canvas()->rend_desc().get_time_end())
1007                 newtime=get_canvas()->rend_desc().get_time_end();
1008         set_time(newtime);
1009 }