Don't include header files that aren't needed.
[synfig.git] / synfig-studio / trunk / src / gtkmm / canvasview.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file canvasview.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 #include <sigc++/adaptors/hide.h>
33
34 #include <ETL/clock>
35 #include <sstream>
36
37 #include <gtkmm/paned.h>
38 #include <gtkmm/scale.h>
39 #include <gtkmm/dialog.h>
40 #include <gtkmm/messagedialog.h>
41 #include <gtkmm/treemodelsort.h>
42 #include <gtkmm/buttonbox.h>
43
44 #include <gtk/gtktreestore.h>
45 #include <gtk/gtkversion.h>
46
47 #include <synfig/valuenode_dynamiclist.h>
48 #include <synfig/layer.h>
49
50 #include <synfigapp/uimanager.h>
51 #include <synfigapp/canvasinterface.h>
52 #include <synfigapp/selectionmanager.h>
53
54 #include <sigc++/retype_return.h>
55 #include <sigc++/retype.h>
56
57 #include "canvasview.h"
58 #include "instance.h"
59 #include "app.h"
60 #include "cellrenderer_timetrack.h"
61 #include "eventkey.h"
62
63 #include "widget_timeslider.h"
64
65 #endif
66
67 /* === U S I N G =========================================================== */
68
69 using namespace std;
70 using namespace etl;
71 using namespace synfig;
72 using namespace studio;
73 using namespace SigC;
74
75 /* === M A C R O S ========================================================= */
76
77 #define GRAB_HINT_DATA(y)       { \
78                 String x; \
79                 if(synfigapp::Main::settings().get_value(String("pref.")+y+"_hints",x)) \
80                 { \
81                         set_type_hint((Gdk::WindowTypeHint)atoi(x.c_str()));    \
82                 } \
83         }
84
85 #define DEFAULT_TIME_WINDOW_SIZE                (10.0)
86
87 /*
88 #ifdef DEBUGPOINT
89 #undef DEBUGPOINT
90 #endif
91 #define DEBUGPOINT()
92 */
93
94 #ifndef SMALL_BUTTON
95 #define SMALL_BUTTON(button,stockid,tooltip)    \
96         button = manage(new class Gtk::Button());       \
97         icon=manage(new Gtk::Image(Gtk::StockID(stockid),iconsize));    \
98         button->add(*icon);     \
99         tooltips.set_tip(*button,tooltip);      \
100         icon->set_padding(0,0);\
101         icon->show();   \
102         button->set_relief(Gtk::RELIEF_NONE); \
103         button->show()
104 #endif
105
106 #ifndef NORMAL_BUTTON
107 #define NORMAL_BUTTON(button,stockid,tooltip)   \
108         button = manage(new class Gtk::Button());       \
109         icon=manage(new Gtk::Image(Gtk::StockID(stockid),Gtk::ICON_SIZE_BUTTON));       \
110         button->add(*icon);     \
111         tooltips.set_tip(*button,tooltip);      \
112         icon->set_padding(0,0);\
113         icon->show();   \
114         /*button->set_relief(Gtk::RELIEF_NONE);*/ \
115         button->show()
116 #endif
117
118 #define NEW_SMALL_BUTTON(x,y,z) Gtk::Button *SMALL_BUTTON(x,y,z)
119
120 #define NOT_IMPLEMENTED_SLOT sigc::mem_fun(*reinterpret_cast<studio::CanvasViewUIInterface*>(get_ui_interface().get()),&studio::CanvasViewUIInterface::not_implemented)
121
122 #define SLOT_EVENT(x)   sigc::hide_return(sigc::bind(sigc::mem_fun(*this,&studio::CanvasView::process_event_key),x))
123
124 /* === C L A S S E S ======================================================= */
125
126
127 class studio::UniversalScrubber
128 {
129         CanvasView *canvas_view;
130
131         bool            scrubbing;
132         etl::clock      scrub_timer;
133
134         sigc::connection end_scrub_connection;
135 public:
136         UniversalScrubber(CanvasView *canvas_view):
137                 canvas_view(canvas_view),
138                 scrubbing(false)
139         {
140                 canvas_view->canvas_interface()->signal_time_changed().connect(
141                         sigc::mem_fun(*this,&studio::UniversalScrubber::on_time_changed)
142                 );
143         }
144
145         ~UniversalScrubber()
146         {
147                 end_scrub_connection.disconnect();
148         }
149
150         void on_time_changed()
151         {
152                 // Make sure we are changing the time quickly
153                 // before we enable scrubbing
154                 if(!scrubbing && scrub_timer()>1)
155                 {
156                         scrub_timer.reset();
157                         return;
158                 }
159
160                 // If we aren't scrubbing already, enable it
161                 if(!scrubbing)
162                 {
163                         scrubbing=true;
164                         audio_container()->start_scrubbing(canvas_view->get_time());
165                 }
166
167                 // Reset the scrubber ender
168                 end_scrub_connection.disconnect();
169                 end_scrub_connection=Glib::signal_timeout().connect(
170                         sigc::bind_return(
171                                 sigc::mem_fun(*this,&UniversalScrubber::end_of_scrubbing),
172                                 false
173                         ),
174                         1000
175                 );
176
177                 // Scrub!
178                 audio_container()->scrub(canvas_view->get_time());
179
180                 scrub_timer.reset();
181         }
182
183         void end_of_scrubbing()
184         {
185                 scrubbing=false;
186                 audio_container()->stop_scrubbing();
187                 scrub_timer.reset();
188         }
189
190         handle<AudioContainer> audio_container()
191         {
192                 assert(canvas_view->audio);
193                 return canvas_view->audio;
194         }
195 };
196
197
198 class studio::CanvasViewUIInterface : public synfigapp::UIInterface
199 {
200         CanvasView *view;
201
202 public:
203
204         CanvasViewUIInterface(CanvasView *view):
205                 view(view)
206         {
207
208                 view->statusbar->push("Idle");
209         }
210
211         ~CanvasViewUIInterface()
212         {
213                 //view->statusbar->pop();
214                 //view->progressbar->set_fraction(0);
215         }
216
217         virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
218         {
219                 view->present();
220                 //while(studio::App::events_pending())studio::App::iteration(false);
221                 Gtk::Dialog dialog(
222                         title,          // Title
223                         *view,          // Parent
224                         true,           // Modal
225                         true            // use_separator
226                 );
227                 Gtk::Label label(message);
228                 label.show();
229
230                 dialog.get_vbox()->pack_start(label);
231                 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
232                 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
233
234                 dialog.set_default_response(dflt);
235                 dialog.show();
236                 return (Response)dialog.run();
237         }
238         virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
239         {
240                 view->present();
241                 //while(studio::App::events_pending())studio::App::iteration(false);
242                 Gtk::Dialog dialog(
243                         title,          // Title
244                         *view,          // Parent
245                         true,           // Modal
246                         true            // use_separator
247                 );
248                 Gtk::Label label(message);
249                 label.show();
250
251                 dialog.get_vbox()->pack_start(label);
252                 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
253                 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
254                 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
255
256                 dialog.set_default_response(dflt);
257                 dialog.show();
258                 return (Response)dialog.run();
259         }
260         virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
261         {
262                 view->present();
263                 //while(studio::App::events_pending())studio::App::iteration(false);
264                 Gtk::Dialog dialog(
265                         title,          // Title
266                         *view,          // Parent
267                         true,           // Modal
268                         true            // use_separator
269                 );
270                 Gtk::Label label(message);
271                 label.show();
272
273                 dialog.get_vbox()->pack_start(label);
274                 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
275                 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
276
277                 dialog.set_default_response(dflt);
278                 dialog.show();
279                 return (Response)dialog.run();
280         }
281
282         virtual bool
283         task(const std::string &task)
284         {
285                 if(!view->is_playing_)
286                 {
287                         view->statusbar->pop();
288                         view->statusbar->push(task);
289                 }
290                 //while(studio::App::events_pending())studio::App::iteration(false);
291                 if(view->cancel){return false;}
292                 return true;
293         }
294
295         virtual bool
296         error(const std::string &err)
297         {
298                 view->statusbar->push("ERROR");
299
300                 // If we are in the process of canceling,
301                 // then just go ahead and return false --
302                 // don't bother displaying a dialog
303                 if(view->cancel)return false;
304                 Gtk::MessageDialog dialog(*view, err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
305                 dialog.show();
306                 dialog.run();
307                 view->statusbar->pop();
308                 return true;
309         }
310
311         virtual bool
312         warning(const std::string &err)
313         {
314                 view->statusbar->pop();
315                 view->statusbar->push(err);
316
317                 //while(studio::App::events_pending())studio::App::iteration(false);
318                 if(view->cancel)return false;
319                 return true;
320         }
321
322         virtual bool
323         amount_complete(int current, int total)
324         {
325                 if(!view->is_playing_)
326                 {
327                         if(!view->working_depth)
328                         {
329                                 if(current)
330                                         view->stopbutton->set_sensitive(true);
331                                 else
332                                         view->stopbutton->set_sensitive(false);
333                         }
334                         float x((float)current/(float)total);
335                         if(x<0)x=0;
336                         else if(x>1)x=1;
337                         view->progressbar->set_fraction(x);
338                 }
339                 //while(studio::App::events_pending())studio::App::iteration(false);
340                 if(view->cancel){/*view->cancel=false;*/return false;}
341                 return true;
342         }
343
344         void
345         not_implemented()
346         {
347                 error("Feature not yet implemented");
348         }
349 };
350
351 class studio::CanvasViewSelectionManager : public synfigapp::SelectionManager
352 {
353         CanvasView *view;
354         CanvasView::LayerTreeModel layer_tree_model;
355         CanvasView::ChildrenTreeModel children_tree_model;
356 public:
357
358         CanvasViewSelectionManager(CanvasView *view): view(view)
359 {
360
361  }
362
363
364 private:
365         void _set_selected_layer(const synfig::Layer::Handle &layer)
366         {
367                 view->layer_tree->select_layer(layer);
368 /*
369                 // Don't change the selection while we are busy
370                 // I cannot remember exactly why I put this here...
371                 // It musta been for some reason, but I cannot recall.
372                 //if(App::Busy::count)
373                 //      return;
374
375                 if(view->layer_tree->get_selection()->get_selected())
376                 {
377                         const Gtk::TreeRow row = *(view->layer_tree->get_selection()->get_selected());
378
379                         // Don't do anything if that layer is already selected
380                         if(layer == static_cast<synfig::Layer::Handle>(row[layer_tree_model.layer]))
381                                 return;
382                 }
383                 Gtk::TreeModel::Children::iterator iter;
384                 if(view->layer_tree_store()->find_layer_row(layer,iter))
385                 {
386                         Gtk::TreePath path(iter);
387                         for(int i=path.get_depth();i;i--)
388                         {
389                                 int j;
390                                 path=Gtk::TreePath(iter);
391                                 for(j=i;j;j--)
392                                         path.up();
393                                 view->layer_tree->get_tree_view().expand_row(path,false);
394                         }
395                         view->layer_tree->get_tree_view().scroll_to_row(Gtk::TreePath(iter));
396                         view->layer_tree->get_selection()->select(iter);
397                 }
398 */
399         }
400 public:
401
402         //! Returns the number of layers selected.
403         virtual int get_selected_layer_count()const
404         {
405                 return get_selected_layers().size();
406         }
407
408         //! Returns a list of the currently selected layers.
409         virtual LayerList get_selected_layers()const
410         {
411 //              assert(view->layer_tree);
412
413                 if(!view->layer_tree) { DEBUGPOINT(); synfig::error("canvas_view.layer_tree not defined!?"); return LayerList(); }
414                 return view->layer_tree->get_selected_layers();
415         }
416
417         //! Returns the first layer selected or an empty handle if none are selected.
418         virtual synfig::Layer::Handle get_selected_layer()const
419         {
420 //              assert(view->layer_tree);
421
422                 if(!view->layer_tree) { DEBUGPOINT(); synfig::error("canvas_view.layer_tree not defined!?"); return 0; }
423                 return view->layer_tree->get_selected_layer();
424         }
425
426         //! Sets which layers should be selected
427         virtual void set_selected_layers(const LayerList &layer_list)
428         {
429 //              assert(view->layer_tree);
430
431                 if(!view->layer_tree) { DEBUGPOINT(); synfig::error("canvas_view.layer_tree not defined!?"); return; }
432                 view->layer_tree->select_layers(layer_list);
433                 //view->get_smach().process_event(EVENT_REFRESH_DUCKS);
434
435                 //view->queue_rebuild_ducks();
436         }
437
438         //! Sets which layer should be selected.
439         virtual void set_selected_layer(const synfig::Layer::Handle &layer)
440         {
441 //              assert(view->layer_tree);
442
443                 if(!view->layer_tree) { DEBUGPOINT(); synfig::error("canvas_view.layer_tree not defined!?"); return; }
444                 view->layer_tree->select_layer(layer);
445                 //view->queue_rebuild_ducks();
446         }
447
448         //! Clears the layer selection list
449         virtual void clear_selected_layers()
450         {
451                 if(!view->layer_tree) return;
452                 view->layer_tree->clear_selected_layers();
453         }
454
455
456
457         //! Returns the number of value_nodes selected.
458         virtual int get_selected_children_count()const
459         {
460                 return get_selected_children().size();
461         }
462
463         static inline void __child_grabber(const Gtk::TreeModel::iterator& iter, ChildrenList* ret)
464         {
465                 const CanvasView::ChildrenTreeModel children_tree_model;
466                 synfigapp::ValueDesc value_desc((*iter)[children_tree_model.value_desc]);
467                 if(value_desc)
468                         ret->push_back(value_desc);
469         }
470
471         //! Returns a list of the currently selected value_nodes.
472         virtual ChildrenList get_selected_children()const
473         {
474                 if(!view->children_tree) return ChildrenList();
475
476                 Glib::RefPtr<Gtk::TreeSelection> selection=view->children_tree->get_selection();
477
478                 if(!selection)
479                         return ChildrenList();
480
481                 ChildrenList ret;
482
483                 selection->selected_foreach_iter(
484                         sigc::bind(
485                                 sigc::ptr_fun(
486                                         &studio::CanvasViewSelectionManager::__child_grabber
487                                 ),
488                                 &ret
489                         )
490                 );
491
492                 /*
493                 Gtk::TreeModel::Children::iterator iter(view->children_tree_store()->children().begin());
494                 iter++;
495                 Gtk::TreeModel::Children children = iter->children();
496                 for(iter = children.begin(); iter != children.end(); ++iter)
497                 {
498                         Gtk::TreeModel::Row row = *iter;
499                         if(selection->is_selected(row))
500                                 ret.push_back((synfigapp::ValueDesc)row[children_tree_model.value_desc]);
501                 }
502                 */
503                 return ret;
504         }
505
506         //! Returns the first value_node selected or an empty handle if none are selected.
507         virtual ChildrenList::value_type get_selected_child()const
508         {
509                 if(!view->children_tree) return ChildrenList::value_type();
510
511                 ChildrenList children(get_selected_children());
512
513                 if(children.empty())
514                         return ChildrenList::value_type();
515
516                 return children.front();
517         }
518
519         //! Sets which value_nodes should be selected
520         virtual void set_selected_children(const ChildrenList &children_list)
521         {
522                 return;
523         }
524
525         //! Sets which value_node should be selected. Empty handle if none.
526         virtual void set_selected_child(const ChildrenList::value_type &child)
527         {
528                 return;
529         }
530
531         //! Clears the value_node selection list
532         virtual void clear_selected_children()
533         {
534                 return;
535         }
536
537
538
539         int get_selected_layer_parameter_count()const
540         {
541                 return get_selected_layer_parameters().size();
542         }
543
544         LayerParamList get_selected_layer_parameters()const
545         {
546                 if(!view->layer_tree) return LayerParamList();
547
548                 Glib::RefPtr<Gtk::TreeSelection> selection=view->layer_tree->get_selection();
549
550                 if(!selection)
551                         return LayerParamList();
552
553                 LayerParamList ret;
554
555                 Gtk::TreeModel::Children children = const_cast<CanvasView*>(view)->layer_tree_store()->children();
556                 Gtk::TreeModel::Children::iterator iter;
557                 for(iter = children.begin(); iter != children.end(); ++iter)
558                 {
559                         Gtk::TreeModel::Row row = *iter;
560                         Gtk::TreeModel::Children::iterator iter;
561                         for(iter=row.children().begin();iter!=row.children().end();iter++)
562                         {
563                                 Gtk::TreeModel::Row row = *iter;
564                                 if(selection->is_selected(row))
565                                         ret.push_back(LayerParam(row[layer_tree_model.layer],(Glib::ustring)row[layer_tree_model.id]));
566                         }
567                 }
568                 return ret;
569         }
570
571         LayerParam get_selected_layer_parameter() const
572         {
573                 if(!view->layer_tree) return LayerParam();
574                 return get_selected_layer_parameters().front();
575         }
576
577         void set_selected_layer_parameters(const LayerParamList &layer_param_list)
578         {
579                 return;
580         }
581
582         void set_selected_layer_param(const LayerParam &layer_param)
583         {
584                 return;
585         }
586
587         void clear_selected_layer_parameters()
588         {
589                 return;
590         }
591
592 }; // END of class SelectionManager
593
594
595 CanvasView::IsWorking::IsWorking(CanvasView &canvas_view_):
596         canvas_view_(canvas_view_)
597 {
598         if(!canvas_view_.working_depth)
599                 canvas_view_.stopbutton->set_sensitive(true);
600         canvas_view_.working_depth++;
601         canvas_view_.cancel=false;
602 }
603
604 CanvasView::IsWorking::~IsWorking()
605 {
606         canvas_view_.working_depth--;
607         if(!canvas_view_.working_depth)
608                 canvas_view_.stopbutton->set_sensitive(false);
609 }
610
611 CanvasView::IsWorking::operator bool()const
612 {
613         if(canvas_view_.cancel)
614                 return false;
615         return true;
616 }
617
618 /* === M E T H O D S ======================================================= */
619
620 CanvasView::CanvasView(etl::loose_handle<Instance> instance,etl::handle<synfigapp::CanvasInterface> canvas_interface_):
621         smach_                                  (this),
622         instance_                               (instance),
623         canvas_interface_               (canvas_interface_),
624         //layer_tree_store_             (LayerTreeStore::create(canvas_interface_)),
625         //children_tree_store_  (ChildrenTreeStore::create(canvas_interface_)),
626         //keyframe_tree_store_  (KeyframeTreeStore::create(canvas_interface_)),
627         time_adjustment_                (0,0,25,0,0,0),
628         time_window_adjustment_ (0,0,25,0,0,0),
629         statusbar                               (manage(new class Gtk::Statusbar())),
630
631         timeslider                              (new Widget_Timeslider),
632
633         ui_interface_                   (new CanvasViewUIInterface(this)),
634         selection_manager_              (new CanvasViewSelectionManager(this)),
635         is_playing_                             (false),
636
637         working_depth                   (0),
638         cancel                                  (false),
639
640         canvas_properties               (*this,canvas_interface_),
641         canvas_options                  (this),
642         render_settings                 (*this,canvas_interface_),
643         waypoint_dialog                 (*this,canvas_interface_->get_canvas()),
644         keyframe_dialog                 (*this,canvas_interface_),
645         preview_dialog                  (new Dialog_Preview),
646         sound_dialog                    (new Dialog_SoundSelect(*this,canvas_interface_))
647 {
648         layer_tree=0;
649         children_tree=0;
650         duck_refresh_flag=true;
651
652         smach_.set_default_state(&state_normal);
653
654         disp_audio = new Widget_Sound();
655
656         //synfig::info("Canvasview: Entered constructor");
657         // Minor hack
658         get_canvas()->set_time(0);
659         //layer_tree_store_->rebuild();
660
661         // Set up the UI and Selection managers
662         canvas_interface()->set_ui_interface(get_ui_interface());
663         canvas_interface()->set_selection_manager(get_selection_manager());
664         rebuild_ducks_queued=false;
665
666         //notebook=manage(new class Gtk::Notebook());
667         //Gtk::VPaned *vpaned = manage(new class Gtk::VPaned());
668         //vpaned->pack1(*create_work_area(), Gtk::EXPAND|Gtk::SHRINK);
669         //vpaned->pack2(*notebook, Gtk::SHRINK);
670         //vpaned->show_all();
671
672
673         //notebook->show();
674
675         //notebook->append_page(*create_layer_tree(),"Layers");
676         //notebook->append_page(*create_children_tree(),"Children");
677         //notebook->append_page(*create_keyframe_tree(),"Keyframes");
678
679         //synfig::info("Canvasview: Before big chunk of allocation and tabling stuff");
680         //create all allocated stuff for this canvas
681         audio = new AudioContainer();
682
683         Gtk::Table *layout_table= manage(new class Gtk::Table(1, 3, false));
684         //layout_table->attach(*vpaned, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
685         layout_table->attach(*create_work_area(), 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
686         init_menus();
687         //layout_table->attach(*App::ui_manager()->get_widget("/menu-main"), 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
688
689
690         layout_table->attach(*create_time_bar(), 0, 1, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
691         layout_table->attach(*create_status_bar(), 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
692
693         update_title();
694
695         layout_table->show();
696         add(*layout_table);
697
698         //set_transient_for(*App::toolbox);
699
700         //synfig::info("Canvasview: Before Signals");
701         /*
702  --     ** -- Signals -------------------------------------------------------------
703         */
704
705         canvas_interface()->signal_dirty_preview().connect(sigc::mem_fun(*this,&studio::CanvasView::on_dirty_preview));
706         canvas_interface()->signal_mode_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_mode_changed));
707
708         canvas_interface()->signal_time_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_time_changed));
709
710         //canvas_interface()->signal_time_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::refresh_tables));
711         canvas_interface()->signal_id_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_id_changed));
712         canvas_interface()->signal_rend_desc_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::refresh_rend_desc));
713         waypoint_dialog.signal_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_waypoint_changed));
714         waypoint_dialog.signal_delete().connect(sigc::mem_fun(*this,&studio::CanvasView::on_waypoint_delete));
715
716         //MODIFIED TIME ADJUSTMENT STUFF....
717         time_window_adjustment().set_child_adjustment(&time_adjustment());
718         time_window_adjustment().signal_value_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::refresh_time_window));
719         time_adjustment().signal_value_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::time_was_changed));
720
721
722         work_area->signal_layer_selected().connect(sigc::mem_fun(*this,&studio::CanvasView::workarea_layer_selected));
723         work_area->signal_input_device_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_input_device_changed));
724
725         canvas_interface()->signal_canvas_added().connect(
726                 sigc::hide(
727                         sigc::mem_fun(*instance,&studio::Instance::refresh_canvas_tree)
728                 )
729         );
730         canvas_interface()->signal_canvas_removed().connect(
731                 sigc::hide(
732                         sigc::mem_fun(*instance,&studio::Instance::refresh_canvas_tree)
733                 )
734         );
735
736         canvas_interface()->signal_layer_param_changed().connect(
737                 sigc::hide(
738                         sigc::hide(
739                                 SLOT_EVENT(EVENT_REFRESH_DUCKS)
740                         )
741                 )
742         );
743
744
745         //MUCH TIME STUFF TAKES PLACE IN HERE
746         refresh_rend_desc();
747         refresh_time_window();
748
749         /*! \todo We shouldn't need to do this at construction --
750         **      This should be preformed at the first time the window
751         **      becomes visible.
752         */
753         work_area->queue_render_preview();
754
755         // If the canvas is really big, zoom out so that we can fit it all in the window
756         /*! \todo In other words, this is a zoom-to-fit, and should be
757         ** in its own function.
758         */
759         int w=get_canvas()->rend_desc().get_w()+70;
760         int h=get_canvas()->rend_desc().get_h()+70;
761         while(w>700 || h>600)
762         {
763                 work_area->zoom_out();
764                 w=round_to_int(get_canvas()->rend_desc().get_w()*work_area->get_zoom()+70);
765                 h=round_to_int(get_canvas()->rend_desc().get_h()*work_area->get_zoom()+70);
766         }
767         if(w>700)w=700;
768         if(h>600)h=600;
769         set_default_size(w,h);
770         property_window_position().set_value(Gtk::WIN_POS_NONE);
771
772
773
774
775         std::list<Gtk::TargetEntry> listTargets;
776         listTargets.push_back( Gtk::TargetEntry("STRING") );
777         listTargets.push_back( Gtk::TargetEntry("text/plain") );
778         listTargets.push_back( Gtk::TargetEntry("image") );
779
780         drag_dest_set(listTargets);
781         signal_drag_data_received().connect( sigc::mem_fun(*this, &studio::CanvasView::on_drop_drag_data_received) );
782
783
784         /*
785         Time length(get_canvas()->rend_desc().get_time_end()-get_canvas()->rend_desc().get_time_start());
786         if(length<10.0)
787         {
788                 time_window_adjustment().set_page_increment(length);
789                 time_window_adjustment().set_page_size(length);
790         }
791         else
792         {
793                 time_window_adjustment().set_page_increment(10.0);
794                 time_window_adjustment().set_page_size(10.0);
795         }
796         */
797
798         //synfig::info("Canvasview: Before Sound Hookup");
799         //load sound info from meta data
800         {
801                 //synfig::warning("Should load Audio: %s with %s offset",apath.c_str(),aoffset.c_str());
802
803                 on_audio_file_notify(); //redundant setting of the metadata, but oh well, it's no big deal :)
804                 on_audio_offset_notify();
805
806                 //signal connection - since they are all associated with the canvas view
807
808                 //hook in signals for sound options box
809                 sound_dialog->signal_file_changed().connect(sigc::mem_fun(*this,&CanvasView::on_audio_file_change));
810                 sound_dialog->signal_offset_changed().connect(sigc::mem_fun(*this,&CanvasView::on_audio_offset_change));
811
812                 //attach to the preview when it's visible
813                 //preview_dialog->get_widget().signal_play().connect(sigc::mem_fun(*this,&CanvasView::play_audio));
814                 //preview_dialog->get_widget().signal_stop().connect(sigc::mem_fun(*this,&CanvasView::stop_audio));
815
816                 //hook to metadata signals
817                 get_canvas()->signal_meta_data_changed("audiofile").connect(sigc::mem_fun(*this,&CanvasView::on_audio_file_notify));
818                 get_canvas()->signal_meta_data_changed("audiooffset").connect(sigc::mem_fun(*this,&CanvasView::on_audio_offset_notify));
819
820                 //universal_scrubber=std::auto_ptr<UniversalScrubber>(new UniversalScrubber(this));
821         }
822
823         //synfig::info("Canvasview: Before Final time set up");
824         //MORE TIME STUFF
825         time_window_adjustment().set_value(get_canvas()->rend_desc().get_time_start());
826         time_window_adjustment().value_changed();
827
828
829         GRAB_HINT_DATA("canvas_view");
830         /*
831         {
832         set_skip_taskbar_hint(true);
833         set_skip_pager_hint(true);
834         set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
835         }
836         */
837
838         refresh_rend_desc();
839         hide_tables();
840
841         on_time_changed();
842         //synfig::info("Canvasview: Constructor Done");
843 }
844
845 CanvasView::~CanvasView()
846 {
847         signal_deleted()();
848
849         App::ui_manager()->remove_action_group(action_group);
850
851         // Shut down the smach
852         smach_.egress();
853         smach_.set_default_state(0);
854
855         // We want to ensure that the UI_Manager and
856         // the selection manager get destructed right now.
857         ui_interface_.reset();
858         selection_manager_.reset();
859
860         // Delete any external widgets
861         for(;!ext_widget_book_.empty();ext_widget_book_.erase(ext_widget_book_.begin()))
862         {
863                 if(ext_widget_book_.begin()->second)
864                         delete ext_widget_book_.begin()->second;
865         }
866
867         //delete preview
868         audio.reset();
869
870         hide();
871
872         synfig::info("CanvasView:~CanvasView(): Destructor Finished");
873 }
874
875
876
877 Gtk::Widget *
878 CanvasView::create_time_bar()
879 {
880         Gtk::Image *icon;
881
882         Gtk::HScrollbar *time_window_scroll = manage(new class Gtk::HScrollbar(time_window_adjustment()));
883         //Gtk::HScrollbar *time_scroll = manage(new class Gtk::HScrollbar(time_adjustment()));
884         //TIME BAR TEMPORARY POSITION
885         //Widget_Timeslider *time_scroll = manage(new Widget_Timeslider);
886         timeslider->show();
887         timeslider->set_time_adjustment(&time_adjustment());
888         timeslider->set_bounds_adjustment(&time_window_adjustment());
889         //layout_table->attach(*timeslider, 0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL);
890
891
892         tooltips.set_tip(*time_window_scroll,_("Moves the time window"));
893         tooltips.set_tip(*timeslider,_("Changes the current time"));
894         time_window_scroll->show();
895         timeslider->show();
896         time_window_scroll->set_flags(Gtk::CAN_FOCUS);
897         timeslider->set_flags(Gtk::CAN_FOCUS);
898
899         //time_scroll->signal_value_changed().connect(sigc::mem_fun(*work_area, &studio::WorkArea::render_preview_hook));
900         //time_scroll->set_update_policy(Gtk::UPDATE_DISCONTINUOUS);
901
902         NORMAL_BUTTON(animatebutton,"gtk-yes","Animate");
903         animatebutton->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_animate_button_pressed));
904         animatebutton->show();
905
906         NORMAL_BUTTON(keyframebutton,"synfig-keyframe_lock_all","All Keyframes Locked");
907         keyframebutton->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_button_pressed));
908         keyframebutton->show();
909
910         Gtk::Table *table= manage(new class Gtk::Table(2, 3, false));
911
912         //setup the audio display
913         disp_audio->set_size_request(-1,32); //disp_audio->show();
914         disp_audio->set_time_adjustment(&time_adjustment());
915         disp_audio->signal_start_scrubbing().connect(
916                 sigc::mem_fun(*audio,&AudioContainer::start_scrubbing)
917         );
918         disp_audio->signal_scrub().connect(
919                 sigc::mem_fun(*audio,&AudioContainer::scrub)
920         );
921         disp_audio->signal_stop_scrubbing().connect(
922                 sigc::mem_fun(*audio,&AudioContainer::stop_scrubbing)
923         );
924
925         table->attach(*manage(disp_audio), 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK);
926         table->attach(*timeslider, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0);
927         table->attach(*time_window_scroll, 0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0);
928
929         table->attach(*animatebutton, 1, 2, 0, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
930         table->attach(*keyframebutton, 2, 3, 0, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
931         timebar=table;
932         table->show();
933         return table;
934 }
935
936 Gtk::Widget *
937 CanvasView::create_work_area()
938 {
939         work_area=std::auto_ptr<WorkArea>(new class studio::WorkArea(canvas_interface_));
940         work_area->set_instance(get_instance());
941         work_area->set_canvas(get_canvas());
942         work_area->set_canvas_view(this);
943         work_area->set_progress_callback(get_ui_interface().get());
944         work_area->signal_popup_menu().connect(sigc::mem_fun(*this, &studio::CanvasView::popup_main_menu));
945         work_area->show();
946         return work_area.get();
947 }
948
949
950 Gtk::Widget*
951 CanvasView::create_status_bar()
952 {
953         Gtk::Image *icon;
954         Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon");
955         cancel=false;
956
957         // Create the status bar at the bottom of the window
958         Gtk::Table *statusbartable= manage(new class Gtk::Table(7, 1, false));
959 //      statusbar = manage(new class Gtk::Statusbar()); // This is already done at construction
960         progressbar =manage(new class Gtk::ProgressBar());
961         SMALL_BUTTON(stopbutton,"gtk-stop","Stop");
962         SMALL_BUTTON(refreshbutton,"gtk-refresh","Refresh");
963         //SMALL_BUTTON(treetogglebutton,"gtk-go-down","Toggle Layer Tree");
964 //      NEW_SMALL_BUTTON(raisebutton,"gtk-go-up","Raise Layer");
965 //      NEW_SMALL_BUTTON(lowerbutton,"gtk-go-down","Lower Layer");
966         //statusbartable->attach(*treetogglebutton, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
967 //      statusbartable->attach(*lowerbutton, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
968 //      statusbartable->attach(*raisebutton, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
969
970
971         current_time_widget=manage(new Widget_Time);
972         current_time_widget->set_value(get_time());
973         current_time_widget->set_fps(get_canvas()->rend_desc().get_frame_rate());
974         current_time_widget->signal_value_changed().connect(
975                 sigc::mem_fun(*this,&CanvasView::on_current_time_widget_changed)
976         );
977
978         statusbartable->attach(*current_time_widget, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
979         statusbartable->attach(*statusbar, 3, 4, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
980         statusbartable->attach(*progressbar, 4, 5, 0, 1, Gtk::SHRINK, Gtk::EXPAND|Gtk::FILL, 0, 0);
981         statusbartable->attach(*refreshbutton, 5, 6, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
982         statusbartable->attach(*stopbutton, 6, 7, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
983         statusbar->set_has_resize_grip(false);
984         statusbar->show();
985         stopbutton->show();
986         refreshbutton->show();
987         progressbar->show();
988         stopbutton->set_sensitive(false);
989
990         //refreshbutton->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_refresh_pressed));
991         //stopbutton->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::stop));
992         //treetogglebutton->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::toggle_tables));
993
994         refreshbutton->signal_clicked().connect(SLOT_EVENT(EVENT_REFRESH));
995         stopbutton->signal_clicked().connect(SLOT_EVENT(EVENT_STOP));
996
997
998         statusbartable->show_all();
999         return statusbartable;
1000 }
1001
1002 void
1003 CanvasView::on_current_time_widget_changed()
1004 {
1005         set_time(current_time_widget->get_value());
1006 }
1007
1008 Gtk::Widget*
1009 CanvasView::create_children_tree()
1010 {
1011         // Create the layer tree
1012         children_tree=manage(new class ChildrenTree());
1013
1014         // Set up the layer tree
1015         //children_tree->set_model(children_tree_store());
1016         if(children_tree)children_tree->set_time_adjustment(time_adjustment());
1017         if(children_tree)children_tree->show();
1018
1019         // Connect Signals
1020         if(children_tree)children_tree->signal_edited_value().connect(sigc::mem_fun(*this, &studio::CanvasView::on_edited_value));
1021         if(children_tree)children_tree->signal_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
1022         if(children_tree)children_tree->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked));
1023         if(children_tree)children_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
1024
1025         return children_tree;
1026 }
1027
1028 Gtk::Widget*
1029 CanvasView::create_keyframe_tree()
1030 {
1031         keyframe_tree=manage(new KeyframeTree());
1032
1033         //keyframe_tree->get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
1034         //keyframe_tree->show();
1035         //keyframe_tree->set_model(keyframe_tree_store());
1036         keyframe_tree->set_editable(true);
1037         //keyframe_tree->signal_edited().connect(sigc::hide_return(sigc::mem_fun(*canvas_interface(), &synfigapp::CanvasInterface::update_keyframe)));
1038
1039         keyframe_tree->signal_event().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_tree_event));
1040
1041         Gtk::ScrolledWindow *scroll_layer_tree = manage(new class Gtk::ScrolledWindow());
1042         scroll_layer_tree->set_flags(Gtk::CAN_FOCUS);
1043         scroll_layer_tree->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
1044         scroll_layer_tree->add(*keyframe_tree);
1045         scroll_layer_tree->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
1046         //scroll_layer_tree->show();
1047
1048
1049         Gtk::Table *layout_table= manage(new Gtk::Table(1, 2, false));
1050         layout_table->attach(*scroll_layer_tree, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1051
1052         Gtk::Image *icon;
1053         Gtk::IconSize iconsize(Gtk::IconSize::from_name("synfig-small_icon"));
1054
1055         NEW_SMALL_BUTTON(button_add,"gtk-add","New Keyframe");
1056         NEW_SMALL_BUTTON(button_duplicate,"synfig-duplicate","Duplicate Keyframe");
1057         NEW_SMALL_BUTTON(button_delete,"gtk-delete","Delete Keyframe");
1058
1059         Gtk::HBox *hbox(manage(new Gtk::HBox()));
1060         layout_table->attach(*hbox, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0);
1061
1062         hbox->pack_start(*button_add,Gtk::PACK_SHRINK);
1063         hbox->pack_start(*button_duplicate,Gtk::PACK_SHRINK);
1064         hbox->pack_start(*button_delete,Gtk::PACK_SHRINK);
1065
1066         /*
1067         button_raise->set_relief(Gtk::RELIEF_HALF);
1068         button_lower->set_relief(Gtk::RELIEF_HALF);
1069         button_duplicate->set_relief(Gtk::RELIEF_HALF);
1070         button_delete->set_relief(Gtk::RELIEF_HALF);
1071         */
1072
1073         button_add->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_add_pressed));
1074         button_duplicate->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_duplicate_pressed));
1075         button_delete->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_remove_pressed));
1076
1077         //layout_table->show_all();
1078
1079         keyframe_tab_child=layout_table;
1080
1081
1082         layout_table->hide();
1083
1084         return layout_table;
1085 }
1086
1087 Gtk::Widget*
1088 CanvasView::create_layer_tree()
1089 {
1090         // Create the layer tree
1091         layer_tree=manage(new class LayerTree());
1092
1093         // Set up the layer tree
1094         //layer_tree->set_model(layer_tree_store());
1095         layer_tree->set_time_adjustment(time_adjustment());
1096         layer_tree->show();
1097
1098         // Connect Signals
1099         layer_tree->signal_layer_toggle().connect(sigc::mem_fun(*this, &studio::CanvasView::on_layer_toggle));
1100         layer_tree->signal_edited_value().connect(sigc::mem_fun(*this, &studio::CanvasView::on_edited_value));
1101         layer_tree->signal_layer_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_layer_user_click));
1102         layer_tree->signal_param_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
1103         layer_tree->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked));
1104         layer_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
1105
1106         layer_tree->hide();
1107         return layer_tree;
1108 }
1109
1110 void
1111 CanvasView::init_menus()
1112 {
1113 /*
1114         mainmenu.set_accel_group(get_accel_group());
1115         mainmenu.set_accel_path("<Canvas-view>");
1116
1117         filemenu.set_accel_group(get_accel_group());
1118         filemenu.set_accel_path("<Canvas-view>/File");
1119
1120         editmenu.set_accel_group(get_accel_group());
1121         editmenu.set_accel_path("<Canvas-view>/Edit");
1122
1123         layermenu.set_accel_group(get_accel_group());
1124         layermenu.set_accel_path("<Canvas-view>/Layer");
1125 */
1126         //cache the position of desired widgets
1127
1128         /*Menus to worry about:
1129         - filemenu
1130         - editmenu
1131         - layermenu
1132         - duckmaskmenu
1133         - mainmenu
1134         - canvasmenu
1135         - viewmenu
1136         */
1137         action_group = Gtk::ActionGroup::create();
1138
1139         //action_group->add( Gtk::Action::create("MenuFile", "_File") );
1140         action_group->add( Gtk::Action::create("save", Gtk::Stock::SAVE),
1141                 hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::save))
1142         );
1143         action_group->add( Gtk::Action::create("save-as", Gtk::Stock::SAVE_AS),
1144                 sigc::hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::dialog_save_as))
1145         );
1146         action_group->add( Gtk::Action::create("revert", Gtk::Stock::REVERT_TO_SAVED),
1147                 sigc::hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::safe_revert))
1148         );
1149         action_group->add( Gtk::Action::create("cvs-add", Gtk::StockID("synfig-cvs_add")),
1150                 sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_add))
1151         );
1152         action_group->add( Gtk::Action::create("cvs-update", Gtk::StockID("synfig-cvs_update")),
1153                 sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_update))
1154         );
1155         action_group->add( Gtk::Action::create("cvs-revert", Gtk::StockID("synfig-cvs_revert")),
1156                 sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_revert))
1157         );
1158         action_group->add( Gtk::Action::create("cvs-commit", Gtk::StockID("synfig-cvs_commit")),
1159                 sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_commit))
1160         );
1161         action_group->add( Gtk::Action::create("import", _("Import")),
1162                 sigc::hide_return(sigc::mem_fun(*this, &studio::CanvasView::image_import))
1163         );
1164         action_group->add( Gtk::Action::create("render", _("Render")),
1165                 sigc::mem_fun0(render_settings,&studio::RenderSettings::present)
1166         );
1167         action_group->add( Gtk::Action::create("preview", _("Preview")),
1168                 sigc::mem_fun(*this,&CanvasView::on_preview_option)
1169         );
1170         action_group->add( Gtk::Action::create("sound", _("Sound File")),
1171                 sigc::mem_fun(*this,&CanvasView::on_audio_option)
1172         );
1173         action_group->add( Gtk::Action::create("options", _("Options")),
1174                 sigc::mem_fun0(canvas_options,&studio::CanvasOptions::present)
1175         );
1176         action_group->add( Gtk::Action::create("close", Gtk::StockID("gtk-close")),
1177                 sigc::hide_return(sigc::mem_fun(*this,&studio::CanvasView::close))
1178         );
1179
1180         //action_group->add( Gtk::Action::create("undo", Gtk::StockID("gtk-undo")),
1181         //      SLOT_EVENT(EVENT_UNDO)
1182         //);
1183
1184         //action_group->add( Gtk::Action::create("redo", Gtk::StockID("gtk-redo")),
1185         //      SLOT_EVENT(EVENT_REDO)
1186         //);
1187
1188         action_group->add( Gtk::Action::create("select-all-ducks", _("Select All Ducks")),
1189                 sigc::mem_fun(*work_area,&studio::WorkArea::select_all_ducks)
1190         );
1191
1192         action_group->add( Gtk::Action::create("unselect-all-layers", _("Unselect All Layers")),
1193                 sigc::mem_fun(*this,&CanvasView::on_unselect_layers)
1194         );
1195
1196         action_group->add( Gtk::Action::create("stop", Gtk::StockID("gtk-stop")),
1197                 SLOT_EVENT(EVENT_STOP)
1198         );
1199
1200         action_group->add( Gtk::Action::create("refresh", Gtk::StockID("gtk-refresh")),
1201                 SLOT_EVENT(EVENT_REFRESH)
1202         );
1203
1204         action_group->add( Gtk::Action::create("properties", Gtk::StockID("gtk-properties")),
1205                 sigc::mem_fun0(canvas_properties,&studio::CanvasProperties::present)
1206         );
1207
1208         // Preview Quality Menu
1209         {
1210                 int i;
1211                 action_group->add( Gtk::RadioAction::create(quality_group,"quality-00", _("Use Parametric Renderer")),
1212                         sigc::bind(
1213                                 sigc::mem_fun(*work_area, &studio::WorkArea::set_quality),
1214                                 0
1215                         )
1216                 );
1217                 for(i=1;i<=10;i++)
1218                 {
1219                         Glib::RefPtr<Gtk::RadioAction> action(Gtk::RadioAction::create(quality_group,strprintf("quality-%02d",i), strprintf("Set Quality to %d",i)));
1220                         if(i==10)
1221                                 action->property_value()=10;
1222                         action_group->add( action,
1223                                 sigc::bind(
1224                                         sigc::mem_fun(*work_area, &studio::WorkArea::set_quality),
1225                                         i
1226                                 )
1227                         );
1228                 }
1229         }
1230
1231         action_group->add( Gtk::Action::create("play", Gtk::StockID("synfig-play")),
1232                 sigc::mem_fun(*this, &studio::CanvasView::play)
1233         );
1234
1235         action_group->add( Gtk::Action::create("dialog-flipbook", _("Flipbook Dialog")),
1236                 sigc::mem_fun0(*preview_dialog, &studio::Dialog_Preview::present)
1237         );
1238
1239         action_group->add( Gtk::Action::create("toggle-grid-show", _("Toggle Grid Show")),
1240                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_grid)
1241         );
1242         action_group->add( Gtk::Action::create("toggle-grid-snap", _("Toggle Grid Snap")),
1243                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_grid_snap)
1244         );
1245         action_group->add( Gtk::Action::create("toggle-guide-show", _("Toggle Guide Show")),
1246                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_guide_snap)
1247         );
1248         action_group->add( Gtk::Action::create("toggle-low-res", _("Toggle Low-Res")),
1249                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_low_resolution_flag)
1250         );
1251         action_group->add( Gtk::Action::create("toggle-onion-skin", _("Toggle Onion Skin")),
1252                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_onion_skin)
1253         );
1254
1255
1256         action_group->add( Gtk::Action::create("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit")),
1257                 sigc::mem_fun(*work_area, &studio::WorkArea::zoom_fit)
1258         );
1259         action_group->add( Gtk::Action::create("canvas-zoom-100", Gtk::StockID("gtk-zoom-100")),
1260                 sigc::mem_fun(*work_area, &studio::WorkArea::zoom_norm)
1261         );
1262
1263
1264         {
1265                 Glib::RefPtr<Gtk::Action> action;
1266
1267                 action=Gtk::Action::create("seek-next-frame", Gtk::Stock::GO_FORWARD,_("Next Frame"),_("Next Frame"));
1268                 action_group->add(action,sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_frame),1));
1269                 action=Gtk::Action::create("seek-prev-frame", Gtk::Stock::GO_BACK,_("Prev Frame"),_("Prev Frame"));
1270                 action_group->add( action, sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_frame),-1));
1271
1272                 action=Gtk::Action::create("seek-next-second", Gtk::Stock::GO_FORWARD,_("Seek Forward"),_("Seek Forward"));
1273                 action_group->add(action,sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time),Time(1)));
1274                 action=Gtk::Action::create("seek-prev-second", Gtk::Stock::GO_BACK,_("Seek Backward"),_("Seek Backward"));
1275                 action_group->add( action, sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time),Time(-1)));
1276
1277                 action=Gtk::Action::create("seek-end", Gtk::Stock::GOTO_LAST,_("Seek to End"),_("Seek to End"));
1278                 action_group->add(action,sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time),Time::end()));
1279
1280                 action=Gtk::Action::create("seek-begin", Gtk::Stock::GOTO_FIRST,_("Seek to Begin"),_("Seek to Begin"));
1281                 action_group->add( action, sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time),Time::begin()));
1282
1283                 action=Gtk::Action::create("jump-next-keyframe", Gtk::Stock::GO_FORWARD,_("Jump to Next Keyframe"),_("Jump to Next Keyframe"));
1284                 action_group->add( action,sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_next_keyframe));
1285
1286                 action=Gtk::Action::create("jump-prev-keyframe", Gtk::Stock::GO_BACK,_("Jump to Prev Keyframe"),_("Jump to Prev Keyframe"));
1287                 action_group->add( action,sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_prev_keyframe));
1288
1289                 action=Gtk::Action::create("canvas-zoom-in", Gtk::Stock::ZOOM_IN);
1290                 action_group->add( action,sigc::mem_fun(*work_area, &studio::WorkArea::zoom_in));
1291
1292                 action=Gtk::Action::create("canvas-zoom-out", Gtk::Stock::ZOOM_OUT);
1293                 action_group->add( action, sigc::mem_fun(*work_area, &studio::WorkArea::zoom_out) );
1294
1295                 action=Gtk::Action::create("time-zoom-in", Gtk::Stock::ZOOM_IN, _("Zoom In on Timeline"));
1296                 action_group->add( action, sigc::mem_fun(*this, &studio::CanvasView::time_zoom_in) );
1297
1298                 action=Gtk::Action::create("time-zoom-out", Gtk::Stock::ZOOM_OUT, _("Zoom Out on Timeline"));
1299                 action_group->add( action, sigc::mem_fun(*this, &studio::CanvasView::time_zoom_out) );
1300
1301         }
1302
1303
1304 #define DUCK_MASK(lower,upper)  \
1305         duck_mask_##lower=Gtk::ToggleAction::create("mask-" #lower "-ducks", _("Show "#lower" ducks")); \
1306         duck_mask_##lower->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_##upper)); \
1307         action_group->add( duck_mask_##lower, \
1308                 sigc::bind( \
1309                         sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask), \
1310                         Duck::TYPE_##upper \
1311                 ) \
1312         )
1313         DUCK_MASK(position,POSITION);
1314         DUCK_MASK(tangent,TANGENT);
1315         DUCK_MASK(vertex,VERTEX);
1316         DUCK_MASK(radius,RADIUS);
1317         DUCK_MASK(width,WIDTH);
1318         DUCK_MASK(angle,ANGLE);
1319 #undef DUCK_MASK
1320
1321         add_accel_group(App::ui_manager()->get_accel_group());
1322
1323 /*      // Here is where we add the actions that may have conflicting
1324         // keyboard accelerators.
1325         {
1326                 Glib::RefPtr<Gtk::ActionGroup> accel_action_group(Gtk::ActionGroup::create("canvas_view"));
1327                 Glib::RefPtr<Gtk::Action> action;
1328
1329                 action=Gtk::Action::create("seek-next-frame", Gtk::StockID("gtk-forward"),_("Next Frame"),_("Next Frame"));
1330                 accel_action_group->add(action,sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek),1));
1331
1332                 action=Gtk::Action::create("seek-prev-frame", Gtk::StockID("gtk-forward"),_("Prev Frame"),_("Prev Frame"));
1333                 accel_action_group->add( action, sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek),-1));
1334
1335                 action=Gtk::Action::create("jump-next-keyframe", Gtk::StockID("gtk-forward"),_("Jump to Next Keyframe"),_("Jump to Next Keyframe"));
1336                 accel_action_group->add( action,sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_next_keyframe));
1337
1338                 action=Gtk::Action::create("jump-prev-keyframe", Gtk::StockID("gtk-back"),_("Jump to Prev Keyframe"),_("Jump to Prev Keyframe"));
1339                 accel_action_group->add( action,sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_prev_keyframe));
1340
1341                 action=Gtk::Action::create("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
1342                 accel_action_group->add( action,sigc::mem_fun(*work_area, &studio::WorkArea::zoom_in));
1343
1344                 action=Gtk::Action::create("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
1345                 accel_action_group->add( action, sigc::mem_fun(*work_area, &studio::WorkArea::zoom_out) );
1346
1347                 action=Gtk::Action::create("time-zoom-in", Gtk::StockID("gtk-zoom-in"), _("Zoom In on Timeline"));
1348                 accel_action_group->add( action, sigc::mem_fun(*this, &studio::CanvasView::time_zoom_in) );
1349
1350                 action=Gtk::Action::create("time-zoom-out", Gtk::StockID("gtk-zoom-out"), _("Zoom Out on Timeline"));
1351                 accel_action_group->add( action, sigc::mem_fun(*this, &studio::CanvasView::time_zoom_out) );
1352
1353                 Glib::RefPtr<Gtk::UIManager> accel_ui_manager(Gtk::UIManager::create());
1354
1355                 Glib::ustring ui_info =
1356                 "
1357                 <ui>
1358                         <accelerator action='seek-next-frame' />
1359                         <accelerator action='seek-prev-frame' />
1360                         <accelerator action='jump-next-keyframe' />
1361                         <accelerator action='jump-prev-keyframe' />
1362                         <accelerator action='canvas-zoom-in' />
1363                         <accelerator action='canvas-zoom-out' />
1364                         <accelerator action='time-zoom-in' />
1365                         <accelerator action='time-zoom-out' />
1366                 </ui>
1367                 ";
1368
1369                 accel_ui_manager->add_ui_from_string(ui_info);
1370                 add_accel_group(accel_ui_manager->get_accel_group());
1371
1372                 accel_ui_manager->insert_action_group(accel_action_group);
1373                 set_ref_obj("accel_ui_manager",accel_ui_manager);
1374                 set_ref_obj("accel_action_group",accel_action_group);
1375         }
1376 */
1377
1378
1379
1380 #if 0
1381
1382         //Test some key stuff
1383
1384         filemenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-save"),
1385                 hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::save))));
1386         filemenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-save-as"),sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_save_as))));
1387         filemenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-revert-to-saved"),hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::safe_revert))));
1388         filemenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1389
1390         filemenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("synfig-cvs_add"),sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_add))));
1391         filemenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("synfig-cvs_update"),sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_update))));
1392         filemenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("synfig-cvs_commit"),sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_commit))));
1393
1394         filemenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1395         filemenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Import..."),Gtk::AccelKey('I',Gdk::CONTROL_MASK),sigc::hide_return(sigc::mem_fun(*this, &studio::CanvasView::image_import))));
1396         filemenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1397         filemenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Render"),Gtk::AccelKey("F9"),
1398                 sigc::mem_fun(render_settings,&studio::RenderSettings::present)
1399         ));
1400         filemenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Preview"),Gtk::AccelKey("F11"),
1401                 sigc::mem_fun(*this,&CanvasView::on_preview_option)
1402         ));
1403         filemenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Sound File"),
1404                 sigc::mem_fun(*this,&CanvasView::on_audio_option)
1405         ));
1406
1407         filemenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1408         filemenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Options"),Gtk::AccelKey("F12"),
1409                 sigc::mem_fun(canvas_options,&studio::CanvasOptions::present)
1410         ));
1411         filemenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1412         filemenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-close"),sigc::hide_return(sigc::mem_fun(*this,&studio::CanvasView::close))));
1413
1414         editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-undo"),Gtk::AccelKey('Z',Gdk::CONTROL_MASK),SLOT_EVENT(EVENT_UNDO)));
1415         editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-redo"),Gtk::AccelKey('R',Gdk::CONTROL_MASK),SLOT_EVENT(EVENT_REDO)));
1416         editmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1417         editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-cut"),NOT_IMPLEMENTED_SLOT));
1418         editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-copy"),NOT_IMPLEMENTED_SLOT));
1419         editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-paste"),NOT_IMPLEMENTED_SLOT));
1420         editmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1421         editmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Select All Ducks"),Gtk::AccelKey('E',Gdk::CONTROL_MASK),sigc::mem_fun(*work_area,&studio::WorkArea::select_all_ducks)));
1422         editmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Unselect All Layers"),Gtk::AccelKey('D',Gdk::CONTROL_MASK),sigc::mem_fun(*this,&CanvasView::on_unselect_layers)));
1423         editmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1424
1425         //editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-stop"),Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0)),sigc::hide_return(sigc::mem_fun(*this, &studio::CanvasView::stop))));
1426         //editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-refresh"),Gtk::AccelKey('k',Gdk::CONTROL_MASK),sigc::hide_return(sigc::mem_fun(*this, &studio::CanvasView::on_refresh_pressed))));
1427         editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-stop"),Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0)),SLOT_EVENT(EVENT_STOP)));
1428         editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-refresh"),Gtk::AccelKey('k',Gdk::CONTROL_MASK),SLOT_EVENT(EVENT_REFRESH)));
1429         editmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1430         editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-properties"),Gtk::AccelKey("F8"),
1431                 sigc::mem_fun(canvas_properties,&studio::CanvasProperties::present)
1432         ));
1433
1434         build_new_layer_menu(newlayermenu);
1435         layermenu.items().push_back(Gtk::Menu_Helpers::MenuElem("New",newlayermenu));
1436
1437
1438         {
1439                 synfigapp::Action::ParamList param_list;
1440                 param_list.add("canvas",Canvas::Handle(get_canvas()));
1441                 param_list.add("canvas_interface",canvas_interface());
1442                 add_actions_to_menu(&canvasmenu, param_list,synfigapp::Action::CATEGORY_CANVAS);
1443         }
1444
1445
1446         //canvasmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("Keyframe Dialog",sigc::mem_fun(keyframe_dialog,&studio::Dialog_Keyframe::present)));
1447
1448         // Duck Mask Menu
1449         if(1)
1450                 {
1451                 duckmaskmenu.items().push_back(Gtk::Menu_Helpers::TearoffMenuElem());
1452
1453                 duckmaskmenu.items().push_back(Gtk::Menu_Helpers::CheckMenuElem(_("Position Ducks"),Gtk::AccelKey('1',Gdk::MOD1_MASK)));
1454                 duck_mask_position=static_cast<Gtk::CheckMenuItem*>(&duckmaskmenu.items().back());
1455                 duck_mask_position->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_POSITION));
1456                 duck_mask_position->signal_toggled().connect(
1457                         sigc::bind(
1458                                 sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),
1459                                 Duck::TYPE_POSITION
1460                         )
1461                 );
1462
1463                 duckmaskmenu.items().push_back(Gtk::Menu_Helpers::CheckMenuElem(_("Vertex Ducks"),Gtk::AccelKey('2',Gdk::MOD1_MASK)));
1464                 duck_mask_vertex=static_cast<Gtk::CheckMenuItem*>(&duckmaskmenu.items().back());
1465                 duck_mask_vertex->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_VERTEX));
1466                 duck_mask_vertex->signal_toggled().connect(
1467                         sigc::bind(
1468                                 sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),
1469                                 Duck::TYPE_VERTEX
1470                         )
1471                 );
1472
1473                 duckmaskmenu.items().push_back(Gtk::Menu_Helpers::CheckMenuElem(_("Tangent Ducks"),Gtk::AccelKey('3',Gdk::MOD1_MASK)));
1474                 duck_mask_tangent=static_cast<Gtk::CheckMenuItem*>(&duckmaskmenu.items().back());
1475                 duck_mask_tangent->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_TANGENT));
1476                 duck_mask_tangent->signal_toggled().connect(
1477                         sigc::bind(
1478                                 sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),
1479                                 Duck::TYPE_TANGENT
1480                         )
1481                 );
1482
1483                 duckmaskmenu.items().push_back(Gtk::Menu_Helpers::CheckMenuElem(_("Radius Ducks"),Gtk::AccelKey('4',Gdk::MOD1_MASK)));
1484                 duck_mask_radius=static_cast<Gtk::CheckMenuItem*>(&duckmaskmenu.items().back());
1485                 duck_mask_radius->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_RADIUS));
1486                 duck_mask_radius->signal_toggled().connect(
1487                         sigc::bind(
1488                                 sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),
1489                                 Duck::TYPE_RADIUS
1490                         )
1491                 );
1492
1493                 duckmaskmenu.items().push_back(Gtk::Menu_Helpers::CheckMenuElem(_("Width Ducks"),Gtk::AccelKey('5',Gdk::MOD1_MASK)));
1494                 duck_mask_width=static_cast<Gtk::CheckMenuItem*>(&duckmaskmenu.items().back());
1495                 duck_mask_width->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_WIDTH));
1496                 duck_mask_width->signal_toggled().connect(
1497                         sigc::bind(
1498                                 sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),
1499                                 Duck::TYPE_WIDTH
1500                         )
1501                 );
1502
1503                 duckmaskmenu.items().push_back(Gtk::Menu_Helpers::CheckMenuElem(_("Angle Ducks"),Gtk::AccelKey('6',Gdk::MOD1_MASK)));
1504                 duck_mask_angle=static_cast<Gtk::CheckMenuItem*>(&duckmaskmenu.items().back());
1505                 duck_mask_angle->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_ANGLE));
1506                 duck_mask_angle->signal_toggled().connect(
1507                         sigc::bind(
1508                                 sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),
1509                                 Duck::TYPE_ANGLE
1510                         )
1511                 );
1512
1513                 viewmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Mask Ducks"),duckmaskmenu));
1514         }
1515
1516         // Preview Quality Menu
1517         if(1)
1518         {
1519                 qualitymenu.items().push_back(Gtk::Menu_Helpers::TearoffMenuElem());
1520                 int i;
1521                 qualitymenu.items().push_back(Gtk::Menu_Helpers::MenuElem(strprintf(_("Use Parametric Renderer"),0),
1522                         sigc::bind(
1523                                 sigc::mem_fun(*work_area, &studio::WorkArea::set_quality),
1524                                 0
1525                         )
1526                 ));
1527                 for(i=1;i<=10;i++)
1528                 {
1529                         qualitymenu.items().push_back(Gtk::Menu_Helpers::MenuElem(strprintf(_("Set Quality to %d"),i),Gtk::AccelKey('0'+(i%10),Gdk::CONTROL_MASK),
1530                                 sigc::bind(
1531                                         sigc::mem_fun(*work_area, &studio::WorkArea::set_quality),
1532                                         i
1533                                 )
1534                         ));
1535                 }
1536                 viewmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Preview Quality"),qualitymenu));
1537         }
1538
1539         viewmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("synfig-play"),
1540                 sigc::mem_fun(*this, &studio::CanvasView::play)));
1541         viewmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("Flipbook Dialog"),
1542                 sigc::mem_fun(*preview_dialog, &studio::Dialog_Preview::present)));
1543
1544         viewmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1545
1546         viewmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Toggle Grid Show"),Gtk::AccelKey('g',Gdk::CONTROL_MASK),
1547                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_grid)));
1548         viewmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Toggle Grid Snap"),Gtk::AccelKey('l',Gdk::CONTROL_MASK),
1549                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_grid_snap)));
1550         viewmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Toggle Guide Snap"),Gtk::AccelKey('k',Gdk::CONTROL_MASK),
1551                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_guide_snap)));
1552         viewmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Toggle Low-Res"),Gtk::AccelKey('`',Gdk::CONTROL_MASK),
1553                 sigc::mem_fun(*work_area, &studio::WorkArea::toggle_low_resolution_flag)));
1554
1555         viewmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1556
1557         viewmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-zoom-in"),Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0)),
1558                 sigc::mem_fun(*work_area, &studio::WorkArea::zoom_in)));
1559         viewmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-zoom-out"),Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0)),
1560                 sigc::mem_fun(*work_area, &studio::WorkArea::zoom_out)));
1561         viewmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-zoom-fit"),
1562                 sigc::mem_fun(*work_area, &studio::WorkArea::zoom_fit)));
1563         viewmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-zoom-100"),Gtk::AccelKey('`',static_cast<Gdk::ModifierType>(0)),
1564                 sigc::mem_fun(*work_area, &studio::WorkArea::zoom_norm)));
1565         viewmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1566
1567         viewmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-zoom-in"),Gtk::AccelKey('+',static_cast<Gdk::ModifierType>(0)),
1568                 sigc::mem_fun(*this, &studio::CanvasView::time_zoom_in)));
1569         viewmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-zoom-out"),Gtk::AccelKey('_',static_cast<Gdk::ModifierType>(0)),
1570                 sigc::mem_fun(*this, &studio::CanvasView::time_zoom_out)));
1571
1572         viewmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Jump to Next Keyframe"),Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0)),
1573                 sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_next_keyframe)));
1574         viewmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Jump to Prev Keyframe"),Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0)),
1575                 sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_prev_keyframe)));
1576
1577         mainmenu.items().push_back(Gtk::Menu_Helpers::TearoffMenuElem());
1578         mainmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("_File",filemenu));
1579         mainmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("_Edit",editmenu));
1580         mainmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("_View",viewmenu));
1581         mainmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("_Canvas",canvasmenu));
1582         mainmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("_Layer",layermenu));
1583
1584         mainmenu.accelerate(*this);
1585
1586         {
1587
1588                 trackmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("New Waypoint",NOT_IMPLEMENTED_SLOT));
1589                 trackmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("Delete Waypoint",NOT_IMPLEMENTED_SLOT));
1590                 trackmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("Export",NOT_IMPLEMENTED_SLOT));
1591                 trackmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem());
1592                 trackmenu.items().push_back(Gtk::Menu_Helpers::MenuElem("Properties",NOT_IMPLEMENTED_SLOT));
1593         }
1594         mainmenu.show();
1595         filemenu.show();
1596         editmenu.show();
1597         canvasmenu.show();
1598         layermenu.show();
1599
1600         keyframemenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-properties"),
1601                 sigc::mem_fun(*this,&studio::CanvasView::show_keyframe_dialog)
1602         ));
1603
1604
1605         get_accel_group()->unlock();
1606
1607         //Set the accelerator paths for all the menus
1608         filemenu.set_accel_path("<synfig>/File");
1609         editmenu.set_accel_path("<synfig>/Edit");
1610         layermenu.set_accel_path("<synfig>/Layer");
1611         //mainmenu.set_accel_path("<synfig-main>");
1612         canvasmenu.set_accel_path("<synfig>/Canvas");
1613         viewmenu.set_accel_path("<synfig>/View");
1614         duckmaskmenu.set_accel_path("<synfig>/DuckMask");
1615 #endif
1616 }
1617
1618 void
1619 CanvasView::on_unselect_layers()
1620 {
1621         layer_tree->clear_selected_layers();
1622 }
1623
1624 void
1625 CanvasView::show_keyframe_dialog()
1626 {
1627         Glib::RefPtr<Gtk::TreeSelection> selection(keyframe_tree->get_selection());
1628         if(selection->get_selected())
1629         {
1630                 Gtk::TreeRow row(*selection->get_selected());
1631
1632                 Keyframe keyframe(row[keyframe_tree->model.keyframe]);
1633
1634                 keyframe_dialog.set_keyframe(keyframe);
1635                 keyframe_dialog.present();
1636         }
1637 }
1638
1639 void
1640 CanvasView::add_layer(synfig::String x)
1641 {
1642         Canvas::Handle canvas;
1643
1644         synfigapp::SelectionManager::LayerList layer_list(get_selection_manager()->get_selected_layers());
1645
1646         int target_depth(0);
1647
1648         if(layer_list.empty())
1649         {
1650                 canvas=get_canvas();
1651         }
1652         else
1653         {
1654                 canvas=(*layer_list.begin())->get_canvas();
1655                 target_depth=canvas->get_depth(*layer_list.begin());
1656         }
1657
1658
1659         Layer::Handle layer(canvas_interface()->add_layer_to(x,canvas,target_depth));
1660         if(layer)
1661         {
1662                 get_selection_manager()->clear_selected_layers();
1663                 get_selection_manager()->set_selected_layer(layer);
1664         }
1665 }
1666
1667 void
1668 CanvasView::popup_layer_menu(synfig::Layer::Handle layer)
1669 {
1670         //Gtk::Menu* menu(manage(new Gtk::Menu));
1671         Gtk::Menu* menu(&parammenu);
1672         menu->items().clear();
1673
1674         synfigapp::Action::ParamList param_list;
1675         param_list.add("time",canvas_interface()->get_time());
1676         param_list.add("canvas",Canvas::Handle(layer->get_canvas()));
1677         param_list.add("canvas_interface",canvas_interface());
1678         param_list.add("layer",layer);
1679
1680         //Gtk::Menu *newlayers(manage(new Gtk::Menu()));
1681         //build_new_layer_menu(*newlayers);
1682
1683         //parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("New Layer"),*newlayers));
1684
1685         if(layer->get_name()=="paste_canvas")
1686         {
1687                 menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Select All Children"),
1688                         sigc::bind(
1689                                 sigc::mem_fun(
1690                                         *layer_tree,
1691                                         &studio::LayerTree::select_all_children_layers
1692                                 ),
1693                                 layer
1694                         )
1695                 ));
1696         }
1697
1698         add_actions_to_menu(menu, param_list,synfigapp::Action::CATEGORY_LAYER);
1699
1700         menu->popup(3,gtk_get_current_event_time());
1701 }
1702
1703 void
1704 CanvasView::register_layer_type(synfig::Layer::Book::value_type &lyr,std::map<synfig::String,Gtk::Menu*>* category_map)
1705 {
1706 /*      if(lyr.second.category==_("Do Not Use"))
1707                 return;
1708
1709         if(category_map->count(lyr.second.category)==0)
1710                 (*category_map)[lyr.second.category]=manage(new Gtk::Menu());
1711
1712         (*category_map)[lyr.second.category]->items().push_back(Gtk::Menu_Helpers::MenuElem(lyr.second.local_name,
1713                 sigc::hide_return(
1714                         sigc::bind(
1715                                 sigc::mem_fun(*this,&studio::CanvasView::add_layer),
1716                                 lyr.first
1717                         )
1718                 )
1719         ));
1720 */
1721 }
1722
1723 void
1724 CanvasView::build_new_layer_menu(Gtk::Menu &menu)
1725 {
1726 /*
1727         std::map<synfig::String,Gtk::Menu*> category_map;
1728
1729         std::for_each(
1730                 synfig::Layer::book().begin(),
1731                 synfig::Layer::book().end(),
1732                 sigc::bind(
1733                         sigc::mem_fun(
1734                                 *this,
1735                                 &studio::CanvasView::register_layer_type
1736                         ),
1737                         &category_map
1738                 )
1739         );
1740
1741         menu.items().clear();
1742         menu.items().push_back(Gtk::Menu_Helpers::TearoffMenuElem());
1743
1744         std::map<synfig::String,Gtk::Menu*>::iterator iter;
1745         for(iter=category_map.begin();iter!=category_map.end();++iter)
1746                 menu.items().push_back(Gtk::Menu_Helpers::MenuElem(iter->first,*iter->second));
1747
1748         menu.show();
1749 */
1750 }
1751
1752 void
1753 CanvasView::popup_main_menu()
1754 {
1755         //mainmenu.popup(0,gtk_get_current_event_time());
1756         Gtk::Menu* menu = dynamic_cast<Gtk::Menu*>(App::ui_manager()->get_widget("/menu-main"));
1757         if(menu)
1758         {
1759                 //menu->set_accel_group(App::ui_manager()->get_accel_group());
1760                 //menu->accelerate(*this);
1761                 menu->popup(0,gtk_get_current_event_time());
1762         }
1763 }
1764
1765 void
1766 CanvasView::on_refresh_pressed()
1767 {
1768         rebuild_tables();
1769         rebuild_ducks();
1770         work_area->queue_render_preview();
1771 }
1772
1773 void
1774 CanvasView::workarea_layer_selected(synfig::Layer::Handle layer)
1775 {
1776         get_selection_manager()->clear_selected_layers();
1777         if(layer)
1778                 get_selection_manager()->set_selected_layer(layer);
1779 }
1780
1781
1782 void
1783 CanvasView::refresh_rend_desc()
1784 {
1785         current_time_widget->set_fps(get_canvas()->rend_desc().get_frame_rate());
1786
1787
1788         //????
1789         //synfig::info("Canvasview: Refreshing render desc info");
1790         if(!get_time().is_equal(time_adjustment().get_value()))
1791         {
1792                 time_adjustment().set_value(get_time());
1793                 time_adjustment().value_changed();
1794         }
1795
1796         Time length(get_canvas()->rend_desc().get_time_end()-get_canvas()->rend_desc().get_time_start());
1797         if(length<DEFAULT_TIME_WINDOW_SIZE)
1798         {
1799                 time_window_adjustment().set_page_increment(length);
1800                 time_window_adjustment().set_page_size(length);
1801         }
1802         else
1803         {
1804                 time_window_adjustment().set_page_increment(DEFAULT_TIME_WINDOW_SIZE);
1805                 time_window_adjustment().set_page_size(DEFAULT_TIME_WINDOW_SIZE);
1806         }
1807
1808         //set the FPS of the timeslider
1809         timeslider->set_global_fps(get_canvas()->rend_desc().get_frame_rate());
1810
1811         //set the beginning and ending time of the time slider
1812         Time begin_time=get_canvas()->rend_desc().get_time_start();
1813         Time end_time=get_canvas()->rend_desc().get_time_end();
1814
1815         // Setup the time_window adjustment
1816         time_window_adjustment().set_lower(begin_time);
1817         time_window_adjustment().set_upper(end_time);
1818         time_window_adjustment().set_step_increment(synfig::Time(1.0/get_canvas()->rend_desc().get_frame_rate()));
1819
1820         //Time length(get_canvas()->rend_desc().get_time_end()-get_canvas()->rend_desc().get_time_start());
1821         if(length < time_window_adjustment().get_page_size())
1822         {
1823                 time_window_adjustment().set_page_increment(length);
1824                 time_window_adjustment().set_page_size(length);
1825         }
1826
1827         /*synfig::info("w: %p - [%.3f,%.3f] (%.3f,%.3f) child: %p\n",
1828                                 &time_window_adjustment_, time_window_adjustment_.get_lower(),
1829                                 time_window_adjustment_.get_upper(),time_window_adjustment_.get_value(),
1830                                 time_window_adjustment_.get_page_size(),time_window_adjustment_.get_child_adjustment()
1831         );*/
1832
1833         time_window_adjustment().changed(); //only non-value stuff was changed
1834
1835         // Setup the time adjustment
1836
1837         //NOTE THESE TWO SHOULD BE CHANGED BY THE changed() CALL ABOVE
1838         //time_adjustment().set_lower(time_window_adjustment().get_value());
1839         //time_adjustment().set_upper(time_window_adjustment().get_value()+time_window_adjustment().get_page_size());
1840
1841 //      time_adjustment().set_lower(get_canvas()->rend_desc().get_time_start());
1842 //      time_adjustment().set_upper(get_canvas()->rend_desc().get_time_end());
1843         time_adjustment().set_step_increment(synfig::Time(1.0/get_canvas()->rend_desc().get_frame_rate()));
1844         time_adjustment().set_page_increment(synfig::Time(1.0));
1845         time_adjustment().set_page_size(0);
1846
1847         time_adjustment().changed();
1848
1849         /*synfig::info("w: %p - [%.3f,%.3f] (%.3f,%.3f) child: %p\n",
1850                                 &time_window_adjustment_, time_window_adjustment_.get_lower(),
1851                                 time_window_adjustment_.get_upper(),time_window_adjustment_.get_value(),
1852                                 time_window_adjustment_.get_page_size(),time_window_adjustment_.get_child_adjustment()
1853         );      */
1854
1855         if(begin_time==end_time)
1856         {
1857                 hide_timebar();
1858         }
1859         else
1860         {
1861                 show_timebar();
1862         }
1863
1864         //clamp time to big bounds...
1865         if(time_adjustment().get_value() < begin_time)
1866         {
1867                 time_adjustment().set_value(begin_time);
1868                 time_adjustment().value_changed();
1869         }
1870
1871         if(time_adjustment().get_value() > end_time)
1872         {
1873                 time_adjustment().set_value(end_time);
1874                 time_adjustment().value_changed();
1875         }
1876
1877         /*synfig::info("Time stats: \n"
1878                                 "w: %p - [%.3f,%.3f] (%.3f,%.3f) child: %p\n"
1879                                 "t: %p - [%.3f,%.3f] %.3f",
1880                                 &time_window_adjustment_, time_window_adjustment_.get_lower(),
1881                                 time_window_adjustment_.get_upper(),time_window_adjustment_.get_value(),
1882                                 time_window_adjustment_.get_page_size(),time_window_adjustment_.get_child_adjustment(),
1883                                 &time_adjustment_,time_adjustment_.get_lower(),time_adjustment_.get_upper(),
1884                                 time_adjustment_.get_value()
1885         );*/
1886
1887         work_area->queue_render_preview();
1888 }
1889
1890
1891 bool
1892 CanvasView::close()
1893 {
1894         get_instance()->safe_close();
1895         return false;
1896 }
1897
1898 handle<CanvasView>
1899 CanvasView::create(loose_handle<Instance> instance,handle<Canvas> canvas)
1900 {
1901         etl::handle<studio::CanvasView> view(new CanvasView(instance,instance->synfigapp::Instance::find_canvas_interface(canvas)));
1902         instance->canvas_view_list().push_front(view);
1903         instance->signal_canvas_view_created()(view.get());
1904         return view;
1905 }
1906
1907 void
1908 CanvasView::update_title()
1909 {
1910         string title;
1911
1912         title+=etl::basename(get_instance()->get_file_name())
1913                 +" : ";
1914         if(get_canvas()->get_name().empty())
1915                 title+='"'+get_canvas()->get_id()+'"';
1916         else
1917                 title+='"'+get_canvas()->get_name()+'"';
1918
1919         if(get_instance()->synfigapp::Instance::get_action_count())
1920                 title+=_(" (Unsaved)");
1921
1922         if(get_instance()->synfigapp::Instance::in_repository())
1923         {
1924                 title+=" (CVS";
1925                 if(get_instance()->synfigapp::Instance::is_modified())
1926                         title+=_("-MODIFIED");
1927                 if(get_instance()->synfigapp::Instance::is_updated())
1928                         title+=_("-UPDATED");
1929                 title+=')';
1930         }
1931
1932         if(get_canvas()->is_root())
1933                 title+=_(" (Root)");
1934
1935         set_title(title);
1936 }
1937
1938
1939 void
1940 CanvasView::on_hide()
1941 {
1942         smach_.egress();
1943         Gtk::Window::on_hide();
1944 }
1945
1946 void
1947 CanvasView::present()
1948 {
1949         grab_focus();//on_focus_in_event(0);
1950         Gtk::Window::present();
1951 }
1952
1953 bool
1954 CanvasView::on_focus_in_event(GdkEventFocus*x)
1955 {
1956         if(studio::App::get_selected_canvas_view()!=this)
1957         {
1958                 if(studio::App::get_selected_canvas_view())
1959                 {
1960                         studio::App::get_selected_canvas_view()->get_smach().process_event(EVENT_YIELD_TOOL_OPTIONS);
1961                         App::ui_manager()->remove_action_group(App::get_selected_canvas_view()->action_group);
1962                 }
1963
1964                 get_smach().process_event(EVENT_REFRESH_TOOL_OPTIONS);
1965
1966                 studio::App::set_selected_canvas_view(this);
1967
1968                 App::ui_manager()->insert_action_group(action_group);
1969         }
1970
1971         // HACK ... Questionable...?
1972         if(x)
1973                 return Gtk::Window::on_focus_in_event(x);
1974
1975         return true;
1976 }
1977
1978 bool
1979 CanvasView::on_focus_out_event(GdkEventFocus*x)
1980 {
1981         //App::ui_manager()->remove_action_group(action_group);
1982         //App::ui_manager()->ensure_update();
1983         return Gtk::Window::on_focus_out_event(x);
1984 }
1985
1986 void
1987 CanvasView::refresh_tables()
1988 {
1989 //      if(layer_tree_store_)layer_tree_store_->refresh();
1990 //      if(children_tree_store_)children_tree_store_->refresh();
1991 }
1992
1993 void
1994 CanvasView::rebuild_tables()
1995 {
1996 //      layer_tree_store_->rebuild();
1997 //      children_tree_store_->rebuild();
1998 }
1999
2000 void
2001 CanvasView::build_tables()
2002 {
2003 //      layer_tree_store_->rebuild();
2004 //      children_tree_store_->rebuild();
2005 }
2006
2007 void
2008 CanvasView::on_layer_toggle(synfig::Layer::Handle layer)
2009 {
2010         synfigapp::Action::Handle action(synfigapp::Action::create("layer_activate"));
2011         assert(action);
2012
2013         if(!action)
2014                 return;
2015
2016         action->set_param("canvas",Canvas::Handle(layer->get_canvas()));
2017         if(!action->set_param("canvas_interface",canvas_interface()))
2018 //      if(!action->set_param("canvas_interface",get_instance()->find_canvas_interface(layer->get_canvas())))
2019                 synfig::error("LayerActivate didn't like CanvasInterface...?");
2020         action->set_param("time",get_time());
2021         action->set_param("layer",layer);
2022         action->set_param("new_status",!layer->active());
2023
2024         assert(action->is_ready());
2025
2026         canvas_interface()->get_instance()->perform_action(action);
2027 }
2028
2029
2030 void
2031 CanvasView::popup_param_menu(synfigapp::ValueDesc value_desc, float location)
2032 {
2033         parammenu.items().clear();
2034         get_instance()->make_param_menu(&parammenu,get_canvas(),value_desc,location);
2035
2036         parammenu.popup(3,gtk_get_current_event_time());
2037 }
2038
2039 void
2040 CanvasView::add_actions_to_menu(Gtk::Menu *menu, const synfigapp::Action::ParamList &param_list,synfigapp::Action::Category category)const
2041 {
2042         get_instance()->add_actions_to_menu(menu, param_list, category);
2043 }
2044
2045 bool
2046 CanvasView::on_layer_user_click(int button, Gtk::TreeRow row, LayerTree::ColumnID column_id)
2047 {
2048         switch(button)
2049         {
2050         case 3:
2051                 {
2052
2053                         Gtk::MenuItem* menu = dynamic_cast<Gtk::MenuItem*>(App::ui_manager()->get_widget("/menu-main/menu-layer"));
2054                         if(menu && menu->get_submenu())
2055                         {
2056                                 //menu->set_accel_group(App::ui_manager()->get_accel_group());
2057                                 //menu->accelerate(*this);
2058                                 menu->get_submenu()->popup(button,gtk_get_current_event_time());
2059                         }
2060
2061
2062                         #if 0
2063                         bool multiple_selected=true;
2064
2065                         if(layer_tree->get_selection()->count_selected_rows()<=1)
2066                                 multiple_selected=false;
2067
2068                         // If the clicked row is not selected, then unselect
2069                         // everything that isn't selected and select this row
2070                         if(multiple_selected && !layer_tree->get_selection()->is_selected(row))
2071                         {
2072                                 layer_tree->get_selection()->unselect_all();
2073                                 layer_tree->get_selection()->select(row);
2074                                 multiple_selected=false;
2075                         }
2076
2077                         if(column_id==COLUMNID_TIME_TRACK)
2078                                 return false;
2079
2080                         //synfigapp::ValueDesc value_desc(row[layer_param_tree_model.value_desc]);
2081                         //ValueNode::Handle value_node(row[layer_param_tree_model.value_node]);
2082                         //ValueNode::Handle parent_value_node;
2083                         //ValueBase value=row[layer_param_tree_model.value];
2084
2085                         //if(row.parent())
2086                         //{
2087                         //      parent_value_node=(*row.parent())[layer_tree_model.value_node];
2088                         //}
2089
2090                         {
2091                                 Layer::Handle layer(row[layer_tree_model.layer]);
2092                                 synfigapp::Action::ParamList param_list;
2093                                 param_list.add("time",canvas_interface()->get_time());
2094                                 param_list.add("canvas",Canvas::Handle(row[layer_tree_model.canvas]));
2095                                 param_list.add("canvas_interface",canvas_interface());
2096                                 if(!multiple_selected)
2097                                         param_list.add("layer",layer);
2098                                 else
2099                                 {
2100                                         synfigapp::SelectionManager::LayerList layer_list(get_selection_manager()->get_selected_layers());
2101                                         synfigapp::SelectionManager::LayerList::iterator iter;
2102
2103                                         for(iter=layer_list.begin();iter!=layer_list.end();++iter)
2104                                                 param_list.add("layer",Layer::Handle(*iter));
2105                                 }
2106
2107                                 parammenu.items().clear();
2108
2109                                 Gtk::Menu *newlayers(manage(new Gtk::Menu()));
2110                                 build_new_layer_menu(*newlayers);
2111
2112                                 parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem("New Layer",*newlayers));
2113                                 if(!multiple_selected && layer->get_name()=="paste_canvas")
2114                                 {
2115                                         parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Select All Children"),
2116                                                 sigc::bind(
2117                                                         sigc::mem_fun(
2118                                                                 *layer_tree,
2119                                                                 &studio::LayerTree::select_all_children_layers
2120                                                         ),
2121                                                         layer
2122                                                 )
2123                                         ));
2124                                 }
2125
2126                                 add_actions_to_menu(&parammenu, param_list,synfigapp::Action::CATEGORY_LAYER);
2127                                 parammenu.popup(button,gtk_get_current_event_time());
2128                                 return true;
2129                         }
2130 /*
2131                         else if(column_id==LayerTree::COLUMNID_TIME_TRACK && value_node && handle<synfig::ValueNode_Animated>::cast_dynamic(value_node))
2132                         {
2133                                 // Right-click on time track with animated
2134 //                              trackmenu.popup(0,0);
2135                                 return true;
2136                         }
2137                         else
2138                         {
2139                                 if(!multiple_selected)
2140                                 {
2141                                         popup_param_menu(value_desc);
2142                                         return true;
2143                                 }
2144                                 else
2145                                 {
2146 #warning update me!
2147 #if 0
2148                                         parammenu.items().clear();
2149                                         parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem("Connect",
2150                                                 hide_return(sigc::mem_fun(*canvas_interface().get(),&synfigapp::CanvasInterface::connect_selected_layer_params))
2151                                         ));
2152                                         parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem("Disconnect",
2153                                                 hide_return(sigc::mem_fun(*canvas_interface().get(),&synfigapp::CanvasInterface::disconnect_selected_layer_params))
2154                                         ));
2155                                         parammenu.popup(0,0);
2156 #endif
2157                                 }
2158                                 return true;
2159                         }
2160                 */
2161 #endif
2162 }
2163                 return true;
2164                 break;
2165
2166         default:
2167                 return false;
2168                 break;
2169         }
2170 }
2171
2172
2173
2174 bool
2175 CanvasView::on_children_user_click(int button, Gtk::TreeRow row, ChildrenTree::ColumnID column_id)
2176 {
2177         switch(button)
2178         {
2179         case 3:
2180                 {
2181                         if(column_id==COLUMNID_TIME_TRACK)
2182                                 return false;
2183                         if(!(bool)row[children_tree_model.is_canvas])
2184                         {
2185                                 synfigapp::ValueDesc value_desc=row[children_tree_model.value_desc];
2186                                 if (!value_desc)
2187                                 {
2188                                         //! \todo fix properly -- what is the child dialog for?
2189                                         synfig::info("preventing child dialog right-click crash");
2190                                         return true;
2191                                 }
2192                                 assert(value_desc);
2193                                 popup_param_menu(value_desc);
2194                                 return true;
2195                         }
2196                 }
2197                 return true;
2198                 break;
2199
2200         default:
2201                 return false;
2202                 break;
2203         }
2204 }
2205
2206 bool
2207 CanvasView::on_keyframe_tree_event(GdkEvent *event)
2208 {
2209     switch(event->type)
2210     {
2211         case GDK_BUTTON_PRESS:
2212                 switch(event->button.button)
2213                 {
2214                         case 3:
2215                         {
2216                                 //keyframemenu.popup(event->button.button,gtk_get_current_event_time());
2217                                 return true;
2218                         }
2219                         break;
2220                 }
2221                 break;
2222         case GDK_MOTION_NOTIFY:
2223                 break;
2224         case GDK_BUTTON_RELEASE:
2225                 break;
2226         default:
2227                 break;
2228         }
2229         return false;
2230 }
2231
2232
2233 void
2234 CanvasView::refresh_time_window()
2235 {
2236         //THESE SHOULD AUTOMATICALLY BE TAKEN CARE OF
2237         //time_adjustment().set_lower(time_window_adjustment().get_value());
2238         //time_adjustment().set_upper(time_window_adjustment().get_value()+time_window_adjustment().get_page_size());
2239
2240         time_adjustment().set_page_increment(1.0); // One second
2241         time_adjustment().set_page_size(0);
2242
2243         if(get_canvas())
2244                 time_adjustment().set_step_increment(1.0/get_canvas()->rend_desc().get_frame_rate());
2245         time_adjustment().changed();
2246
2247         //NOTE THIS SHOULD HOOK INTO THE CORRECT SIGNALS...
2248         if(children_tree)
2249                 children_tree->queue_draw();
2250 }
2251
2252 void
2253 CanvasView::on_time_changed()
2254 {
2255         Time time(get_time());
2256
2257         current_time_widget->set_value(time);
2258         try {
2259                 get_canvas()->keyframe_list().find(time);
2260                 current_time_widget->modify_text(Gtk::STATE_NORMAL,Gdk::Color("#FF0000"));
2261         }catch(...){
2262                 current_time_widget->modify_text(Gtk::STATE_NORMAL,Gdk::Color("#000000"));
2263         }
2264
2265         if(get_time() != time_adjustment().get_value())
2266         {
2267
2268                 //Recenters the window, causing it to jump (possibly undesirably... but whatever)
2269                 if(time < time_window_adjustment().get_value() ||
2270                         time > time_window_adjustment().get_value()+time_window_adjustment().get_page_size())
2271                 {
2272                         time_window_adjustment().set_value(
2273                                 time-time_window_adjustment().get_page_size()/2
2274                         );
2275                 }
2276                 time_adjustment().set_value(time);
2277                 time_adjustment().value_changed();
2278
2279                 // Shouldn't these trees just hook into
2280                 // the time changed signal...?
2281                 //YES THEY SHOULD...
2282                 if(layer_tree)layer_tree->queue_draw();
2283                 if(children_tree)children_tree->queue_draw();
2284         }
2285 }
2286
2287 void
2288 CanvasView::time_zoom_in()
2289 {
2290         time_window_adjustment().set_page_size(time_window_adjustment().get_page_size()*0.75);
2291         time_window_adjustment().changed();
2292
2293         refresh_time_window();
2294 }
2295
2296 void
2297 CanvasView::time_zoom_out()
2298 {
2299         time_window_adjustment().set_page_size(time_window_adjustment().get_page_size()/0.75);
2300         time_window_adjustment().changed();
2301
2302         refresh_time_window();
2303 }
2304
2305 void
2306 CanvasView::time_was_changed()
2307 {
2308         synfig::Time time((synfig::Time)(double)time_adjustment().get_value());
2309         set_time(time);
2310 }
2311
2312 void
2313 CanvasView::on_edited_value(synfigapp::ValueDesc value_desc,synfig::ValueBase new_value)
2314 {
2315         canvas_interface()->change_value(value_desc,new_value);
2316 }
2317
2318 /*
2319 void
2320 CanvasView::on_children_edited_value(const Glib::ustring&path_string,synfig::ValueBase value)
2321 {
2322         Gtk::TreePath path(path_string);
2323
2324         const Gtk::TreeRow row = *(children_tree->get_model()->get_iter(path));
2325
2326         assert((bool)row[children_tree_model.is_value_node]);
2327
2328         synfigapp::ValueDesc value_desc=row[children_tree_model.value_desc];
2329         assert(value_desc);
2330
2331         on_edited_value(value_desc,value);
2332 }
2333 */
2334
2335 void
2336 CanvasView::on_id_changed()
2337 {
2338         update_title();
2339 }
2340
2341
2342 void
2343 CanvasView::on_mode_changed(synfigapp::CanvasInterface::Mode mode)
2344 {
2345         // If the aninimate flag was set in mode...
2346         if(mode&synfigapp::MODE_ANIMATE)
2347         {
2348                 Gtk::Image *icon;
2349                 icon=manage(new Gtk::Image(Gtk::StockID("gtk-no"),Gtk::ICON_SIZE_BUTTON));
2350                 animatebutton->remove();
2351                 animatebutton->add(*icon);
2352                 tooltips.set_tip(*animatebutton,_("In Animate Editing Mode"));
2353                 icon->set_padding(0,0);
2354                 icon->show();
2355         }
2356         else
2357         {
2358                 Gtk::Image *icon;
2359                 icon=manage(new Gtk::Image(Gtk::StockID("gtk-yes"),Gtk::ICON_SIZE_BUTTON));
2360                 animatebutton->remove();
2361                 animatebutton->add(*icon);
2362                 tooltips.set_tip(*animatebutton,_("Not in Animate Editing Mode"));
2363                 icon->set_padding(0,0);
2364                 icon->show();
2365         }
2366
2367         if((mode&synfigapp::MODE_ANIMATE_FUTURE) && (mode&synfigapp::MODE_ANIMATE_PAST))
2368         {
2369                 Gtk::Image *icon;
2370                 icon=manage(new Gtk::Image(Gtk::StockID("synfig-keyframe_lock_all"),Gtk::ICON_SIZE_BUTTON));
2371                 keyframebutton->remove();
2372                 keyframebutton->add(*icon);
2373                 tooltips.set_tip(*keyframebutton,_("All Keyframes Locked"));
2374                 icon->set_padding(0,0);
2375                 icon->show();
2376         }
2377         else if((mode&synfigapp::MODE_ANIMATE_FUTURE) && !(mode&synfigapp::MODE_ANIMATE_PAST))
2378         {
2379                 Gtk::Image *icon;
2380                 icon=manage(new Gtk::Image(Gtk::StockID("synfig-keyframe_lock_future"),Gtk::ICON_SIZE_BUTTON));
2381                 keyframebutton->remove();
2382                 keyframebutton->add(*icon);
2383                 tooltips.set_tip(*keyframebutton,_("Future Keyframes Locked"));
2384                 icon->set_padding(0,0);
2385                 icon->show();
2386         }
2387         else if(!(mode&synfigapp::MODE_ANIMATE_FUTURE) && (mode&synfigapp::MODE_ANIMATE_PAST))
2388         {
2389                 Gtk::Image *icon;
2390                 icon=manage(new Gtk::Image(Gtk::StockID("synfig-keyframe_lock_past"),Gtk::ICON_SIZE_BUTTON));
2391                 keyframebutton->remove();
2392                 keyframebutton->add(*icon);
2393                 tooltips.set_tip(*keyframebutton,_("Past Keyframes Locked"));
2394                 icon->set_padding(0,0);
2395                 icon->show();
2396         }
2397         else if(!(mode&synfigapp::MODE_ANIMATE_FUTURE) && !(mode&synfigapp::MODE_ANIMATE_PAST))
2398         {
2399                 Gtk::Image *icon;
2400                 icon=manage(new Gtk::Image(Gtk::StockID("synfig-keyframe_lock_none"),Gtk::ICON_SIZE_BUTTON));
2401                 keyframebutton->remove();
2402                 keyframebutton->add(*icon);
2403                 tooltips.set_tip(*keyframebutton,_("No Keyframes Locked"));
2404                 icon->set_padding(0,0);
2405                 icon->show();
2406         }
2407
2408         work_area->queue_draw();
2409 }
2410
2411 void
2412 CanvasView::on_animate_button_pressed()
2413 {
2414         if(get_mode()&synfigapp::MODE_ANIMATE)
2415                 set_mode(get_mode()-synfigapp::MODE_ANIMATE);
2416         else
2417                 set_mode(get_mode()|synfigapp::MODE_ANIMATE);
2418 }
2419
2420 void
2421 CanvasView::on_keyframe_button_pressed()
2422 {
2423         synfigapp::CanvasInterface::Mode mode(get_mode());
2424
2425         if((mode&synfigapp::MODE_ANIMATE_FUTURE) && (mode&synfigapp::MODE_ANIMATE_PAST))
2426         {
2427                 set_mode(get_mode()-synfigapp::MODE_ANIMATE_FUTURE);
2428         }
2429         else if(!(mode&synfigapp::MODE_ANIMATE_FUTURE) && (mode&synfigapp::MODE_ANIMATE_PAST))
2430         {
2431                 set_mode(get_mode()-synfigapp::MODE_ANIMATE_PAST|synfigapp::MODE_ANIMATE_FUTURE);
2432         }
2433         else if((mode&synfigapp::MODE_ANIMATE_FUTURE) && !(mode&synfigapp::MODE_ANIMATE_PAST))
2434         {
2435                 set_mode(get_mode()-synfigapp::MODE_ANIMATE_FUTURE);
2436         }
2437         else if(!(mode&synfigapp::MODE_ANIMATE_FUTURE) && !(mode&synfigapp::MODE_ANIMATE_PAST))
2438         {
2439                 set_mode(get_mode()|synfigapp::MODE_ANIMATE_FUTURE|synfigapp::MODE_ANIMATE_PAST);
2440         }
2441 }
2442
2443 bool
2444 CanvasView::duck_change_param(const Point &value,synfig::Layer::Handle layer, synfig::String param_name)
2445 {
2446         return canvas_interface()->change_value(synfigapp::ValueDesc(layer,param_name),value);
2447 }
2448
2449 bool
2450 CanvasView::on_duck_changed(const synfig::Point &value,const synfigapp::ValueDesc& value_desc)
2451 {
2452         switch(value_desc.get_value_type())
2453         {
2454         case ValueBase::TYPE_REAL:
2455                 return canvas_interface()->change_value(value_desc,value.mag());
2456                 break;
2457         case ValueBase::TYPE_ANGLE:
2458                 return canvas_interface()->change_value(value_desc,Angle::tan(value[1],value[0]));
2459                 break;
2460         default:
2461                 return canvas_interface()->change_value(value_desc,value);
2462                 break;
2463         }
2464
2465         return true;
2466 }
2467
2468 void
2469 CanvasView::selected_layer_color_set(Color color)
2470 {
2471         synfigapp::SelectionManager::LayerList selected_list(get_selection_manager()->get_selected_layers());
2472         synfigapp::SelectionManager::LayerList::iterator iter;
2473
2474         // Create the action group
2475         //synfigapp::PassiveGrouper group(canvas_interface()->get_instance(),_("Set Colors"));
2476
2477         Layer::Handle layer;
2478         for(iter=selected_list.begin();iter!=selected_list.end();++iter)
2479         {
2480                 if(*iter==layer)
2481                         continue;
2482                 layer=*iter;
2483                 on_edited_value(synfigapp::ValueDesc(layer,"color"),color);
2484         }
2485 }
2486
2487 void
2488 CanvasView::rebuild_ducks_layer_(synfig::TransformStack& transform_stack, Canvas::Handle canvas, std::set<synfig::Layer::Handle>& selected_list)
2489 {
2490         int transforms(0);
2491         String layer_name;
2492
2493 #define QUEUE_REBUILD_DUCKS             sigc::mem_fun(*this,&CanvasView::queue_rebuild_ducks)
2494
2495         if(!canvas)
2496         {
2497                 synfig::warning("CanvasView::rebuild_ducks_layer_(): Layer doesn't have canvas set");
2498                 return;
2499         }
2500         for(Canvas::iterator iter(canvas->begin());iter!=canvas->end();++iter)
2501         {
2502                 Layer::Handle layer(*iter);
2503
2504                 if(selected_list.count(layer))
2505                 {
2506                         if(!curr_transform_stack_set)
2507                         {
2508                                 curr_transform_stack_set=true;
2509                                 curr_transform_stack=transform_stack;
2510                         }
2511
2512                         // This layer is currently selected.
2513                         duck_changed_connections.push_back(layer->signal_changed().connect(QUEUE_REBUILD_DUCKS));
2514
2515                         // do the bounding box thing
2516                         bbox|=transform_stack.perform(layer->get_bounding_rect());
2517
2518                         // Grab the layer's list pf parameters
2519                         Layer::ParamList paramlist(layer->get_param_list());
2520
2521                         // Grab the layer vocabulary
2522                         Layer::Vocab vocab=layer->get_param_vocab();
2523                         Layer::Vocab::iterator iter;
2524
2525                         for(iter=vocab.begin();iter!=vocab.end();iter++)
2526                         {
2527                                 if(!iter->get_hidden() && !iter->get_invisible_duck())
2528                                 {
2529                                         synfigapp::ValueDesc value_desc(layer,iter->get_name());
2530                                         work_area->add_to_ducks(value_desc,this,transform_stack,&*iter);
2531                                         if(value_desc.is_value_node())
2532                                                 duck_changed_connections.push_back(value_desc.get_value_node()->signal_changed().connect(QUEUE_REBUILD_DUCKS));
2533                                 }
2534                                 if(iter->get_name()=="color")
2535                                 {
2536                                         /*
2537                                         if(!App::dialog_color->busy())
2538                                         {
2539                                                 App::dialog_color->reset();
2540                                                 App::dialog_color->set_color(layer->get_param("color").get(Color()));
2541                                                 App::dialog_color->signal_edited().connect(
2542                                                         sigc::mem_fun(
2543                                                                 *this,
2544                                                                 &studio::CanvasView::selected_layer_color_set
2545                                                         )
2546                                                 );
2547                                         }
2548                                         */
2549                                 }
2550                         }
2551                 }
2552
2553                 layer_name=layer->get_name();
2554
2555                 if(layer->active())
2556                 {
2557                         Transform::Handle trans(layer->get_transform());
2558                         if(trans)
2559                         {
2560                                 transform_stack.push(trans);
2561                                 transforms++;
2562                         }
2563
2564 /*                      // Add transforms onto the stack
2565                         if(layer_name=="Translate")
2566                         {
2567                                 transform_stack.push(synfig::Transform_Translate(layer->get_param("origin").get(Vector())));
2568                                 transforms++;
2569                         }else
2570                         if(layer_name=="Zoom")
2571                         {
2572                                 Vector scale;
2573                                 scale[0]=scale[1]=exp(layer->get_param("amount").get(Real()));
2574                                 transform_stack.push(synfig::Transform_Scale(scale,layer->get_param("center").get(Vector())));
2575                                 transforms++;
2576                         }else
2577                         if(layer_name=="stretch")
2578                         {
2579                                 Vector scale(layer->get_param("amount").get(Vector()));
2580                                 transform_stack.push(synfig::Transform_Scale(scale,layer->get_param("center").get(Vector())));
2581                                 transforms++;
2582                         }else
2583                         if(layer_name=="Rotate")
2584                         {
2585                                 transform_stack.push(synfig::Transform_Rotate(layer->get_param("amount").get(Angle()),layer->get_param("origin").get(Vector())));
2586                                 transforms++;
2587                         }
2588 */
2589                 }
2590
2591                 // If this is a paste canvas layer, then we need to
2592                 // descend into it
2593                 if(layer_name=="paste_canvas")
2594                 {
2595                         Vector scale;
2596                         scale[0]=scale[1]=exp(layer->get_param("zoom").get(Real()));
2597                         Vector origin(layer->get_param("origin").get(Vector()));
2598
2599                         Canvas::Handle child_canvas(layer->get_param("canvas").get(Canvas::Handle()));
2600
2601                         if(!scale.is_equal_to(Vector(1,1)))
2602                                 transform_stack.push(new Transform_Scale(scale,origin));
2603                         if(!scale.is_equal_to(Vector(0,0)))
2604                                 transform_stack.push(new Transform_Translate(origin));
2605
2606                         rebuild_ducks_layer_(transform_stack,child_canvas,selected_list);
2607
2608                         if(!scale.is_equal_to(Vector(0,0)))
2609                                 transform_stack.pop();
2610                         if(!scale.is_equal_to(Vector(1,1)))
2611                                 transform_stack.pop();
2612                 }
2613         }
2614         // Remove all of the transforms we have added
2615         while(transforms--) { transform_stack.pop(); }
2616
2617 #undef QUEUE_REBUILD_DUCKS
2618 }
2619
2620 void
2621 CanvasView::queue_rebuild_ducks()
2622 {
2623 #if 0
2624         if(rebuild_ducks_queued)
2625                 return;
2626 #else
2627         if(rebuild_ducks_queued)
2628                 queue_rebuild_ducks_connection.disconnect();
2629 #endif
2630
2631         queue_rebuild_ducks_connection=Glib::signal_timeout().connect(
2632                 sigc::bind_return(
2633                         sigc::mem_fun(*this,&CanvasView::rebuild_ducks),
2634                         false
2635                 ),
2636                 50
2637         );
2638
2639         rebuild_ducks_queued=true;
2640 }
2641
2642 void
2643 CanvasView::rebuild_ducks()
2644 {
2645         /*static int i=0;
2646         i++;
2647         if(i>30)
2648                 synfig::info("%d",i/(i-i));
2649         */
2650
2651         rebuild_ducks_queued=false;
2652         //queue_rebuild_ducks_connection.disconnect();
2653
2654         if(work_area->is_dragging())
2655         {
2656                 queue_rebuild_ducks();
2657                 return;
2658         }
2659
2660         if(!duck_refresh_flag)
2661         {
2662                 duck_refresh_needed=true;
2663                 return;
2664         }
2665
2666         bbox=Rect::zero();
2667
2668         work_area->clear_ducks();
2669         work_area->set_time(get_time());
2670         get_canvas()->set_time(get_time());
2671         curr_transform_stack.clear();
2672         //curr_transform_stack.push(new Transform_Translate(Point(0,0)));
2673         curr_transform_stack_set=false;
2674
2675         for(;!duck_changed_connections.empty();duck_changed_connections.pop_back())duck_changed_connections.back().disconnect();
2676
2677         //get_canvas()->set_time(get_time());
2678         bool not_empty(false);
2679
2680         // First do the layers...
2681         do{
2682                 synfigapp::SelectionManager::LayerList selected_list(get_selection_manager()->get_selected_layers());
2683                 std::set<synfig::Layer::Handle> layer_set(selected_list.begin(),selected_list.end());
2684
2685                 if(!layer_set.empty())
2686                         not_empty=true;
2687
2688                 synfig::TransformStack transform_stack;
2689
2690                 rebuild_ducks_layer_(transform_stack, get_canvas(), layer_set);
2691
2692         }while(0);
2693
2694         // Now do the children
2695         do{
2696                 synfigapp::SelectionManager::ChildrenList selected_list(get_selection_manager()->get_selected_children());
2697                 synfigapp::SelectionManager::ChildrenList::iterator iter;
2698                 synfig::TransformStack transform_stack;
2699
2700                 if(selected_list.empty())
2701                 {
2702                         break;
2703                 }
2704                 else
2705                 {
2706                         not_empty=true;
2707                         for(iter=selected_list.begin();iter!=selected_list.end();++iter)
2708                         {
2709                                 work_area->add_to_ducks(*iter,this,transform_stack);
2710                         }
2711                 }
2712         }while(0);
2713         work_area->refresh_selected_ducks();
2714         work_area->queue_draw_preview();
2715 }
2716
2717 void
2718 CanvasView::on_dirty_preview()
2719 {
2720         if(!is_playing_)
2721         {
2722                 IsWorking is_working(*this);
2723
2724                 work_area->queue_render_preview();
2725         }
2726 }
2727
2728 void
2729 CanvasView::play()
2730 {
2731         assert(get_canvas());
2732
2733         // If we are already busy, don't play!
2734         if(working_depth)return;
2735
2736         // Set us up as working
2737         IsWorking is_working(*this);
2738
2739         etl::clock timer;
2740         Time
2741                 time=work_area->get_time(),
2742                 endtime=get_canvas()->rend_desc().get_time_end();
2743
2744         // If we are already at the end of time, start over
2745         if(time==endtime)
2746                 time=get_canvas()->rend_desc().get_time_start();
2747
2748         is_playing_=true;
2749
2750         work_area->clear_ducks();
2751
2752         for(timer.reset(); time + timer() < endtime;)
2753         {
2754                 //Clamp the time window so we can see the time value as it races across the horizon
2755                 bool timewindreset = false;
2756
2757                 while( time + timer() > Time(time_window_adjustment().get_sub_upper()) )
2758                 {
2759                         time_window_adjustment().set_value(
2760                                         min(
2761                                                 time_window_adjustment().get_value()+time_window_adjustment().get_page_size()/2,
2762                                                 time_window_adjustment().get_upper()-time_window_adjustment().get_page_size() )
2763                                 );
2764                         timewindreset = true;
2765                 }
2766
2767                 while( time + timer() < Time(time_window_adjustment().get_sub_lower()) )
2768                 {
2769                         time_window_adjustment().set_value(
2770                                 max(
2771                                         time_window_adjustment().get_value()-time_window_adjustment().get_page_size()/2,
2772                                         time_window_adjustment().get_lower())
2773                         );
2774
2775                         timewindreset = true;
2776                 }
2777
2778                 //we need to tell people that the value changed
2779                 if(timewindreset) time_window_adjustment().value_changed();
2780
2781                 //update actual time to next step
2782                 time_adjustment().set_value(time+timer());
2783                 time_adjustment().value_changed();
2784
2785                 if(!work_area->sync_render_preview())
2786                         break;
2787
2788                 studio::App::iteration(false);
2789
2790                 if(get_cancel_status())
2791                         return;
2792         }
2793         is_playing_=false;
2794
2795         time_adjustment().set_value(endtime);
2796         time_adjustment().value_changed();
2797 }
2798
2799 void
2800 CanvasView::show_tables()
2801 {
2802 /*
2803         Smach::event_result x(process_event_key(EVENT_TABLES_SHOW));
2804         if(x==Smach::RESULT_OK || x==Smach::RESULT_ACCEPT)
2805         {
2806                 Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon");
2807                 treetogglebutton->remove();
2808                 treetogglebutton->add(*manage(new Gtk::Image(Gtk::StockID("gtk-go-down"),iconsize)));
2809                 treetogglebutton->show_all();
2810                 notebook->show();
2811         }
2812 */
2813 }
2814
2815 void
2816 CanvasView::hide_tables()
2817 {
2818 /*
2819         Smach::event_result x(process_event_key(EVENT_TABLES_HIDE));
2820         if(x==Smach::RESULT_OK || x==Smach::RESULT_ACCEPT)
2821         {
2822                 Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon");
2823                 treetogglebutton->remove();
2824                 treetogglebutton->add(*manage(new Gtk::Image(Gtk::StockID("gtk-go-up"),iconsize)));
2825                 treetogglebutton->show_all();
2826                 notebook->hide();
2827         }
2828 */
2829 }
2830
2831 bool
2832 CanvasView::tables_are_visible()
2833 {
2834 //      return notebook->is_visible();
2835         return false;
2836 }
2837
2838 void
2839 CanvasView::toggle_tables()
2840 {
2841 //      if(tables_are_visible())
2842 //              hide_tables();
2843 //      else
2844 //              show_tables();
2845 }
2846
2847 void
2848 CanvasView::show_timebar()
2849 {
2850         timebar->show();
2851         current_time_widget->show();
2852
2853         //keyframe_tab_child->show();
2854         if(layer_tree)
2855                 layer_tree->set_show_timetrack(true);
2856         if(children_tree)
2857                 children_tree->set_show_timetrack(true);
2858 }
2859
2860 void
2861 CanvasView::hide_timebar()
2862 {
2863         timebar->hide();
2864         current_time_widget->hide();
2865         //keyframe_tab_child->hide();
2866         if(layer_tree)
2867                 layer_tree->set_show_timetrack(false);
2868         if(children_tree)
2869                 children_tree->set_show_timetrack(false);
2870 }
2871
2872 void
2873 CanvasView::set_sensitive_timebar(bool sensitive)
2874 {
2875         timebar->set_sensitive(sensitive);
2876         current_time_widget->set_sensitive(sensitive);
2877         //keyframe_tab_child->set_sensitive(sensitive);
2878         if(layer_tree)
2879                 layer_tree->set_sensitive(sensitive);
2880         if(children_tree)
2881                 children_tree->set_sensitive(sensitive);
2882 }
2883
2884
2885 void
2886 CanvasView::on_waypoint_clicked(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint,int button)
2887 {
2888         waypoint_dialog.set_value_desc(value_desc);
2889         waypoint_dialog.set_waypoint(waypoint);
2890
2891         switch(button)
2892         {
2893         case -1:
2894                 waypoint_dialog.show();
2895                 break;
2896         case 2:
2897                 {
2898                         Gtk::Menu* waypoint_menu(manage(new Gtk::Menu()));
2899
2900                         waypoint_menu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-jump-to"),
2901                                 sigc::bind(
2902                                         sigc::mem_fun(
2903                                                 *canvas_interface(),
2904                                                 &synfigapp::CanvasInterface::set_time
2905                                         ),
2906                                         waypoint.get_time()
2907                                 )
2908                         ));
2909
2910                         waypoint_menu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("Edit Waypoint"),
2911                                 sigc::mem_fun(
2912                                         waypoint_dialog,
2913                                         &Gtk::Widget::show
2914                                 )
2915                         ));
2916
2917                         waypoint_menu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("synfig-duplicate"),
2918                                 sigc::bind(
2919                                         sigc::bind(
2920                                                 sigc::mem_fun(
2921                                                         *canvas_interface(),
2922                                                         &synfigapp::CanvasInterface::waypoint_duplicate
2923                                                 ),
2924                                                 waypoint
2925                                         ),
2926                                         value_desc
2927                                 )
2928                         ));
2929                         waypoint_menu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-delete"),
2930                                 sigc::bind(
2931                                         sigc::bind(
2932                                                 sigc::mem_fun(
2933                                                         *canvas_interface(),
2934                                                         &synfigapp::CanvasInterface::waypoint_remove
2935                                                 ),
2936                                                 waypoint
2937                                         ),
2938                                         value_desc
2939                                 )
2940                         ));
2941                         waypoint_menu->popup(button+1,gtk_get_current_event_time());
2942                 }
2943                 break;
2944         default:
2945                 break;
2946         }
2947 }
2948
2949 void
2950 CanvasView::on_waypoint_changed()
2951 {
2952         synfigapp::Action::ParamList param_list;
2953         param_list.add("canvas",get_canvas());
2954         param_list.add("canvas_interface",canvas_interface());
2955         param_list.add("value_node",waypoint_dialog.get_value_desc().get_value_node());
2956         param_list.add("waypoint",waypoint_dialog.get_waypoint());
2957 //      param_list.add("time",canvas_interface()->get_time());
2958
2959         get_instance()->process_action("waypoint_set_smart", param_list);
2960 }
2961
2962 void
2963 CanvasView::on_waypoint_delete()
2964 {
2965         synfigapp::Action::ParamList param_list;
2966         param_list.add("canvas",get_canvas());
2967         param_list.add("canvas_interface",canvas_interface());
2968         param_list.add("value_node",waypoint_dialog.get_value_desc().get_value_node());
2969         param_list.add("waypoint",waypoint_dialog.get_waypoint());
2970 //      param_list.add("time",canvas_interface()->get_time());
2971
2972         get_instance()->process_action("waypoint_remove", param_list);
2973 }
2974
2975 void
2976 CanvasView::on_drop_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data_, guint info, guint time)
2977 {
2978         // We will make this true once we have a solid drop
2979         bool success(false);
2980         //synfig::info("Droped data of type \"%s\"",selection_data.get_data_type());
2981         //synfig::info("Droped data of target \"%s\"",gdk_atom_name(selection_data->target));
2982         //synfig::info("selection=\"%s\"",gdk_atom_name(selection_data->selection));
2983
2984         if ((selection_data_.get_length() >= 0) && (selection_data_.get_format() == 8))
2985         {
2986                 if(synfig::String(selection_data_.get_data_type())=="STRING")do
2987                 {
2988                         synfig::String selection_data((gchar *)(selection_data_.get_data()));
2989
2990                         Layer::Handle layer(synfig::Layer::create("Text"));
2991                         if(!layer)
2992                                 break;
2993                         if(!layer->set_param("text",ValueBase(selection_data)))
2994                                 break;
2995
2996                         synfigapp::Action::Handle       action(synfigapp::Action::create("layer_add"));
2997
2998                         assert(action);
2999                         if(!action)
3000                                 break;
3001
3002                         action->set_param("canvas",get_canvas());
3003                         action->set_param("canvas_interface",canvas_interface());
3004                         action->set_param("new",layer);
3005
3006                         if(!get_instance()->perform_action(action))
3007                                 break;
3008
3009                         // Ok, we have successfuly imported at least one item.
3010                         success=true;
3011                 } while(0); // END of "STRING"
3012
3013                 if(synfig::String(selection_data_.get_data_type())=="text/plain")
3014                 {
3015                         synfig::String selection_data((gchar *)(selection_data_.get_data()));
3016
3017                         // For some reason, GTK hands us a list of URL's seperated
3018                         // by not only Carrage-Returns, but also Line-Feeds.
3019                         // Line-Feeds will mess us up. Remove all the line-feeds.
3020                         while(selection_data.find_first_of('\r')!=synfig::String::npos)
3021                                 selection_data.erase(selection_data.begin()+selection_data.find_first_of('\r'));
3022
3023                         std::stringstream stream(selection_data);
3024
3025                         //synfigapp::PassiveGrouper group(canvas_interface()->get_instance(),_("Insert Image"));
3026                         while(stream)
3027                         {
3028                                 synfig::String filename,URI;
3029                                 getline(stream,filename);
3030
3031                                 // If we don't have a filename, move on.
3032                                 if(filename.empty())
3033                                         continue;
3034
3035                                 // Make sure this URL is of the "file://" type.
3036                                 URI=String(filename.begin(),filename.begin()+sizeof("file://")-1);
3037                                 if(URI!="file://")
3038                                 {
3039                                         synfig::warning("Unknown URI (%s) in \"%s\"",URI.c_str(),filename.c_str());
3040                                         continue;
3041                                 }
3042
3043                                 // Strip the "file://" part from the filename
3044                                 filename=synfig::String(filename.begin()+sizeof("file://")-1,filename.end());
3045
3046                                 String ext;
3047                                 try{ext=(String(filename.begin()+filename.find_last_of('.')+1,filename.end()));}catch(...){continue;}
3048
3049                                 // If this is a SIF file, then we need to do things slightly differently
3050                                 if(ext=="sketch")
3051                                 {
3052                                         if(work_area->load_sketch(filename))
3053                                         {
3054                                                 success=true;
3055                                                 work_area->queue_draw();
3056                                         }
3057                                 }
3058                                 else
3059                                 {
3060                                         if(canvas_interface()->import(filename))
3061                                                 success=true;
3062                                 }
3063
3064                                 continue;
3065                         }
3066                 } // END of "text/plain"
3067         }
3068         else
3069                 ui_interface_->error("Drop failed: bad selection data");
3070
3071         // Finish the drag
3072         context->drag_finish(success, false, time);
3073 }
3074
3075 void
3076 CanvasView::on_keyframe_add_pressed()
3077 {
3078         synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_add"));
3079
3080         if(!action)
3081         {
3082                 ui_interface_->error("I am unable to find the appropriate action");
3083                 return;
3084         }
3085
3086         action->set_param("canvas",get_canvas());
3087         action->set_param("canvas_interface",canvas_interface());
3088         action->set_param("keyframe",Keyframe(get_time()));
3089
3090         canvas_interface()->get_instance()->perform_action(action);
3091 }
3092
3093 void
3094 CanvasView::on_keyframe_duplicate_pressed()
3095 {
3096         const KeyframeTreeStore::Model model;
3097         const Gtk::TreeRow row(*keyframe_tree->get_selection()->get_selected());
3098         Keyframe keyframe;
3099         if(!row)
3100         {
3101                 ui_interface_->error("I am unable to duplicate the keyframe");
3102                 return;
3103         }
3104         keyframe=row[model.keyframe];
3105
3106         synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_duplicate"));
3107
3108         if(!action)
3109         {
3110                 ui_interface_->error("I am unable to find the appropriate action");
3111                 return;
3112         }
3113
3114         action->set_param("canvas",get_canvas());
3115         action->set_param("canvas_interface",canvas_interface());
3116         action->set_param("keyframe",keyframe);
3117         action->set_param("time",get_time());
3118
3119         canvas_interface()->get_instance()->perform_action(action);
3120 }
3121
3122 void
3123 CanvasView::on_keyframe_remove_pressed()
3124 {
3125         const KeyframeTreeStore::Model model;
3126         const Gtk::TreeRow row(*keyframe_tree->get_selection()->get_selected());
3127         Keyframe keyframe;
3128         if(!row)
3129         {
3130                 ui_interface_->error("I am unable to remove the keyframe");
3131                 return;
3132         }
3133         keyframe=row[model.keyframe];
3134
3135         synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_remove"));
3136
3137         if(!action)
3138         {
3139                 ui_interface_->error("I am unable to find the appropriate action");
3140                 return;
3141         }
3142
3143         action->set_param("canvas",get_canvas());
3144         action->set_param("canvas_interface",canvas_interface());
3145         action->set_param("keyframe",keyframe);
3146
3147         canvas_interface()->get_instance()->perform_action(action);
3148 }
3149
3150
3151 void
3152 CanvasView::toggle_duck_mask(Duckmatic::Type type)
3153 {
3154         bool is_currently_on(work_area->get_type_mask()&type);
3155
3156         switch(type)
3157         {
3158         case Duck::TYPE_POSITION:
3159                 if(duck_mask_position)
3160                         duck_mask_position->set_active(!is_currently_on);
3161                 break;
3162
3163         case Duck::TYPE_VERTEX:
3164                 if(duck_mask_vertex)
3165                         duck_mask_vertex->set_active(!is_currently_on);
3166                 break;
3167
3168         case Duck::TYPE_TANGENT:
3169                 if(duck_mask_tangent)
3170                         duck_mask_tangent->set_active(!is_currently_on);
3171                 break;
3172
3173         case Duck::TYPE_RADIUS:
3174                 if(duck_mask_radius)
3175                         duck_mask_radius->set_active(!is_currently_on);
3176                 break;
3177
3178         case Duck::TYPE_WIDTH:
3179                 if(duck_mask_width)
3180                         duck_mask_width->set_active(!is_currently_on);
3181                 break;
3182
3183         case Duck::TYPE_ANGLE:
3184                 if(duck_mask_angle)
3185                         duck_mask_angle->set_active(!is_currently_on);
3186                 break;
3187
3188         default:
3189                 synfig::warning("CanvasView::toggle_duck_mask():Unknown duck type!");
3190                 break;
3191         }
3192
3193         if(is_currently_on)
3194                 work_area->set_type_mask(work_area->get_type_mask()-type);
3195         else
3196                 work_area->set_type_mask(work_area->get_type_mask()|type);
3197
3198         work_area->queue_draw();
3199 }
3200
3201
3202 void
3203 CanvasView::image_import()
3204 {
3205         String filename(dirname(get_canvas()->get_file_name()));
3206         if(App::dialog_open_file(_("Import Image"), filename))
3207                 canvas_interface()->import(filename);
3208 }
3209
3210 Smach::event_result
3211 CanvasView::process_event_key(EventKey x)
3212 {
3213         return smach_.process_event(x);
3214 }
3215
3216 void
3217 CanvasView::on_input_device_changed(GdkDevice* device)
3218 {
3219         if(!device)
3220         {
3221                 get_smach().egress();
3222         }
3223         assert(device);
3224
3225         synfigapp::InputDevice::Handle input_device;
3226         input_device=synfigapp::Main::select_input_device(device->name);
3227         App::toolbox->change_state(input_device->get_state());
3228         process_event_key(EVENT_INPUT_DEVICE_CHANGED);
3229 }
3230
3231 void
3232 CanvasView::on_preview_option()
3233 {
3234         Dialog_PreviewOptions *po = dynamic_cast<Dialog_PreviewOptions *>(get_ext_widget("prevoptions"));
3235
3236         Canvas::Handle  canv = get_canvas();
3237
3238         if(canv)
3239         {
3240                 RendDesc &r = canv->rend_desc();
3241                 if(r.get_frame_rate())
3242                 {
3243                         float rate = 1/r.get_frame_rate();
3244                         float beg = r.get_time_start() + r.get_frame_start()*rate;
3245                         float end = r.get_time_start() + r.get_frame_end()*rate;
3246
3247                         if(!po)
3248                         {
3249                                 po = new Dialog_PreviewOptions;
3250                                 po->set_zoom(work_area->get_zoom()/2);
3251                                 po->set_fps(r.get_frame_rate()/2);
3252                                 po->set_begintime(beg);
3253                                 po->set_begin_override(false);
3254                                 po->set_endtime(end);
3255                                 po->set_end_override(false);
3256
3257                                 set_ext_widget("prevoptions",po);
3258                         }
3259                         /*po->set_zoom(work_area->get_zoom()/2);
3260                         po->set_fps(r.get_frame_rate()/2);
3261                         po->set_begintime(beg);
3262                         po->set_begin_override(false);
3263                         po->set_endtime(end);
3264                         po->set_end_override(false);*/
3265
3266                         po->set_global_fps(r.get_frame_rate());
3267                         po->signal_finish().connect(sigc::mem_fun(*this,&CanvasView::on_preview_create));
3268                         po->present();
3269                 }
3270         }
3271 }
3272
3273 void
3274 CanvasView::on_preview_create(const PreviewInfo &info)
3275 {
3276         //set all the options
3277         etl::handle<Preview>    prev = new Preview;
3278
3279         prev->set_canvasview(this);
3280         prev->set_zoom(info.zoom);
3281         prev->set_fps(info.fps);
3282         prev->set_overbegin(info.overbegin);
3283         prev->set_begintime(info.begintime);
3284         prev->set_overend(info.overend);
3285         prev->set_endtime(info.endtime);
3286         prev->set_quality(work_area->get_quality());
3287
3288         //render it out...
3289         prev->render();
3290
3291         Dialog_Preview *pd = preview_dialog.get();
3292         assert(pd);
3293
3294         pd->set_default_size(700,510);
3295         pd->set_preview(prev.get());
3296         pd->present();
3297 }
3298
3299 void
3300 CanvasView::on_audio_option()
3301 {
3302         synfig::warning("Launching Audio Options");
3303         sound_dialog->set_global_fps(get_canvas()->rend_desc().get_frame_rate());
3304         sound_dialog->present();
3305 }
3306
3307 void
3308 CanvasView::on_audio_file_change(const std::string &f)
3309 {
3310         //save in meta data - always even when not valid...
3311         canvas_interface()->set_meta_data("audiofile",f);
3312 }
3313
3314 void
3315 CanvasView::on_audio_offset_change(const Time &t)
3316 {
3317         canvas_interface()->set_meta_data("audiooffset",t.get_string());
3318 }
3319
3320 void
3321 CanvasView::on_audio_file_notify()
3322 {
3323         std::string file(get_canvas()->get_meta_data("audiofile"));
3324         if(!file.c_str()) return;
3325
3326         if(!audio->load(file,dirname(get_canvas()->get_file_name())+string("/")))
3327         {
3328                 if(file != "") synfig::warning("Could not load the file: %s", file.c_str());
3329                 get_canvas()->erase_meta_data("audiofile");
3330                 disp_audio->hide();
3331                 disp_audio->set_profile(etl::handle<AudioProfile>());
3332         }else
3333         {
3334                 //save in canvasview
3335                 synfig::warning("Getting the profile of the music stuff");
3336
3337                 //profile specific stuff for the preview widget
3338                 //similar for other attachments
3339                 Dialog_Preview *pd = preview_dialog.get();
3340                 pd->get_widget().set_audio(audio);
3341
3342                 handle<AudioProfile>    prof = audio->get_profile();
3343
3344                 if(!prof)
3345                 {
3346                         synfig::warning("Agh, I couldn't build the profile captain!");
3347                 }
3348                 pd->get_widget().set_audioprofile(prof);
3349
3350                 disp_audio->set_profile(audio->get_profile());
3351                 disp_audio->show();
3352
3353                 synfig::warning("successfully set the profiles and stuff");
3354         }
3355         disp_audio->queue_draw();
3356 }
3357
3358 void
3359 CanvasView::on_audio_offset_notify()
3360 {
3361         Time t(get_canvas()->get_meta_data("audiooffset"),get_canvas()->rend_desc().get_frame_rate());
3362         audio->set_offset(t);
3363         sound_dialog->set_offset(t);
3364         disp_audio->queue_draw();
3365
3366         synfig::info("CanvasView::on_audio_offset_notify(): offset time set to %s",t.get_string(get_canvas()->rend_desc().get_frame_rate()).c_str());
3367 }
3368
3369 void
3370 CanvasView::play_audio(float t)
3371 {
3372         if(audio.get())
3373         {
3374                 synfig::info("Playing audio at %f s",t);
3375                 audio->play(t);
3376         }
3377 }
3378
3379 void
3380 CanvasView::stop_audio()
3381 {
3382         if(audio.get())
3383         {
3384                 audio->stop();
3385         }
3386 }
3387
3388 bool
3389 CanvasView::on_audio_scrub()
3390 {
3391         disp_audio->draw();
3392         return true;
3393 }
3394
3395
3396
3397 Glib::RefPtr<Glib::ObjectBase>
3398 CanvasView::get_ref_obj(const synfig::String& x)
3399 {
3400         return ref_obj_book_[x];
3401 }
3402
3403 Glib::RefPtr<const Glib::ObjectBase>
3404 CanvasView::get_ref_obj(const synfig::String& x)const
3405 {
3406         return ref_obj_book_.find(x)->second;
3407 }
3408
3409 void
3410 CanvasView::set_ref_obj(const synfig::String& x, Glib::RefPtr<Glib::ObjectBase> y)
3411 {
3412         ref_obj_book_[x]=y;
3413 }
3414
3415 Glib::RefPtr<Gtk::TreeModel>
3416 CanvasView::get_tree_model(const synfig::String& x)
3417 {
3418         return Glib::RefPtr<Gtk::TreeModel>::cast_dynamic(ref_obj_book_["_tree_model_"+x]);
3419 }
3420
3421 Glib::RefPtr<const Gtk::TreeModel>
3422 CanvasView::get_tree_model(const synfig::String& x)const
3423 {
3424         return Glib::RefPtr<Gtk::TreeModel>::cast_dynamic(ref_obj_book_.find("_tree_model_"+x)->second);
3425 }
3426
3427 void
3428 CanvasView::set_tree_model(const synfig::String& x, Glib::RefPtr<Gtk::TreeModel> y)
3429 {
3430         ref_obj_book_["_tree_model_"+x]=Glib::RefPtr<Glib::ObjectBase>::cast_static(y);
3431 }
3432
3433 Gtk::Widget*
3434 CanvasView::get_ext_widget(const synfig::String& x)
3435 {
3436         return ext_widget_book_[x];
3437 }
3438
3439 void
3440 CanvasView::set_ext_widget(const synfig::String& x, Gtk::Widget* y)
3441 {
3442         ext_widget_book_[x]=y;
3443         if(x=="layers_cmp")
3444         {
3445                 layer_tree=dynamic_cast<LayerTree*>(y);
3446
3447                 layer_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_LAYER_SELECTION_CHANGED));
3448                 layer_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
3449                 layer_tree->signal_layer_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_layer_user_click));
3450                 layer_tree->signal_param_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
3451                 layer_tree->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked));
3452         }
3453         if(x=="children")
3454         {
3455                 children_tree=dynamic_cast<ChildrenTree*>(y);
3456                 if(children_tree)children_tree->signal_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
3457                 if(children_tree)children_tree->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked));
3458                 if(children_tree)children_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
3459         }
3460         if(x=="keyframes")
3461                 keyframe_tree=dynamic_cast<KeyframeTree*>(y);
3462 }
3463
3464 static bool _close_instance(etl::handle<Instance> instance)
3465 {
3466         etl::handle<Instance> argh(instance);
3467         instance->safe_close();
3468         synfig::info("closed");
3469         return false;
3470 }
3471
3472 bool
3473 CanvasView::on_delete_event(GdkEventAny* event)
3474 {
3475         if(get_instance()->get_visible_canvases()==1)
3476         {
3477                 // Schedule a close to occur in a few moments
3478                 Glib::signal_timeout().connect(
3479                         sigc::bind(
3480                                 sigc::ptr_fun(_close_instance),
3481                                 (etl::handle<Instance>)get_instance()
3482                         )
3483                         ,250
3484                 );
3485         }
3486         if(event)
3487                 return Gtk::Window::on_delete_event(event);
3488
3489         return true;
3490 }