source: synfigstudio/trunk/fuentes/src/gui/canvasview.cpp @ 481

Last change on this file since 481 was 481, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 136.5 KB
Line 
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**      Copyright (c) 2007, 2008 Chris Moore
10**      Copyright (c) 2009, 2011, 2012 Carlos López
11**      Copyright (c) 2009, 2011 Nikita Kitaev
12**      Copyright (c) 2012 Konstantin Dmitriev
13**
14**      This package is free software; you can redistribute it and/or
15**      modify it under the terms of the GNU General Public License as
16**      published by the Free Software Foundation; either version 2 of
17**      the License, or (at your option) any later version.
18**
19**      This package is distributed in the hope that it will be useful,
20**      but WITHOUT ANY WARRANTY; without even the implied warranty of
21**      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22**      General Public License for more details.
23**      \endlegal
24*/
25/* ========================================================================= */
26
27/* === H E A D E R S ======================================================= */
28
29#ifdef USING_PCH
30#       include "pch.h"
31#else
32#ifdef HAVE_CONFIG_H
33#       include <config.h>
34#endif
35
36#include <sigc++/sigc++.h>
37
38#include <sstream>
39#include <algorithm>
40#include <math.h>
41
42#include <gtkmm/paned.h>
43#include <gtkmm/scale.h>
44#include <gtkmm/dialog.h>
45#include <gtkmm/messagedialog.h>
46#include <gtkmm/treemodelsort.h>
47#include <gtkmm/button.h>
48#include <gtkmm/buttonbox.h>
49#include <gtkmm/separator.h>
50#include <gtkmm/eventbox.h>
51#include <gtkmm/label.h>
52#include <gtkmm/box.h>
53#include <gtkmm/menu.h>
54#include <gtkmm/menuitem.h>
55#include <gtkmm/imagemenuitem.h>
56#include <gtkmm/separatormenuitem.h>
57#include <gtkmm/toolitem.h>
58#include <gtkmm/toolbutton.h>
59#include <gtkmm/toggletoolbutton.h>
60#include <gtkmm/separatortoolitem.h>
61#include <gtkmm/menutoolbutton.h>
62
63#include <glibmm/uriutils.h>
64#include <glibmm/convert.h>
65
66#include <gtk/gtk.h>
67
68#include <gdk/gdk.h>
69
70#include <synfig/valuenodes/valuenode_reference.h>
71#include <synfig/valuenodes/valuenode_subtract.h>
72#include <synfig/valuenodes/valuenode_linear.h>
73#include <synfig/valuenodes/valuenode_timedswap.h>
74#include <synfig/valuenodes/valuenode_scale.h>
75#include <synfig/valuenodes/valuenode_range.h>
76#include <synfig/valuenodes/valuenode_dynamiclist.h>
77#include <synfig/valuenodes/valuenode_twotone.h>
78#include <synfig/valuenodes/valuenode_stripes.h>
79#include <synfig/valuenodes/valuenode_blinecalctangent.h>
80#include <synfig/valuenodes/valuenode_blinecalcvertex.h>
81#include <synfig/valuenodes/valuenode_blinecalcwidth.h>
82#include <synfig/valuenodes/valuenode_bline.h>
83#include <synfig/valuenodes/valuenode_bone.h>
84#include <synfig/layer.h>
85#include <synfig/layers/layer_pastecanvas.h>
86#include <synfig/context.h>
87
88#include <synfigapp/uimanager.h>
89#include <synfigapp/canvasinterface.h>
90#include <synfigapp/selectionmanager.h>
91//#include <synfigapp/action_setwaypoint.h>
92//#include <synfigapp/action_deletewaypoint.h>
93
94#include "canvasview.h"
95#include "instance.h"
96#include "app.h"
97#include "cellrenderer/cellrenderer_value.h"
98#include "cellrenderer/cellrenderer_timetrack.h"
99#include "workarea.h"
100#include "dialogs/dialog_color.h"
101#include "eventkey.h"
102
103#include "states/state_polygon.h"
104#include "states/state_bline.h"
105#include "states/state_normal.h"
106#include "states/state_eyedrop.h"
107
108#include "ducktransform_scale.h"
109#include "ducktransform_translate.h"
110#include "ducktransform_rotate.h"
111
112#include "event_mouse.h"
113#include "event_layerclick.h"
114
115#include "mainwindow.h"
116#include "docks/dockmanager.h"
117#include "docks/dockbook.h"
118#include "docks/dock_toolbox.h"
119
120#include "dialogs/dialog_preview.h"
121#include "dialogs/dialog_soundselect.h"
122
123#include "preview.h"
124#include "audiocontainer.h"
125#include "widgets/widget_timeslider.h"
126#include "widgets/widget_enum.h"
127#include "dials/keyframedial.h"
128#include "dials/jackdial.h"
129
130#include <synfigapp/main.h>
131#include <synfigapp/inputdevice.h>
132
133#include <pangomm.h>
134
135#include "general.h"
136
137#endif
138
139/* === U S I N G =========================================================== */
140
141using namespace std;
142using namespace etl;
143using namespace synfig;
144using namespace studio;
145using namespace sigc;
146
147/* === M A C R O S ========================================================= */
148
149#define DEFAULT_TIME_WINDOW_SIZE                (10.0)
150
151#ifndef SMALL_BUTTON
152#define SMALL_BUTTON(button,stockid,tooltip)    \
153        button = manage(new class Gtk::Button());       \
154        icon=manage(new Gtk::Image(Gtk::StockID(stockid),iconsize));    \
155        button->add(*icon);     \
156        button->set_tooltip_text(tooltip);\
157        icon->set_padding(0,0);\
158        icon->show();   \
159        button->set_relief(Gtk::RELIEF_NONE); \
160        button->show()
161#endif
162
163#ifndef NORMAL_BUTTON
164#define NORMAL_BUTTON(button,stockid,tooltip)   \
165        button = manage(new class Gtk::Button());       \
166        icon=manage(new Gtk::Image(Gtk::StockID(stockid),Gtk::ICON_SIZE_BUTTON));       \
167        button->add(*icon);     \
168        button->set_tooltip_text(tooltip);\
169        icon->set_padding(0,0);\
170        icon->show();   \
171        /*button->set_relief(Gtk::RELIEF_NONE);*/ \
172        button->show()
173#endif
174
175#define NEW_SMALL_BUTTON(x,y,z) Gtk::Button *SMALL_BUTTON(x,y,z)
176
177#define NOT_IMPLEMENTED_SLOT sigc::mem_fun(*reinterpret_cast<studio::CanvasViewUIInterface*>(get_ui_interface().get()),&studio::CanvasViewUIInterface::not_implemented)
178
179#define SLOT_EVENT(x)   sigc::hide_return(sigc::bind(sigc::mem_fun(*this,&studio::CanvasView::process_event_key),x))
180
181/* === C L A S S E S ======================================================= */
182
183class studio::UniversalScrubber
184{
185        CanvasView *canvas_view;
186
187        bool            scrubbing;
188        etl::clock      scrub_timer;
189
190        sigc::connection end_scrub_connection;
191public:
192        UniversalScrubber(CanvasView *canvas_view):
193                canvas_view(canvas_view),
194                scrubbing(false)
195        {
196                canvas_view->canvas_interface()->signal_time_changed().connect(
197                        sigc::mem_fun(*this,&studio::UniversalScrubber::on_time_changed)
198                );
199        }
200
201        ~UniversalScrubber()
202        {
203                end_scrub_connection.disconnect();
204        }
205
206        void on_time_changed()
207        {
208                // Make sure we are changing the time quickly
209                // before we enable scrubbing
210                if(!scrubbing && scrub_timer()>1)
211                {
212                        scrub_timer.reset();
213                        return;
214                }
215
216                // If we aren't scrubbing already, enable it
217                if(!scrubbing)
218                {
219                        scrubbing=true;
220                        audio_container()->start_scrubbing(canvas_view->get_time());
221                }
222
223                // Reset the scrubber ender
224                end_scrub_connection.disconnect();
225                end_scrub_connection=Glib::signal_timeout().connect(
226                        sigc::bind_return(
227                                sigc::mem_fun(*this,&UniversalScrubber::end_of_scrubbing),
228                                false
229                        ),
230                        1000
231                );
232
233                // Scrub!
234                audio_container()->scrub(canvas_view->get_time());
235
236                scrub_timer.reset();
237        }
238
239        void end_of_scrubbing()
240        {
241                scrubbing=false;
242                audio_container()->stop_scrubbing();
243                scrub_timer.reset();
244        }
245
246        handle<AudioContainer> audio_container()
247        {
248                assert(canvas_view->audio);
249                return canvas_view->audio;
250        }
251};
252
253class studio::CanvasViewUIInterface : public synfigapp::UIInterface
254{
255        CanvasView *view;
256
257public:
258
259        CanvasViewUIInterface(CanvasView *view):
260                view(view)
261        {
262                view->statusbar->push(_("Idle"));
263        }
264
265        ~CanvasViewUIInterface()
266        {
267                //view->statusbar->pop();
268                //view->progressbar->set_fraction(0);
269        }
270
271        virtual Response confirmation(
272                        const std::string &message,
273                        const std::string &details,
274                        const std::string &cancel,
275                        const std::string &confirm,
276                        Response dflt = RESPONSE_OK
277        )
278        {
279                view->present();
280                //while(studio::App::events_pending())studio::App::iteration(false);
281                Gtk::MessageDialog dialog(
282                        *App::main_window,
283                        message,
284                        false,
285                        Gtk::MESSAGE_WARNING,
286                        Gtk::BUTTONS_NONE,
287                        true
288                );
289
290                if (! details.empty())
291                        dialog.set_secondary_text(details);
292
293                dialog.add_button(cancel, RESPONSE_CANCEL);
294                dialog.add_button(confirm, RESPONSE_OK);
295                dialog.set_default_response(dflt);
296
297                dialog.show_all();
298                return (Response) dialog.run();
299        }
300
301
302        virtual Response yes_no_cancel(
303                                const std::string &message,
304                                const std::string &details,
305                                const std::string &button1,
306                                const std::string &button2,
307                                const std::string &button3,
308                                Response dflt=RESPONSE_YES
309        )
310        {
311                view->present();
312                //while(studio::App::events_pending())studio::App::iteration(false);
313                Gtk::MessageDialog dialog(
314                        *App::main_window,
315                        message,
316                        false,
317                        Gtk::MESSAGE_QUESTION,
318                        Gtk::BUTTONS_NONE,
319                        true
320                );
321
322                dialog.set_secondary_text(details);
323                dialog.add_button(button1, RESPONSE_NO);
324                dialog.add_button(button2, RESPONSE_CANCEL);
325                dialog.add_button(button3, RESPONSE_YES);
326
327                dialog.set_default_response(dflt);
328                dialog.show();
329                return (Response)dialog.run();
330        }
331
332
333        virtual bool
334        task(const std::string &task)
335        {
336                if(!view->is_playing_)
337                {
338                        view->statusbar->pop();
339                        view->statusbar->push(task);
340                }
341                //while(studio::App::events_pending())studio::App::iteration(false);
342                if(view->cancel){return false;}
343                return true;
344        }
345
346        virtual bool
347        error(const std::string &err)
348        {
349                view->statusbar->push(_("ERROR"));
350
351                // If we are in the process of canceling,
352                // then just go ahead and return false --
353                // don't bother displaying a dialog
354                if(view->cancel)return false;
355                Gtk::MessageDialog dialog(*App::main_window, err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
356                dialog.show();
357                dialog.run();
358                view->statusbar->pop();
359                return true;
360        }
361
362        virtual bool
363        warning(const std::string &err)
364        {
365                view->statusbar->pop();
366                view->statusbar->push(err);
367
368                //while(studio::App::events_pending())studio::App::iteration(false);
369                if(view->cancel)return false;
370                return true;
371        }
372
373        virtual bool
374        amount_complete(int current, int total)
375        {
376                if(!view->is_playing_)
377                {
378                        if(!view->working_depth)
379                        {
380                                if(current)
381                                        view->stopbutton->set_sensitive(true);
382                                else
383                                        view->stopbutton->set_sensitive(false);
384                        }
385                        float x((float)current/(float)total);
386                        if(x<0)x=0;
387                        else if(x>1)x=1;
388                        view->progressbar->set_fraction(x);
389                }
390                //while(studio::App::events_pending())studio::App::iteration(false);
391                if(view->cancel){/*view->cancel=false;*/return false;}
392                return true;
393        }
394
395        void
396        not_implemented()
397        {
398                error(_("Feature not yet implemented"));
399        }
400};
401
402class studio::CanvasViewSelectionManager : public synfigapp::SelectionManager
403{
404        CanvasView *view;
405        CanvasView::LayerTreeModel layer_tree_model;
406        CanvasView::ChildrenTreeModel children_tree_model;
407
408public:
409        CanvasViewSelectionManager(CanvasView *view): view(view) { }
410
411private:
412        void _set_selected_layer(const synfig::Layer::Handle &layer)
413        {
414                view->layer_tree->select_layer(layer);
415/*
416                // Don't change the selection while we are busy
417                // I cannot remember exactly why I put this here...
418                // It musta been for some reason, but I cannot recall.
419                //if(App::Busy::count)
420                //      return;
421
422                if(view->layer_tree->get_selection()->get_selected())
423                {
424                        const Gtk::TreeRow row = *(view->layer_tree->get_selection()->get_selected());
425
426                        // Don't do anything if that layer is already selected
427                        if(layer == static_cast<synfig::Layer::Handle>(row[layer_tree_model.layer]))
428                                return;
429                }
430                Gtk::TreeModel::Children::iterator iter;
431                if(view->layer_tree_store()->find_layer_row(layer,iter))
432                {
433                        Gtk::TreePath path(iter);
434                        for(int i=path.get_depth();i;i--)
435                        {
436                                int j;
437                                path=Gtk::TreePath(iter);
438                                for(j=i;j;j--)
439                                        path.up();
440                                view->layer_tree->get_tree_view().expand_row(path,false);
441                        }
442                        view->layer_tree->get_tree_view().scroll_to_row(Gtk::TreePath(iter));
443                        view->layer_tree->get_selection()->select(iter);
444                }
445*/
446        }
447public:
448
449        //! Returns the number of layers selected.
450        virtual int get_selected_layer_count()const
451        {
452                return get_selected_layers().size();
453        }
454
455        //! Returns a list of the currently selected layers.
456        virtual LayerList get_selected_layers()const
457        {
458//              assert(view->layer_tree);
459
460                if(!view->layer_tree) { synfig::error("%s:%d canvas_view.layer_tree not defined!?", __FILE__, __LINE__); return LayerList(); }
461                return view->layer_tree->get_selected_layers();
462        }
463
464        //! Returns the first layer selected or an empty handle if none are selected.
465        virtual synfig::Layer::Handle get_selected_layer()const
466        {
467//              assert(view->layer_tree);
468
469                if(!view->layer_tree) { synfig::error("%s:%d canvas_view.layer_tree not defined!?", __FILE__, __LINE__); return 0; }
470                return view->layer_tree->get_selected_layer();
471        }
472
473        //! Sets which layers should be selected
474        virtual void set_selected_layers(const LayerList &layer_list)
475        {
476//              assert(view->layer_tree);
477
478                if(!view->layer_tree) { synfig::error("%s:%d canvas_view.layer_tree not defined!?", __FILE__, __LINE__); return; }
479                view->layer_tree->select_layers(layer_list);
480                //view->get_smach().process_event(EVENT_REFRESH_DUCKS);
481
482                //view->queue_rebuild_ducks();
483        }
484
485        //! Sets which layer should be selected.
486        virtual void set_selected_layer(const synfig::Layer::Handle &layer)
487        {
488//              assert(view->layer_tree);
489
490                if(!view->layer_tree) { synfig::error("canvas_view.layer_tree not defined!?"); return; }
491                view->layer_tree->select_layer(layer);
492                //view->queue_rebuild_ducks();
493        }
494
495        //! Clears the layer selection list
496        virtual void clear_selected_layers()
497        {
498                if(!view->layer_tree) return;
499                view->layer_tree->clear_selected_layers();
500        }
501
502        //! Returns the number of value_nodes selected.
503        virtual int get_selected_children_count()const
504        {
505                return get_selected_children().size();
506        }
507
508        static inline void __child_grabber(const Gtk::TreeModel::iterator& iter, ChildrenList* ret)
509        {
510                const CanvasView::ChildrenTreeModel children_tree_model;
511                synfigapp::ValueDesc value_desc((*iter)[children_tree_model.value_desc]);
512                if(value_desc)
513                        ret->push_back(value_desc);
514        }
515
516        //! Returns a list of the currently selected value_nodes.
517        virtual ChildrenList get_selected_children()const
518        {
519                if(!view->children_tree) return ChildrenList();
520
521                Glib::RefPtr<Gtk::TreeSelection> selection=view->children_tree->get_selection();
522
523                if(!selection)
524                        return ChildrenList();
525
526                ChildrenList ret;
527
528                selection->selected_foreach_iter(
529                        sigc::bind(
530                                sigc::ptr_fun(
531                                        &studio::CanvasViewSelectionManager::__child_grabber
532                                ),
533                                &ret
534                        )
535                );
536
537                /*
538                Gtk::TreeModel::Children::iterator iter(view->children_tree_store()->children().begin());
539                iter++;
540                Gtk::TreeModel::Children children = iter->children();
541                for(iter = children.begin(); iter != children.end(); ++iter)
542                {
543                        Gtk::TreeModel::Row row = *iter;
544                        if(selection->is_selected(row))
545                                ret.push_back((synfigapp::ValueDesc)row[children_tree_model.value_desc]);
546                }
547                */
548                return ret;
549        }
550
551        //! Returns the first value_node selected or an empty handle if none are selected.
552        virtual ChildrenList::value_type get_selected_child()const
553        {
554                if(!view->children_tree) return ChildrenList::value_type();
555
556                ChildrenList children(get_selected_children());
557
558                if(children.empty())
559                        return ChildrenList::value_type();
560
561                return children.front();
562        }
563
564        //! Sets which value_nodes should be selected
565        virtual void set_selected_children(const ChildrenList &/*children_list*/)
566        {
567                return;
568        }
569
570        //! Sets which value_node should be selected. Empty handle if none.
571        virtual void set_selected_child(const ChildrenList::value_type &/*child*/)
572        {
573                return;
574        }
575
576        //! Clears the value_node selection list
577        virtual void clear_selected_children()
578        {
579                return;
580        }
581
582        int get_selected_layer_parameter_count()const
583        {
584                return get_selected_layer_parameters().size();
585        }
586
587        LayerParamList get_selected_layer_parameters()const
588        {
589                if(!view->layer_tree) return LayerParamList();
590
591                Glib::RefPtr<Gtk::TreeSelection> selection=view->layer_tree->get_selection();
592
593                if(!selection)
594                        return LayerParamList();
595
596                LayerParamList ret;
597
598                Gtk::TreeModel::Children children = const_cast<CanvasView*>(view)->layer_tree_store()->children();
599                Gtk::TreeModel::Children::iterator iter;
600                for(iter = children.begin(); iter != children.end(); ++iter)
601                {
602                        Gtk::TreeModel::Row row = *iter;
603                        Gtk::TreeModel::Children::iterator iter;
604                        for(iter=row.children().begin();iter!=row.children().end();iter++)
605                        {
606                                Gtk::TreeModel::Row row = *iter;
607                                if(selection->is_selected(row))
608                                        ret.push_back(LayerParam(row[layer_tree_model.layer],(Glib::ustring)row[layer_tree_model.id]));
609                        }
610                }
611                return ret;
612        }
613
614        LayerParam get_selected_layer_parameter() const
615        {
616                if(!view->layer_tree) return LayerParam();
617                return get_selected_layer_parameters().front();
618        }
619
620        void set_selected_layer_parameters(const LayerParamList &/*layer_param_list*/)
621        {
622                return;
623        }
624
625        void set_selected_layer_param(const LayerParam &/*layer_param*/)
626        {
627                return;
628        }
629
630        void clear_selected_layer_parameters()
631        {
632                return;
633        }
634
635}; // END of class SelectionManager
636
637CanvasView::IsWorking::IsWorking(CanvasView &canvas_view_):
638        canvas_view_(canvas_view_)
639{
640        if(!canvas_view_.working_depth)
641                canvas_view_.stopbutton->set_sensitive(true);
642        canvas_view_.working_depth++;
643        canvas_view_.cancel=false;
644}
645
646CanvasView::IsWorking::~IsWorking()
647{
648        canvas_view_.working_depth--;
649        if(!canvas_view_.working_depth)
650                canvas_view_.stopbutton->set_sensitive(false);
651}
652
653CanvasView::IsWorking::operator bool()const
654{
655        if(canvas_view_.cancel)
656                return false;
657        return true;
658}
659
660/* === M E T H O D S ======================================================= */
661
662CanvasView::ActivationIndex CanvasView::ActivationIndex::last__;
663
664CanvasView::CanvasView(etl::loose_handle<Instance> instance,etl::handle<synfigapp::CanvasInterface> canvas_interface_):
665        Dockable(synfig::GUID().get_string(),_("Canvas View")),
666        activation_index_       (true),
667        smach_                                  (this),
668        instance_                               (instance),
669        canvas_interface_               (canvas_interface_),
670        context_params_                 (true),
671        //layer_tree_store_             (LayerTreeStore::create(canvas_interface_)),
672        //children_tree_store_  (ChildrenTreeStore::create(canvas_interface_)),
673        //keyframe_tree_store_  (KeyframeTreeStore::create(canvas_interface_)),
674        time_adjustment_                (Gtk::Adjustment::create(0,0,25,0,0,0)),
675        time_window_adjustment_ (new studio::Adjust_Window(0,0,25,0,0,0)),
676        statusbar                               (manage(new class Gtk::Statusbar())),
677        jackbutton              (NULL),
678        offset_widget           (NULL),
679        toggleducksdial         (Gtk::IconSize::from_name("synfig-small_icon_16x16")),
680        resolutiondial          (Gtk::IconSize::from_name("synfig-small_icon_16x16")),
681        quality_adjustment_             (Gtk::Adjustment::create(8,1,10,1,1,0)),
682        future_onion_adjustment_(Gtk::Adjustment::create(0,0,ONION_SKIN_FUTURE,1,1,0)),
683        past_onion_adjustment_  (Gtk::Adjustment::create(1,0,ONION_SKIN_PAST,1,1,0)),
684
685        timeslider                              (new Widget_Timeslider),
686        widget_kf_list                  (new Widget_Keyframe_List),
687
688        ui_interface_                   (new CanvasViewUIInterface(this)),
689        selection_manager_              (new CanvasViewSelectionManager(this)),
690        is_playing_                             (false),
691
692        jack_enabled                    (false),
693        jack_actual_enabled             (false),
694        jack_locks                              (0),
695        jack_enabled_in_preview (false),
696#ifdef WITH_JACK
697        jack_client                             (NULL),
698        jack_synchronizing              (true),
699        jack_is_playing                 (false),
700        jack_time                               (0),
701        toggling_jack                   (false),
702#endif
703
704        working_depth                   (0),
705        cancel                                  (false),
706
707        canvas_properties               (*App::main_window,canvas_interface_),
708        canvas_options                  (*App::main_window,this),
709        render_settings                 (*App::main_window,canvas_interface_),
710        waypoint_dialog                 (*App::main_window,canvas_interface_->get_canvas()),
711        keyframe_dialog                 (*App::main_window,canvas_interface_),
712        preview_dialog                  (new Dialog_Preview),
713        sound_dialog                    (new Dialog_SoundSelect(*App::main_window,canvas_interface_))
714{
715        layer_tree=0;
716        children_tree=0;
717        duck_refresh_flag=true;
718        toggling_ducks_=false;
719        toggling_animate_mode_=false;
720        changing_resolution_=false;
721        updating_quality_=false;
722        toggling_show_grid=false;
723        toggling_snap_grid=false;
724        toggling_onion_skin=false;
725
726        disp_audio = new Widget_Sound();
727
728        //synfig::info("Canvasview: Entered constructor");
729        // Minor hack
730        get_canvas()->set_time(0);
731        //layer_tree_store_->rebuild();
732
733        // Set up the UI and Selection managers
734        canvas_interface()->set_ui_interface(get_ui_interface());
735        canvas_interface()->set_selection_manager(get_selection_manager());
736        rebuild_ducks_queued=false;
737
738        //notebook=manage(new class Gtk::Notebook());
739        //Gtk::VPaned *vpaned = manage(new class Gtk::VPaned());
740        //vpaned->pack1(*create_work_area(), Gtk::EXPAND|Gtk::SHRINK);
741        //vpaned->pack2(*notebook, Gtk::SHRINK);
742        //vpaned->show_all();
743
744        //notebook->show();
745
746        //notebook->append_page(*create_layer_tree(),_("Layers"));
747        //notebook->append_page(*create_children_tree(),_("Children"));
748        //notebook->append_page(*create_keyframe_tree(),_("Keyframes"));
749
750        //synfig::info("Canvasview: Before big chunk of allocation and tabling stuff");
751        //create all allocated stuff for this canvas
752        audio = new AudioContainer();
753       
754        Gtk::Alignment *space = Gtk::manage(new Gtk::Alignment());
755        space->set_size_request(4,4);
756        space->show();
757
758        Gtk::Table *layout_table= manage(new class Gtk::Table(4, 1, false));
759        //layout_table->attach(*vpaned, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
760        layout_table->attach(*create_work_area(),   0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
761        layout_table->attach(*space, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
762        init_menus();
763        layout_table->attach(*create_display_bar(), 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
764        //layout_table->attach(*App::ui_manager()->get_widget("/menu-main"), 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
765        layout_table->attach(*create_time_bar(),    0, 1, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
766        //layout_table->attach(*create_status_bar(),  0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
767
768        update_title();
769
770        layout_table->show();
771
772        Gtk::EventBox *event_box = manage(new Gtk::EventBox());
773        //event_box->set_above_child(true);
774        event_box->add(*layout_table);
775        event_box->show();
776        event_box->signal_button_press_event().connect(sigc::mem_fun(*this,&studio::CanvasView::on_button_press_event));
777
778        set_use_scrolled(false);
779        add(*event_box);
780
781        //set_transient_for(*App::toolbox);
782
783        smach_.set_default_state(&state_normal);
784
785        //synfig::info("Canvasview: Before Signals");
786        /*
787 --     ** -- Signals -------------------------------------------------------------
788        */
789
790        canvas_interface()->signal_dirty_preview().connect(sigc::mem_fun(*this,&studio::CanvasView::on_dirty_preview));
791        canvas_interface()->signal_mode_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_mode_changed));
792
793        canvas_interface()->signal_time_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_time_changed));
794
795        //canvas_interface()->signal_time_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::refresh_tables));
796        canvas_interface()->signal_id_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_id_changed));
797        canvas_interface()->signal_rend_desc_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::refresh_rend_desc));
798        waypoint_dialog.signal_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_waypoint_changed));
799        waypoint_dialog.signal_delete().connect(sigc::mem_fun(*this,&studio::CanvasView::on_waypoint_delete));
800
801        //MODIFIED TIME ADJUSTMENT STUFF....
802        time_window_adjustment()->set_child_adjustment(time_adjustment());
803        time_window_adjustment()->signal_value_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::refresh_time_window));
804        time_adjustment()->signal_value_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::time_was_changed));
805
806        work_area->signal_layer_selected().connect(sigc::mem_fun(*this,&studio::CanvasView::workarea_layer_selected));
807        work_area->signal_input_device_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_input_device_changed));
808        work_area->signal_meta_data_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_meta_data_changed));
809
810        canvas_interface()->signal_canvas_added().connect(
811                sigc::hide(
812                        sigc::mem_fun(*instance,&studio::Instance::refresh_canvas_tree)
813                )
814        );
815        canvas_interface()->signal_canvas_removed().connect(
816                sigc::hide(
817                        sigc::mem_fun(*instance,&studio::Instance::refresh_canvas_tree)
818                )
819        );
820
821        canvas_interface()->signal_layer_param_changed().connect(
822                sigc::hide(
823                        sigc::hide(
824                                SLOT_EVENT(EVENT_REFRESH_DUCKS)
825                        )
826                )
827        );
828
829        canvas_interface()->signal_keyframe_properties().connect(sigc::mem_fun(*this,&studio::CanvasView::show_keyframe_dialog));
830
831        //MUCH TIME STUFF TAKES PLACE IN HERE
832        refresh_rend_desc();
833        refresh_time_window();
834
835        /*! \todo We shouldn't need to do this at construction --
836        **      This should be performed at the first time the window
837        **      becomes visible.
838        */
839        work_area->queue_render_preview();
840
841        std::vector<Gtk::TargetEntry> listTargets;
842        listTargets.push_back( Gtk::TargetEntry("text/uri-list") );
843        listTargets.push_back( Gtk::TargetEntry("text/plain") );
844        listTargets.push_back( Gtk::TargetEntry("STRING") );
845
846        drag_dest_set(listTargets);
847        signal_drag_data_received().connect( sigc::mem_fun(*this, &studio::CanvasView::on_drop_drag_data_received) );
848
849        /*
850        Time length(get_canvas()->rend_desc().get_time_end()-get_canvas()->rend_desc().get_time_start());
851        if(length<10.0)
852        {
853                time_window_adjustment()->set_page_increment(length);
854                time_window_adjustment()->set_page_size(length);
855        }
856        else
857        {
858                time_window_adjustment()->set_page_increment(10.0);
859                time_window_adjustment()->set_page_size(10.0);
860        }
861        */
862
863        //synfig::info("Canvasview: Before Sound Hookup");
864        //load sound info from meta data
865        {
866                //synfig::warning("Should load Audio: %s with %s offset",apath.c_str(),aoffset.c_str());
867
868                on_audio_file_notify(); //redundant setting of the metadata, but oh well, it's no big deal :)
869                on_audio_offset_notify();
870
871                //signal connection - since they are all associated with the canvas view
872
873                //hook in signals for sound options box
874                sound_dialog->signal_file_changed().connect(sigc::mem_fun(*this,&CanvasView::on_audio_file_change));
875                sound_dialog->signal_offset_changed().connect(sigc::mem_fun(*this,&CanvasView::on_audio_offset_change));
876
877                //attach to the preview when it's visible
878                //preview_dialog->get_widget().signal_play().connect(sigc::mem_fun(*this,&CanvasView::play_audio));
879                //preview_dialog->get_widget().signal_stop().connect(sigc::mem_fun(*this,&CanvasView::stop_audio));
880
881                //hook to metadata signals
882                get_canvas()->signal_meta_data_changed("audiofile").connect(sigc::mem_fun(*this,&CanvasView::on_audio_file_notify));
883                get_canvas()->signal_meta_data_changed("audiooffset").connect(sigc::mem_fun(*this,&CanvasView::on_audio_offset_notify));
884
885                //universal_scrubber=std::auto_ptr<UniversalScrubber>(new UniversalScrubber(this));
886        }
887
888        //synfig::info("Canvasview: Before Final time set up");
889        //MORE TIME STUFF
890        time_window_adjustment()->set_value(get_canvas()->rend_desc().get_time_start());
891        time_window_adjustment()->value_changed();
892
893        refresh_rend_desc();
894        hide_tables();
895
896        on_time_changed();
897        show();
898
899        instance->canvas_view_list().push_front(this);
900        instance->signal_canvas_view_created()(this);
901        //synfig::info("Canvasview: Constructor Done");
902
903        if (App::jack_is_locked())
904                jack_lock();
905
906#ifdef WITH_JACK
907        jack_dispatcher.connect(sigc::mem_fun(*this, &CanvasView::on_jack_sync));
908#endif
909
910        App::dock_manager->register_dockable(*this);
911        App::main_window->main_dock_book().add(*this);
912        present();
913        App::set_selected_canvas_view(this);
914}
915
916CanvasView::~CanvasView()
917{
918#ifdef WITH_JACK
919        set_jack_enabled(false);
920#endif
921
922        App::dock_manager->unregister_dockable(*this);
923        signal_deleted()();
924
925        App::ui_manager()->remove_action_group(action_group);
926
927        // Shut down the smach
928        smach_.egress();
929        smach_.set_default_state(0);
930
931        // We want to ensure that the UI_Manager and
932        // the selection manager get destructed right now.
933        ui_interface_.reset();
934        selection_manager_.reset();
935
936        // Delete any external widgets
937        for(;!ext_widget_book_.empty();ext_widget_book_.erase(ext_widget_book_.begin()))
938        {
939                if(ext_widget_book_.begin()->second)
940                        delete ext_widget_book_.begin()->second;
941        }
942
943        //delete preview
944        audio.reset();
945
946        // don't be calling on_dirty_preview once this object has been deleted;
947        // this was causing a crash before
948        canvas_interface()->signal_dirty_preview().clear();
949
950        if (getenv("SYNFIG_DEBUG_DESTRUCTORS"))
951                synfig::info("CanvasView::~CanvasView(): Deleted");
952}
953
954void CanvasView::save_all()
955{
956        std::list<etl::handle<Instance> >::iterator iter;
957        for(iter=App::instance_list.begin();iter!=App::instance_list.end();iter++)
958                (*iter)->save();
959}
960
961void CanvasView::activate()
962{
963        activation_index_.activate();
964        get_smach().process_event(EVENT_REFRESH_TOOL_OPTIONS);
965        App::ui_manager()->insert_action_group(action_group);
966        update_title();
967        present();
968}
969
970void CanvasView::deactivate()
971{
972        get_smach().process_event(EVENT_YIELD_TOOL_OPTIONS);
973        App::ui_manager()->remove_action_group(action_group);
974        update_title();
975}
976
977void CanvasView::present()
978{
979        Dockable::present();
980        // If hided by CanvasView::close_view, time to come back to the show
981        if(!get_visible())show();
982        update_title();
983}
984
985void CanvasView::jack_lock()
986{
987        ++jack_locks;
988#ifdef WITH_JACK
989        if (jack_locks == 1)
990                set_jack_enabled(get_jack_enabled());
991#endif
992}
993
994void CanvasView::jack_unlock()
995{
996        --jack_locks;
997        assert(jack_locks >= 0);
998#ifdef WITH_JACK
999        if (jack_locks == 0)
1000                set_jack_enabled(get_jack_enabled());
1001#endif
1002}
1003
1004#ifdef WITH_JACK
1005void CanvasView::set_jack_enabled(bool value)
1006{
1007        bool actual_value = value && !jack_is_locked();
1008        if (jack_actual_enabled != actual_value) {
1009                jack_actual_enabled = actual_value;
1010                if (jack_actual_enabled)
1011                {
1012                        // initialize jack
1013                        stop();
1014                        jack_client = jack_client_open("synfigstudiocanvas", JackNullOption, 0);
1015                        jack_set_sync_callback(jack_client, jack_sync_callback, this);
1016                        if (jack_activate(jack_client) != 0)
1017                        {
1018                                jack_client_close(jack_client);
1019                                jack_client = NULL;
1020                                jack_actual_enabled = false;
1021                                // make conditions to update button
1022                                jack_enabled = true;
1023                                value = false;
1024                        }
1025                }
1026                else
1027                {
1028                        // deinitialize jack
1029                        jack_deactivate(jack_client);
1030                        jack_client_close(jack_client);
1031                        jack_client = NULL;
1032                }
1033
1034                jackbutton->set_sensitive(!jack_is_locked());
1035        }
1036
1037        if (jack_enabled != value)
1038        {
1039                jack_enabled = value;
1040
1041                Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon_16x16");
1042                Gtk::Image *icon;
1043                offset_widget = jackdial->get_offsetwidget();
1044
1045                if (jackbutton->get_active() != jack_enabled)
1046                        jackbutton->set_active(jack_enabled);
1047
1048                if (jack_enabled)
1049                {
1050                        icon = manage(new Gtk::Image(Gtk::StockID("synfig-jack"),iconsize));
1051                        jackbutton->remove();
1052                        jackbutton->add(*icon);
1053                        jackbutton->set_tooltip_text(_("Disable JACK"));
1054                        icon->set_padding(0,0);
1055                        icon->show();
1056                        offset_widget->show();
1057                }
1058                else
1059                {
1060                        icon = manage(new Gtk::Image(Gtk::StockID("synfig-jack"),iconsize));
1061                        jackbutton->remove();
1062                        jackbutton->add(*icon);
1063                        jackbutton->set_tooltip_text(_("Enable JACK"));
1064                        icon->set_padding(0,0);
1065                        icon->show();
1066                        offset_widget->hide();
1067                }
1068        }
1069}
1070#endif
1071
1072std::list<int>&
1073CanvasView::get_pixel_sizes()
1074{
1075        // prime factors of 120 are 2, 2, 2, 3, 5 - see TILE_SIZE in synfig-core/trunk/src/synfig/target_tile.h
1076        static int pixel_size_array[] = {2,3,4,5,6,8,10,12,15,20,24,30,40,60,120};
1077        static list<int> pixel_sizes = list<int>(pixel_size_array, pixel_size_array + sizeof(pixel_size_array) / sizeof(int));
1078
1079        return pixel_sizes;
1080}
1081
1082Gtk::Widget *
1083CanvasView::create_time_bar()
1084{
1085        //Setup the Time Slider and the Time window scroll
1086        Gtk::HScrollbar *time_window_scroll = manage(new class Gtk::HScrollbar(time_window_adjustment()));
1087        //Gtk::HScrollbar *time_scroll = manage(new class Gtk::HScrollbar(time_adjustment()));
1088        //TIME BAR TEMPORARY POSITION
1089        //Widget_Timeslider *time_scroll = manage(new Widget_Timeslider);
1090        timeslider->set_time_adjustment(time_adjustment());
1091        timeslider->set_bounds_adjustment(time_window_adjustment());
1092        //layout_table->attach(*timeslider, 0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL);
1093        //Setup the keyframe list widget
1094        widget_kf_list->set_time_adjustment(time_adjustment());
1095        widget_kf_list->set_canvas_interface(canvas_interface());
1096        widget_kf_list->show();
1097
1098        time_window_scroll->set_tooltip_text(_("Moves the time window"));
1099        timeslider->set_tooltip_text(_("Changes the current time"));
1100        time_window_scroll->show();
1101        timeslider->show();
1102        //time_window_scroll->set_can_focus(true); // Uncomment this produce bad render of the HScroll
1103        timeslider->set_can_focus(true);
1104        //time_scroll->signal_value_changed().connect(sigc::mem_fun(*work_area, &studio::WorkArea::render_preview_hook));
1105        //time_scroll->set_update_policy(Gtk::UPDATE_DISCONTINUOUS);
1106       
1107        timetrack = manage(new class Gtk::VBox());
1108        timetrack->pack_start(*widget_kf_list);
1109        timetrack->pack_start(*timeslider);
1110        timetrack->pack_start(*time_window_scroll);
1111        timetrack->hide();
1112       
1113        // Interpolation widget
1114        widget_interpolation = manage(new Widget_Enum());
1115        widget_interpolation->set_param_desc(
1116                ParamDesc("interpolation")
1117                        .set_hint("enum")
1118                        .add_enum_value(INTERPOLATION_CLAMPED,"clamped",_("Clamped"))
1119                        .add_enum_value(INTERPOLATION_TCB,"auto",_("TCB"))
1120                        .add_enum_value(INTERPOLATION_CONSTANT,"constant",_("Constant"))
1121                        .add_enum_value(INTERPOLATION_HALT,"ease",_("Ease In/Out"))
1122                        .add_enum_value(INTERPOLATION_LINEAR,"linear",_("Linear"))
1123        );
1124        widget_interpolation->set_icon(0, Gtk::Button().render_icon_pixbuf(Gtk::StockID("synfig-interpolation_type_clamped"), Gtk::ICON_SIZE_MENU));
1125        widget_interpolation->set_icon(1, Gtk::Button().render_icon_pixbuf(Gtk::StockID("synfig-interpolation_type_tcb"), Gtk::ICON_SIZE_MENU));
1126        widget_interpolation->set_icon(2, Gtk::Button().render_icon_pixbuf(Gtk::StockID("synfig-interpolation_type_const"), Gtk::ICON_SIZE_MENU));
1127        widget_interpolation->set_icon(3, Gtk::Button().render_icon_pixbuf(Gtk::StockID("synfig-interpolation_type_ease"), Gtk::ICON_SIZE_MENU));
1128        widget_interpolation->set_icon(4, Gtk::Button().render_icon_pixbuf(Gtk::StockID("synfig-interpolation_type_linear"), Gtk::ICON_SIZE_MENU));
1129        widget_interpolation->set_tooltip_text(_("Default Interpolation"));
1130        widget_interpolation->set_popup_fixed_width(false);
1131        widget_interpolation->set_size_request(120,0);
1132        widget_interpolation->show();
1133        Gtk::Alignment* widget_interpolation_align=manage(new Gtk::Alignment(1, Gtk::ALIGN_CENTER, 0, 0));
1134        widget_interpolation_align->add(*widget_interpolation);
1135        widget_interpolation_align->show();
1136        widget_interpolation_scroll=manage(new class Gtk::ScrolledWindow());
1137        widget_interpolation_scroll->add(*widget_interpolation_align);
1138        widget_interpolation_scroll->show();
1139        widget_interpolation_scroll->set_shadow_type(Gtk::SHADOW_NONE);
1140        widget_interpolation_scroll->set_policy(Gtk::POLICY_ALWAYS,Gtk::POLICY_NEVER);
1141        widget_interpolation_scroll->set_size_request(25,0);
1142        Gtk::Scrollbar* hscroll=widget_interpolation_scroll->get_hscrollbar();
1143        hscroll->hide();
1144       
1145        widget_interpolation->signal_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_interpolation_changed));
1146        widget_interpolation_scroll->add_events(Gdk::POINTER_MOTION_MASK);
1147        widget_interpolation_scroll->signal_event().connect(sigc::bind_return(sigc::mem_fun(*this,&studio::CanvasView::on_interpolation_event),false));
1148
1149        synfigapp::Main::signal_interpolation_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::interpolation_refresh));
1150        synfigapp::Main::set_interpolation(INTERPOLATION_CLAMPED); // Clamped by default.
1151        interpolation_refresh();
1152
1153        //Setup the Animation Mode Button and the Keyframe Lock button
1154        {
1155                Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon_16x16");
1156                Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID("synfig-animate_mode_off"), iconsize));
1157                animatebutton = Gtk::manage(new class Gtk::ToggleButton());
1158                animatebutton->set_tooltip_text(_("Turn on animate editing mode"));
1159                icon->set_padding(0,0);
1160                icon->show();
1161                animatebutton->add(*icon);
1162                animatebutton->signal_toggled().connect(sigc::mem_fun(*this, &studio::CanvasView::toggle_animatebutton));
1163                animatebutton->set_relief(Gtk::RELIEF_NONE);
1164                animatebutton->show();
1165        }
1166       
1167        {
1168                Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon_16x16");
1169                Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID("synfig-timetrack"), iconsize));
1170                timetrackbutton = Gtk::manage(new class Gtk::ToggleButton());
1171                timetrackbutton->set_tooltip_text(_("Toggle timebar"));
1172                icon->set_padding(0,0);
1173                icon->show();
1174                timetrackbutton->add(*icon);
1175                timetrackbutton->signal_toggled().connect(sigc::mem_fun(*this, &studio::CanvasView::toggle_timetrackbutton));
1176                timetrackbutton->set_relief(Gtk::RELIEF_NONE);
1177                timetrackbutton->show();
1178        }
1179
1180        //Setup the audio display
1181        disp_audio->set_size_request(-1,32); //disp_audio->show();
1182        disp_audio->set_time_adjustment(time_adjustment());
1183        disp_audio->signal_start_scrubbing().connect(
1184                sigc::mem_fun(*audio,&AudioContainer::start_scrubbing)
1185        );
1186        disp_audio->signal_scrub().connect(
1187                sigc::mem_fun(*audio,&AudioContainer::scrub)
1188        );
1189        disp_audio->signal_stop_scrubbing().connect(
1190                sigc::mem_fun(*audio,&AudioContainer::stop_scrubbing)
1191        );
1192        //Setup the current time widget
1193        current_time_widget=manage(new Widget_Time);
1194        current_time_widget->set_value(get_time());
1195        current_time_widget->set_fps(get_canvas()->rend_desc().get_frame_rate());
1196        current_time_widget->signal_value_changed().connect(
1197                sigc::mem_fun(*this,&CanvasView::on_current_time_widget_changed)
1198        );
1199        current_time_widget->set_size_request(0,-1); // request horizontal shrink
1200        current_time_widget->set_width_chars(5);
1201        current_time_widget->set_tooltip_text(_("Current time"));
1202        current_time_widget->show();
1203
1204        //Setup the FrameDial widget
1205        framedial = manage(new class FrameDial());
1206        framedial->signal_seek_begin().connect(
1207                        sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time), Time::begin())
1208        );
1209       
1210        framedial->signal_seek_prev_keyframe().connect(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_prev_keyframe));
1211        framedial->signal_seek_prev_frame().connect(sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_frame), -1));
1212        framedial->signal_play().connect(sigc::mem_fun(*this, &studio::CanvasView::on_play_pause_pressed));
1213        framedial->signal_pause().connect(sigc::mem_fun(*this, &studio::CanvasView::on_play_pause_pressed));
1214        framedial->signal_seek_next_frame().connect(sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_frame), 1));
1215        framedial->signal_seek_next_keyframe().connect(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_next_keyframe));
1216        framedial->signal_seek_end().connect(sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time), Time::end()));
1217        framedial->show();
1218
1219        //Setup the KeyFrameDial widget
1220        KeyFrameDial *keyframedial = Gtk::manage(new class KeyFrameDial());
1221        keyframedial->signal_toggle_keyframe_past().connect(sigc::mem_fun(*this, &studio::CanvasView::toggle_past_keyframe_button));
1222        keyframedial->signal_toggle_keyframe_future().connect(sigc::mem_fun(*this, &studio::CanvasView::toggle_future_keyframe_button));
1223        keyframedial->show();
1224        pastkeyframebutton=keyframedial->get_toggle_pastbutton();
1225        futurekeyframebutton=keyframedial->get_toggle_futurebutton();
1226
1227        //Adjust both widgets to be the same as the
1228        int header_height = 0;
1229        if(getenv("SYNFIG_TIMETRACK_HEADER_HEIGHT"))
1230                header_height = atoi(getenv("SYNFIG_TIMETRACK_HEADER_HEIGHT"));
1231        if (header_height < 3)
1232                header_height = 24;
1233        timeslider->set_size_request(-1,header_height-header_height/3+1);
1234        widget_kf_list->set_size_request(-1,header_height/3+1);
1235
1236        Gtk::Alignment *space = Gtk::manage(new Gtk::Alignment());
1237        space->set_size_request(4);
1238        space->show();
1239       
1240        Gtk::Alignment *space2 = Gtk::manage(new Gtk::Alignment());
1241        space2->set_size_request(4);
1242       
1243        jackdial = manage(new class JackDial());
1244#ifdef WITH_JACK
1245        jackbutton = jackdial->get_toggle_jackbutton();
1246        jackdial->signal_toggle_jack().connect(sigc::mem_fun(*this, &studio::CanvasView::toggle_jack_button));
1247        jackdial->signal_offset_changed().connect(sigc::mem_fun(*this, &studio::CanvasView::on_jack_offset_changed));
1248        jackdial->set_fps(get_canvas()->rend_desc().get_frame_rate());
1249        jackdial->set_offset(get_jack_offset());
1250        if ( !getenv("SYNFIG_DISABLE_JACK") )
1251        {
1252                jackdial->show();
1253                space2->show();
1254        }
1255#endif
1256        statusbar->show();
1257       
1258        timebar = Gtk::manage(new class Gtk::Table(11, 2, false));
1259
1260        //Attach widgets to the timebar
1261        //timebar->attach(*manage(disp_audio), 1, 5, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK);
1262        timebar->attach(*timetrackbutton, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
1263        timebar->attach(*current_time_widget, 1, 2, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
1264        timebar->attach(*framedial, 2, 4, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
1265        timebar->attach(*jackdial, 4, 5, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
1266        //timebar->attach(*space2, 5, 6, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::FILL);
1267        timebar->attach(*statusbar, 5, 7, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
1268        //timebar->attach(*progressbar, 5, 6, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
1269        timebar->attach(*widget_interpolation_scroll, 7, 8, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
1270        timebar->attach(*keyframedial, 8, 9, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
1271        timebar->attach(*space, 9, 10, 1, 2, Gtk::SHRINK, Gtk::FILL);
1272        timebar->attach(*animatebutton, 10, 11, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
1273       
1274        timebar->attach(*timetrack, 0, 11, 0, 1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL);
1275
1276        timebar->show();
1277
1278        return timebar;
1279}
1280
1281Gtk::Widget *
1282CanvasView::create_work_area()
1283{
1284        work_area=std::auto_ptr<WorkArea>(new class studio::WorkArea(canvas_interface_));
1285        work_area->set_instance(get_instance());
1286        work_area->set_canvas(get_canvas());
1287        work_area->set_canvas_view(this);
1288        work_area->set_progress_callback(get_ui_interface().get());
1289        work_area->signal_popup_menu().connect(sigc::mem_fun(*this, &studio::CanvasView::popup_main_menu));
1290        work_area->show();
1291        return work_area.get();
1292}
1293
1294Gtk::ToolButton*
1295CanvasView::create_action_toolbutton(const Glib::RefPtr<Gtk::Action> &action)
1296{
1297        Gtk::ToolButton *button = Gtk::manage(new Gtk::ToolButton());
1298        button->set_related_action(action);
1299        button->show();
1300        return button;
1301}
1302
1303Gtk::SeparatorToolItem*
1304CanvasView::create_tool_separator()
1305{
1306        Gtk::SeparatorToolItem *separator = Gtk::manage(new Gtk::SeparatorToolItem());
1307        separator->show();
1308        return separator;
1309}
1310
1311Gtk::Widget*
1312CanvasView::create_display_bar()
1313{
1314        Gtk::IconSize iconsize = Gtk::IconSize::from_name("synfig-small_icon_16x16");
1315
1316        displaybar = manage(new class Gtk::Toolbar());
1317        displaybar->set_icon_size(iconsize);
1318        displaybar->set_toolbar_style(Gtk::TOOLBAR_BOTH_HORIZ);
1319
1320        // File
1321        displaybar->append( *create_action_toolbutton( App::ui_manager()->get_action("/toolbar-main/new") ) );
1322        displaybar->append( *create_action_toolbutton( App::ui_manager()->get_action("/toolbar-main/open") ) );
1323        displaybar->append( *create_action_toolbutton( action_group->get_action("save") ) );
1324        displaybar->append( *create_action_toolbutton( action_group->get_action("save-as") ) );
1325        displaybar->append( *create_action_toolbutton( App::ui_manager()->get_action("/toolbar-main/save-all") ) );
1326
1327        // Separator
1328        displaybar->append( *create_tool_separator() );
1329
1330        // Edit
1331        displaybar->append( *create_action_toolbutton( App::ui_manager()->get_action("/toolbar-main/undo") ) );
1332        displaybar->append( *create_action_toolbutton( App::ui_manager()->get_action("/toolbar-main/redo") ) );
1333
1334        // Separator
1335        displaybar->append( *create_tool_separator() );
1336       
1337        { // Setup render options dialog button
1338                Gtk::Image *icon = Gtk::manage(new Gtk::Image(Gtk::StockID("synfig-render_options"), iconsize));
1339                icon->set_padding(0, 0);
1340                icon->show();
1341
1342                render_options_button = Gtk::manage(new class Gtk::ToolButton());
1343                render_options_button->set_icon_widget(*icon);
1344                render_options_button->signal_clicked().connect(
1345                        sigc::mem_fun0(render_settings,&studio::RenderSettings::present));
1346                render_options_button->set_label(_("Render"));
1347                render_options_button->set_tooltip_text( _("Shows the Render Settings Dialog"));
1348                render_options_button->show();
1349
1350                displaybar->append(*render_options_button);
1351        }
1352
1353        { // Setup preview options dialog button
1354                Gtk::Image *icon = Gtk::manage(new Gtk::Image(Gtk::StockID("synfig-preview_options"), iconsize));
1355                icon->set_padding(0, 0);
1356                icon->show();
1357
1358                preview_options_button = Gtk::manage(new class Gtk::ToolButton());
1359                preview_options_button->set_icon_widget(*icon);
1360                preview_options_button->signal_clicked().connect(
1361                        sigc::mem_fun(*this,&CanvasView::on_preview_option));
1362                preview_options_button->set_label(_("Preview"));
1363                preview_options_button->set_tooltip_text(_("Shows the Preview Settings Dialog"));
1364                preview_options_button->show();
1365
1366                displaybar->append(*preview_options_button);
1367        }
1368
1369        // Separator
1370        displaybar->append( *create_tool_separator() );
1371
1372        // Setup the ToggleDuckDial widget
1373        Duck::Type m = work_area->get_type_mask();
1374        toggleducksdial.update_toggles(m);
1375        toggleducksdial.signal_ducks_position().connect(
1376                sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_POSITION) );
1377        toggleducksdial.signal_ducks_vertex().connect(
1378                sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_VERTEX) );
1379        toggleducksdial.signal_ducks_tangent().connect(
1380                sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_TANGENT) );
1381        toggleducksdial.signal_ducks_radius().connect(
1382                sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_RADIUS) );
1383        toggleducksdial.signal_ducks_width().connect(
1384                sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_WIDTH) );
1385        toggleducksdial.signal_ducks_angle().connect(
1386                sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_ANGLE) );
1387        toggleducksdial.insert_to_toolbar(*displaybar);
1388
1389        // Separator
1390        displaybar->append( *create_tool_separator() );
1391
1392        /* QUALITY_SPIN_DISABLED see also CanvasView::set_quality
1393        { // Set up quality spin button
1394                quality_spin=Gtk::manage(new class Gtk::SpinButton(quality_adjustment_));
1395                quality_spin->signal_value_changed().connect(
1396                        sigc::mem_fun(*this, &studio::CanvasView::update_quality));
1397                quality_spin->set_tooltip_text( _("Quality (lower is better)"));
1398                quality_spin->show();
1399
1400                Gtk::ToolItem *toolitem = Gtk::manage(new Gtk::ToolItem());
1401                toolitem->add(*quality_spin);
1402                toolitem->set_is_important(true);
1403                toolitem->show();
1404
1405                displaybar->append(*toolitem);
1406        }
1407
1408        // Separator
1409        displaybar->append( *create_tool_separator() );
1410        */
1411
1412        { // Set up the show grid toggle button
1413                Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_show_grid"), iconsize));
1414                icon->set_padding(0, 0);
1415                icon->show();
1416
1417                show_grid = Gtk::manage(new class Gtk::ToggleToolButton());
1418                show_grid->set_active(work_area->grid_status());
1419                show_grid->set_icon_widget(*icon);
1420                show_grid->signal_toggled().connect(
1421                        sigc::mem_fun(*this, &studio::CanvasView::toggle_show_grid));
1422                show_grid->set_label(_("Show grid"));
1423                show_grid->set_tooltip_text( _("Show grid when enabled"));
1424                show_grid->show();
1425
1426                displaybar->append(*show_grid);
1427        }
1428
1429        { // Set up the snap to grid toggle button
1430                Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_snap_grid"), iconsize));
1431                icon->set_padding(0, 0);
1432                icon->show();
1433
1434                snap_grid = Gtk::manage(new class Gtk::ToggleToolButton());
1435                snap_grid->set_active(work_area->grid_status());
1436                snap_grid->set_icon_widget(*icon);
1437                snap_grid->signal_toggled().connect(
1438                        sigc::mem_fun(*this, &studio::CanvasView::toggle_snap_grid));
1439                snap_grid->set_label(_("Snap to grid"));
1440                snap_grid->set_tooltip_text( _("Snap to grid when enabled"));
1441                snap_grid->show();
1442
1443                displaybar->append(*snap_grid);
1444        }
1445
1446        // Separator
1447        displaybar->append( *create_tool_separator() );
1448
1449        { // Set up the onion skin toggle button
1450                Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_onion_skin"), iconsize));
1451                icon->set_padding(0, 0);
1452                icon->show();
1453
1454                onion_skin = Gtk::manage(new class Gtk::ToggleToolButton());
1455                onion_skin->set_active(work_area->get_onion_skin());
1456                onion_skin->set_icon_widget(*icon);
1457                onion_skin->signal_toggled().connect(
1458                        sigc::mem_fun(*this, &studio::CanvasView::toggle_onion_skin));
1459                onion_skin->set_label(_("Onion skin"));
1460                onion_skin->set_tooltip_text( _("Shows onion skin when enabled"));
1461                onion_skin->show();
1462
1463                displaybar->append(*onion_skin);
1464        }
1465       
1466        { // Set up past onion skin spin button
1467                past_onion_spin=Gtk::manage(new class Gtk::SpinButton(past_onion_adjustment_));
1468                past_onion_spin->signal_value_changed().connect(
1469                        sigc::mem_fun(*this, &studio::CanvasView::set_onion_skins));
1470                past_onion_spin->set_tooltip_text( _("Past onion skins"));
1471                past_onion_spin->show();
1472
1473                Gtk::ToolItem *toolitem = Gtk::manage(new Gtk::ToolItem());
1474                toolitem->add(*past_onion_spin);
1475                toolitem->set_is_important(true);
1476                toolitem->show();
1477
1478                displaybar->append(*toolitem);
1479        }
1480
1481        { // Set up future onion skin spin button
1482                future_onion_spin=Gtk::manage(new class Gtk::SpinButton(future_onion_adjustment_));
1483                future_onion_spin->signal_value_changed().connect(
1484                        sigc::mem_fun(*this, &studio::CanvasView::set_onion_skins));
1485                future_onion_spin->set_tooltip_text( _("Future onion skins"));
1486                future_onion_spin->show();
1487
1488                Gtk::ToolItem *toolitem = Gtk::manage(new Gtk::ToolItem());
1489                toolitem->add(*future_onion_spin);
1490                toolitem->set_is_important(true);
1491                toolitem->show();
1492
1493                displaybar->append(*toolitem);
1494        }
1495
1496        // Separator
1497        displaybar->append( *create_tool_separator() );
1498       
1499        { // Setup refresh button
1500                Gtk::Image *icon = Gtk::manage(new Gtk::Image(Gtk::StockID("gtk-refresh"), iconsize));
1501                icon->set_padding(0, 0);
1502                icon->show();
1503
1504                refreshbutton = Gtk::manage(new class Gtk::ToolButton());
1505                refreshbutton->set_icon_widget(*icon);
1506                refreshbutton->signal_clicked().connect(SLOT_EVENT(EVENT_REFRESH));
1507                refreshbutton->set_label(_("Refresh"));
1508                refreshbutton->set_tooltip_text( _("Refresh workarea"));
1509                refreshbutton->show();
1510
1511                displaybar->append(*refreshbutton);
1512        }
1513       
1514        // Separator
1515        displaybar->append( *create_tool_separator() );
1516       
1517        // Set up the ResolutionDial widget
1518        resolutiondial.update_lowres(work_area->get_low_resolution_flag());
1519        resolutiondial.signal_increase_resolution().connect(
1520                sigc::mem_fun(*this, &studio::CanvasView::decrease_low_res_pixel_size));
1521        resolutiondial.signal_decrease_resolution().connect(
1522                sigc::mem_fun(*this, &studio::CanvasView::increase_low_res_pixel_size));
1523        resolutiondial.signal_use_low_resolution().connect(
1524                sigc::mem_fun(*this, &studio::CanvasView::toggle_low_res_pixel_flag));
1525        resolutiondial.insert_to_toolbar(*displaybar);
1526
1527        displaybar->show();
1528       
1529        progressbar =manage(new class Gtk::ProgressBar());
1530        //progressbar->set_text("Idle");
1531        //progressbar->set_show_text(true);
1532        progressbar->show();
1533        cancel=false;
1534       
1535        {
1536                Gtk::Image *icon = Gtk::manage(new Gtk::Image(Gtk::StockID("gtk-stop"), iconsize));
1537                icon->set_padding(0, 0);
1538                icon->show();
1539               
1540                stopbutton = Gtk::manage(new class Gtk::Button());
1541                stopbutton->set_image(*icon);
1542                stopbutton->signal_clicked().connect(SLOT_EVENT(EVENT_STOP));
1543                stopbutton->set_relief(Gtk::RELIEF_NONE);
1544                //stopbutton->set_label(_("Stop"));
1545                stopbutton->set_tooltip_text( _("Stop current operation"));
1546                stopbutton->show();
1547                stopbutton->set_sensitive(false);
1548        }
1549       
1550        Gtk::HBox *hbox = manage(new class Gtk::HBox(false, 0));
1551        hbox->pack_start(*displaybar, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0);
1552        //hbox->pack_start(*progressbar, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0);
1553        hbox->pack_start(*stopbutton, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0);
1554        hbox->show();
1555       
1556        return hbox;
1557}
1558
1559void
1560CanvasView::on_current_time_widget_changed()
1561{
1562        set_time(current_time_widget->get_value());
1563
1564        // show the value being used - it will have been rounded to nearest frame
1565        // this was already being done elsewhere, but only if the time was really changed;
1566        // if the current time was 6f and the user edited it to 6.1f, then the 6.1f would
1567        // be left in the display without the following line to fix it
1568        current_time_widget->set_value(get_time());
1569        current_time_widget->set_position(-1); // leave the cursor at the end
1570}
1571
1572//      Gtk::Widget*
1573//      CanvasView::create_children_tree()
1574//      {
1575//              // Create the layer tree
1576//              children_tree=manage(new class ChildrenTree());
1577//
1578//              // Set up the layer tree
1579//              //children_tree->set_model(children_tree_store());
1580//              if(children_tree)children_tree->set_time_adjustment(time_adjustment());
1581//              if(children_tree)children_tree->show();
1582//
1583//              // Connect Signals
1584//              if(children_tree)children_tree->signal_edited_value().connect(sigc::mem_fun(*this, &studio::CanvasView::on_edited_value));
1585//              if(children_tree)children_tree->signal_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
1586//              if(children_tree)children_tree->signal_waypoint_clicked_childrentree().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked_canvasview));
1587//              if(children_tree)children_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
1588//
1589//              return children_tree;
1590//      }
1591
1592//      Gtk::Widget*
1593//      CanvasView::create_keyframe_tree()
1594//      {
1595//              keyframe_tree=manage(new KeyframeTree());
1596//
1597//              //keyframe_tree->get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
1598//              //keyframe_tree->show();
1599//              //keyframe_tree->set_model(keyframe_tree_store());
1600//              keyframe_tree->set_editable(true);
1601//              //keyframe_tree->signal_edited().connect(sigc::hide_return(sigc::mem_fun(*canvas_interface(), &synfigapp::CanvasInterface::update_keyframe)));
1602//
1603//              keyframe_tree->signal_event().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_tree_event));
1604//
1605//              Gtk::ScrolledWindow *scroll_layer_tree = manage(new class Gtk::ScrolledWindow());
1606//              scroll_layer_tree->set_can_focus(true);
1607//              scroll_layer_tree->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
1608//              scroll_layer_tree->add(*keyframe_tree);
1609//              scroll_layer_tree->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
1610//              //scroll_layer_tree->show();
1611//
1612//
1613//              Gtk::Table *layout_table= manage(new Gtk::Table(1, 2, false));
1614//              layout_table->attach(*scroll_layer_tree, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0);
1615//
1616//              Gtk::Image *icon;
1617//              Gtk::IconSize iconsize(Gtk::IconSize::from_name("synfig-small_icon"));
1618//
1619//              NEW_SMALL_BUTTON(button_add,"gtk-add",_("New Keyframe"));
1620//              NEW_SMALL_BUTTON(button_duplicate,"synfig-duplicate",_("Duplicate Keyframe"));
1621//              NEW_SMALL_BUTTON(button_delete,"gtk-delete",_("Delete Keyframe"));
1622//
1623//              Gtk::HBox *hbox(manage(new Gtk::HBox()));
1624//              layout_table->attach(*hbox, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0);
1625//
1626//              hbox->pack_start(*button_add,Gtk::PACK_SHRINK);
1627//              hbox->pack_start(*button_duplicate,Gtk::PACK_SHRINK);
1628//              hbox->pack_start(*button_delete,Gtk::PACK_SHRINK);
1629//
1630//              /*
1631//              button_raise->set_relief(Gtk::RELIEF_HALF);
1632//              button_lower->set_relief(Gtk::RELIEF_HALF);
1633//              button_duplicate->set_relief(Gtk::RELIEF_HALF);
1634//              button_delete->set_relief(Gtk::RELIEF_HALF);
1635//              */
1636//
1637//              button_add->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_add_pressed));
1638//              button_duplicate->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_duplicate_pressed));
1639//              button_delete->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_remove_pressed));
1640//
1641//              //layout_table->show_all();
1642//
1643//              keyframe_tab_child=layout_table;
1644//
1645//
1646//              layout_table->hide();
1647//
1648//              return layout_table;
1649//      }
1650
1651//      Gtk::Widget*
1652//      CanvasView::create_layer_tree()
1653//      {
1654//              // Create the layer tree
1655//              printf("CanvasView::create_layer_tree()\n");
1656//              layer_tree=manage(new class LayerTree());
1657//
1658//              // Set up the layer tree
1659//              //layer_tree->set_model(layer_tree_store());
1660//              layer_tree->set_time_adjustment(time_adjustment());
1661//              layer_tree->show();
1662//
1663//              // Connect Signals
1664//              layer_tree->signal_layer_toggle().connect(sigc::mem_fun(*this, &studio::CanvasView::on_layer_toggle));
1665//              layer_tree->signal_edited_value().connect(sigc::mem_fun(*this, &studio::CanvasView::on_edited_value));
1666//              layer_tree->signal_layer_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_layer_user_click));
1667//              layer_tree->signal_param_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
1668//              layer_tree->signal_waypoint_clicked_layertree().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked_canvasview));
1669//              layer_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
1670//
1671//              layer_tree->hide();
1672//              return layer_tree;
1673//      }
1674
1675void
1676CanvasView::init_menus()
1677{
1678        //cache the position of desired widgets
1679
1680        /*Menus to worry about:
1681        - filemenu
1682        - editmenu
1683        - layermenu
1684        - duckmaskmenu
1685        - mainmenu
1686        - canvasmenu
1687        - viewmenu
1688        */
1689        action_group = Gtk::ActionGroup::create("canvasview");
1690
1691        action_group->add( Gtk::Action::create("save", Gtk::StockID("synfig-save")),
1692                hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::save))
1693        );
1694        action_group->add( Gtk::Action::create("save-as", Gtk::StockID("synfig-save_as"), _("Save As...")),
1695                sigc::hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::dialog_save_as))
1696        );
1697        action_group->add( Gtk::Action::create("save-all", Gtk::StockID("synfig-save_all"), _("Save All"), _("Save all opened documents")),
1698                sigc::ptr_fun(save_all)
1699        );
1700        action_group->add( Gtk::Action::create("revert", Gtk::Stock::REVERT_TO_SAVED),
1701                sigc::hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::safe_revert))
1702        );
1703        /*
1704        action_group->add( Gtk::Action::create("cvs-add", Gtk::StockID("synfig-cvs_add")),
1705                sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_add))
1706        );
1707        action_group->add( Gtk::Action::create("cvs-update", Gtk::StockID("synfig-cvs_update")),
1708                sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_update))
1709        );
1710        action_group->add( Gtk::Action::create("cvs-revert", Gtk::StockID("synfig-cvs_revert")),
1711                sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_revert))
1712        );
1713        action_group->add( Gtk::Action::create("cvs-commit", Gtk::StockID("synfig-cvs_commit")),
1714                sigc::hide_return(sigc::mem_fun(*get_instance(), &studio::Instance::dialog_cvs_commit))
1715        );
1716        */
1717        action_group->add( Gtk::Action::create("import", _("Import...")),
1718                sigc::hide_return(sigc::mem_fun(*this, &studio::CanvasView::image_import))
1719        );
1720        action_group->add( Gtk::Action::create("render", Gtk::StockID("synfig-render_options"), _("Render...")),
1721                sigc::mem_fun0(render_settings,&studio::RenderSettings::present)
1722        );
1723        action_group->add( Gtk::Action::create("preview", Gtk::StockID("synfig-preview_options"), _("Preview...")),
1724                sigc::mem_fun(*this,&CanvasView::on_preview_option)
1725        );
1726        //action_group->add( Gtk::Action::create("sound", _("Import Sound File...")),
1727        //      sigc::mem_fun(*this,&CanvasView::on_audio_option)
1728        //);
1729        action_group->add( Gtk::Action::create("options", _("Options...")),
1730                sigc::mem_fun0(canvas_options,&studio::CanvasOptions::present)
1731        );
1732        action_group->add( Gtk::Action::create("close-document", Gtk::StockID("gtk-close"), _("Close Document")),
1733                sigc::hide_return(sigc::mem_fun(*this,&studio::CanvasView::close_instance))
1734        );
1735        action_group->add( Gtk::Action::create("quit", Gtk::StockID("gtk-quit"), _("Quit")),
1736                sigc::hide_return(sigc::ptr_fun(&studio::App::quit))
1737        );
1738
1739        action_group->add( Gtk::Action::create("select-all-ducks", _("Select All Handles")),
1740                sigc::mem_fun(*work_area,&studio::WorkArea::select_all_ducks)
1741        );
1742
1743        action_group->add( Gtk::Action::create("unselect-all-ducks", _("Unselect All Handles")),
1744                sigc::mem_fun(*work_area,&studio::WorkArea::unselect_all_ducks)
1745        );
1746
1747        action_group->add( Gtk::Action::create("select-all-layers", _("Select All Layers")),
1748                sigc::mem_fun(*this,&CanvasView::on_select_layers)
1749        );
1750
1751        action_group->add( Gtk::Action::create("unselect-all-layers", _("Unselect All Layers")),
1752                sigc::mem_fun(*this,&CanvasView::on_unselect_layers)
1753        );
1754
1755        // the stop is not as normal stop but pause. So use "Pause" in UI, including TEXT and
1756        // icon. the internal code is still using stop.
1757        action_group->add( Gtk::Action::create("stop", Gtk::StockID("synfig-animate_pause")),
1758                SLOT_EVENT(EVENT_STOP)
1759        );
1760
1761        action_group->add( Gtk::Action::create("refresh", Gtk::StockID("gtk-refresh")),
1762                SLOT_EVENT(EVENT_REFRESH)
1763        );
1764
1765        action_group->add( Gtk::Action::create("properties", Gtk::StockID("gtk-properties"), _("Properties...")),
1766                sigc::mem_fun0(canvas_properties,&studio::CanvasProperties::present)
1767        );
1768
1769        list<synfigapp::PluginManager::plugin> plugin_list = studio::App::plugin_manager.get_list();
1770        for(list<synfigapp::PluginManager::plugin>::const_iterator p=plugin_list.begin();p!=plugin_list.end();++p) {
1771
1772                synfigapp::PluginManager::plugin plugin = *p;
1773
1774                action_group->add( Gtk::Action::create(plugin.id, plugin.name),
1775                                sigc::bind(
1776                                        sigc::mem_fun(*get_instance().get(), &studio::Instance::run_plugin),
1777                                        plugin.path
1778                                )
1779                );
1780        }
1781
1782        // Preview Quality Menu
1783        {
1784                int i;
1785                action_group->add( Gtk::RadioAction::create(quality_group,"quality-00", _("Use Parametric Renderer")),
1786                        sigc::bind(
1787                                sigc::mem_fun(*work_area, &studio::WorkArea::set_quality),
1788                                0
1789                        )
1790                );
1791                for(i=1;i<=10;i++)
1792                {
1793                        String note;
1794                        if (i == 1) note = _(" (best)");
1795                        if (i == 10) note = _(" (fastest)");
1796                        Glib::RefPtr<Gtk::RadioAction> action(Gtk::RadioAction::create(quality_group,strprintf("quality-%02d",i),
1797                                                                                                                                                   strprintf(_("Set Quality to %d"),i) + note));
1798                        if (i==8)                       // default quality
1799                        {
1800                                action->set_active();
1801                                work_area->set_quality(i);
1802                        }
1803                        action_group->add( action,
1804                                sigc::bind(
1805                                        sigc::mem_fun(*this, &studio::CanvasView::set_quality),
1806                                        i
1807                                )
1808                        );
1809                }
1810        }
1811
1812        // Low-Res Quality Menu
1813        {
1814                int i;
1815                for(list<int>::iterator iter = CanvasView::get_pixel_sizes().begin(); iter != CanvasView::get_pixel_sizes().end(); iter++)
1816                {
1817                        i = *iter;
1818                        Glib::RefPtr<Gtk::RadioAction> action(Gtk::RadioAction::create(low_res_pixel_size_group,strprintf("lowres-pixel-%d",i),
1819                                                                                                                                                   strprintf(_("Set Low-Res pixel size to %d"),i)));
1820                        if(i==2)                        // default pixel size
1821                        {
1822                                action->set_active();
1823                                work_area->set_low_res_pixel_size(i);
1824                        }
1825                        action_group->add( action,
1826                                sigc::bind(
1827                                        sigc::mem_fun(*work_area, &studio::WorkArea::set_low_res_pixel_size),
1828                                        i
1829                                )
1830                        );
1831                }
1832
1833                Glib::RefPtr<Gtk::Action> action;
1834
1835                action=Gtk::Action::create("decrease-low-res-pixel-size", _("Decrease Low-Res Pixel Size"));
1836                action_group->add( action,sigc::mem_fun(this, &studio::CanvasView::decrease_low_res_pixel_size));
1837
1838                action=Gtk::Action::create("increase-low-res-pixel-size",  _("Increase Low-Res Pixel Size"));
1839                action_group->add( action, sigc::mem_fun(this, &studio::CanvasView::increase_low_res_pixel_size));
1840
1841        }
1842
1843        action_group->add( Gtk::Action::create("play", Gtk::Stock::MEDIA_PLAY),
1844                sigc::mem_fun(*this, &studio::CanvasView::on_play_pause_pressed)
1845        );
1846
1847        action_group->add( Gtk::Action::create("dialog-flipbook", _("Preview Window")),
1848                sigc::mem_fun0(*preview_dialog, &studio::Dialog_Preview::present)
1849        );
1850        // Prevent call to preview window before preview option has created the preview window
1851        {
1852                Glib::RefPtr< Gtk::Action > action = action_group->get_action("dialog-flipbook");
1853                action->set_sensitive(false);
1854        }
1855
1856        {
1857                Glib::RefPtr<Gtk::ToggleAction> action;
1858
1859                grid_show_toggle = Gtk::ToggleAction::create("toggle-grid-show", _("Show Grid"));
1860                grid_show_toggle->set_active(work_area->grid_status());
1861                action_group->add(grid_show_toggle, sigc::mem_fun(*this, &studio::CanvasView::toggle_show_grid));
1862
1863                grid_snap_toggle = Gtk::ToggleAction::create("toggle-grid-snap", _("Snap to Grid"));
1864                grid_snap_toggle->set_active(work_area->get_grid_snap());
1865                action_group->add(grid_snap_toggle, sigc::mem_fun(*this, &studio::CanvasView::toggle_snap_grid));
1866
1867                action = Gtk::ToggleAction::create("toggle-guide-show", _("Show Guides"));
1868                action->set_active(work_area->get_show_guides());
1869                action_group->add(action, sigc::mem_fun(*work_area, &studio::WorkArea::toggle_show_guides));
1870
1871                action = Gtk::ToggleAction::create("toggle-guide-snap", _("Snap to Guides"));
1872                action->set_active(work_area->get_guide_snap());
1873                action_group->add(action, sigc::mem_fun(*work_area, &studio::WorkArea::toggle_guide_snap));
1874
1875
1876                action = Gtk::ToggleAction::create("toggle-low-res", _("Use Low-Res"));
1877                action->set_active(work_area->get_low_resolution_flag());
1878                action_group->add(action, sigc::mem_fun(*this, &studio::CanvasView::toggle_low_res_pixel_flag));
1879
1880                onion_skin_toggle = Gtk::ToggleAction::create("toggle-onion-skin", _("Show Onion Skin"));
1881                onion_skin_toggle->set_active(work_area->get_onion_skin());
1882                action_group->add(onion_skin_toggle, sigc::mem_fun(*this, &studio::CanvasView::toggle_onion_skin));
1883        }
1884
1885        action_group->add( Gtk::Action::create("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit")),
1886                sigc::mem_fun(*work_area, &studio::WorkArea::zoom_fit)
1887        );
1888        action_group->add( Gtk::Action::create("canvas-zoom-100", Gtk::StockID("gtk-zoom-100")),
1889                sigc::mem_fun(*work_area, &studio::WorkArea::zoom_norm)
1890        );
1891
1892        {
1893                Glib::RefPtr<Gtk::Action> action;
1894
1895                action=Gtk::Action::create("seek-next-frame", Gtk::StockID("synfig-animate_seek_next_frame"));
1896                action_group->add(action,sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_frame),1));
1897                action=Gtk::Action::create("seek-prev-frame", Gtk::StockID("synfig-animate_seek_prev_frame"));
1898                action_group->add( action, sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_frame),-1));
1899
1900                action=Gtk::Action::create("seek-next-second", Gtk::Stock::GO_FORWARD,_("Seek Forward"),_("Seek Forward"));
1901                action_group->add(action,sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time),Time(1)));
1902                action=Gtk::Action::create("seek-prev-second", Gtk::Stock::GO_BACK,_("Seek Backward"),_("Seek Backward"));
1903                action_group->add( action, sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time),Time(-1)));
1904
1905                action=Gtk::Action::create("seek-end", Gtk::StockID("synfig-animate_seek_end"));
1906                action_group->add(action,sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time),Time::end()));
1907
1908                action=Gtk::Action::create("seek-begin", Gtk::StockID("synfig-animate_seek_begin"));
1909                action_group->add( action, sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time),Time::begin()));
1910
1911                action=Gtk::Action::create("jump-next-keyframe", Gtk::StockID("synfig-animate_seek_next_keyframe"));
1912                action_group->add( action,sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_next_keyframe));
1913
1914                action=Gtk::Action::create("jump-prev-keyframe", Gtk::StockID("synfig-animate_seek_prev_keyframe"));
1915                action_group->add( action,sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_prev_keyframe));
1916
1917                action=Gtk::Action::create("canvas-zoom-in", Gtk::Stock::ZOOM_IN);
1918                action_group->add( action,sigc::mem_fun(*work_area, &studio::WorkArea::zoom_in));
1919
1920                action=Gtk::Action::create("canvas-zoom-out", Gtk::Stock::ZOOM_OUT);
1921                action_group->add( action, sigc::mem_fun(*work_area, &studio::WorkArea::zoom_out) );
1922
1923                action=Gtk::Action::create("time-zoom-in", Gtk::Stock::ZOOM_IN, _("Zoom In on Timeline"));
1924                action_group->add( action, sigc::mem_fun(*this, &studio::CanvasView::time_zoom_in) );
1925
1926                action=Gtk::Action::create("time-zoom-out", Gtk::Stock::ZOOM_OUT, _("Zoom Out on Timeline"));
1927                action_group->add( action, sigc::mem_fun(*this, &studio::CanvasView::time_zoom_out) );
1928
1929        }
1930
1931        {
1932                Glib::RefPtr<Gtk::ToggleAction> action;
1933
1934#define DUCK_MASK(lower,upper,string)                                                                                           \
1935                action=Gtk::ToggleAction::create("mask-" #lower "-ducks", string);                      \
1936                action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_##upper));      \
1937                action_group->add(action,                                                                                                       \
1938                        sigc::bind(                                                                                                                             \
1939                                sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),            \
1940                                Duck::TYPE_##upper))
1941
1942                DUCK_MASK(position,POSITION,_("Show Position Handles"));
1943                DUCK_MASK(tangent,TANGENT,_("Show Tangent Handles"));
1944                DUCK_MASK(vertex,VERTEX,_("Show Vertex Handles"));
1945                DUCK_MASK(radius,RADIUS,_("Show Radius Handles"));
1946                DUCK_MASK(width,WIDTH,_("Show Width Handles"));
1947                DUCK_MASK(angle,ANGLE,_("Show Angle Handles"));
1948                action_mask_bone_setup_ducks = action;
1949                DUCK_MASK(bone-recursive,BONE_RECURSIVE,_("Show Recursive Scale Bone Handles"));
1950                action_mask_bone_recursive_ducks = action;
1951                DUCK_MASK(widthpoint-position, WIDTHPOINT_POSITION, _("Show WidthPoints Position Handles"));
1952
1953#undef DUCK_MASK
1954
1955                action_group->add(Gtk::Action::create("mask-bone-ducks", _("Next Bone Handles")),
1956                                                  sigc::mem_fun(*this,&CanvasView::mask_bone_ducks));
1957        }
1958
1959}
1960
1961void
1962CanvasView::on_select_layers()
1963{
1964        Canvas::Handle canvas(get_canvas());
1965        for (CanvasBase::iterator iter = canvas->begin(); iter != canvas->end(); iter++)
1966                layer_tree->select_all_children_layers(*iter);
1967}
1968
1969void
1970CanvasView::on_unselect_layers()
1971{
1972        layer_tree->clear_selected_layers();
1973}
1974
1975void
1976CanvasView::add_layer(synfig::String x)
1977{
1978        Canvas::Handle canvas;
1979
1980        synfigapp::SelectionManager::LayerList layer_list(get_selection_manager()->get_selected_layers());
1981
1982        int target_depth(0);
1983
1984        if(layer_list.empty())
1985        {
1986                canvas=get_canvas();
1987        }
1988        else
1989        {
1990                canvas=(*layer_list.begin())->get_canvas();
1991                target_depth=canvas->get_depth(*layer_list.begin());
1992        }
1993
1994        Layer::Handle layer(canvas_interface()->add_layer_to(x,canvas,target_depth));
1995        if(layer)
1996        {
1997                get_selection_manager()->clear_selected_layers();
1998                get_selection_manager()->set_selected_layer(layer);
1999        }
2000}
2001
2002void
2003CanvasView::popup_layer_menu(synfig::Layer::Handle layer)
2004{
2005        Gtk::Menu* menu(&parammenu);
2006        std::vector<Widget*> children = menu->get_children();
2007        for(std::vector<Widget*>::iterator i = children.begin(); i != children.end(); ++i)
2008                menu->remove(**i);
2009
2010        synfigapp::Action::ParamList param_list;
2011        param_list.add("time",canvas_interface()->get_time());
2012        param_list.add("canvas",Canvas::Handle(layer->get_canvas()));
2013        param_list.add("canvas_interface",canvas_interface());
2014        param_list.add("layer",layer);
2015
2016        //Gtk::Menu *newlayers(manage(new Gtk::Menu()));
2017        //build_new_layer_menu(*newlayers);
2018
2019        //parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("New Layer"),*newlayers));
2020
2021        if(etl::handle<Layer_PasteCanvas>::cast_dynamic(layer))
2022        {
2023                Gtk::MenuItem *item = manage(new Gtk::ImageMenuItem(
2024                        *manage(new Gtk::Image(
2025                                Gtk::StockID("synfig-select_all_child_layers"),
2026                                Gtk::ICON_SIZE_MENU )),
2027                        _("Select All Children") ));
2028                item->signal_activate().connect(
2029                        sigc::bind(
2030                                sigc::mem_fun(
2031                                        *layer_tree,
2032                                        &studio::LayerTree::select_all_children_layers ),
2033                                layer ));
2034                item->show_all();
2035                menu->append(*item);
2036        }
2037
2038        add_actions_to_menu(menu, param_list,synfigapp::Action::CATEGORY_LAYER);
2039        menu->popup(3,gtk_get_current_event_time());
2040}
2041
2042void
2043CanvasView::register_layer_type(synfig::Layer::Book::value_type &/*lyr*/,std::map<synfig::String,Gtk::Menu*>* /*category_map*/)
2044{
2045/*      if(lyr.second.category==CATEGORY_DO_NOT_USE)
2046                return;
2047
2048        if(category_map->count(lyr.second.category)==0)
2049                (*category_map)[lyr.second.category]=manage(new Gtk::Menu());
2050
2051        (*category_map)[lyr.second.category]->items().push_back(Gtk::Menu_Helpers::MenuElem(lyr.second.local_name,
2052                sigc::hide_return(
2053                        sigc::bind(
2054                                sigc::mem_fun(*this,&studio::CanvasView::add_layer),
2055                                lyr.first
2056                        )
2057                )
2058        ));
2059*/
2060}
2061
2062void
2063CanvasView::build_new_layer_menu(Gtk::Menu &/*menu*/)
2064{
2065/*
2066        std::map<synfig::String,Gtk::Menu*> category_map;
2067
2068        std::for_each(
2069                synfig::Layer::book().begin(),
2070                synfig::Layer::book().end(),
2071                sigc::bind(
2072                        sigc::mem_fun(
2073                                *this,
2074                                &studio::CanvasView::register_layer_type
2075                        ),
2076                        &category_map
2077                )
2078        );
2079
2080        menu.items().clear();
2081        menu.items().push_back(Gtk::Menu_Helpers::TearoffMenuElem());
2082
2083        std::map<synfig::String,Gtk::Menu*>::iterator iter;
2084        for(iter=category_map.begin();iter!=category_map.end();++iter)
2085                menu.items().push_back(Gtk::Menu_Helpers::MenuElem(iter->first,*iter->second));
2086
2087        menu.show();
2088*/
2089}
2090
2091void
2092CanvasView::popup_main_menu()
2093{
2094        //mainmenu.popup(0,gtk_get_current_event_time());
2095        Gtk::Menu* menu = dynamic_cast<Gtk::Menu*>(App::ui_manager()->get_widget("/menu-main"));
2096        if(menu)
2097        {
2098                //menu->set_accel_group(App::ui_manager()->get_accel_group());
2099                //menu->accelerate(*this);
2100                menu->popup(0,gtk_get_current_event_time());
2101        }
2102}
2103
2104void
2105CanvasView::on_refresh_pressed()
2106{
2107        rebuild_tables();
2108        rebuild_ducks();
2109        work_area->queue_render_preview();
2110}
2111
2112void
2113CanvasView::workarea_layer_selected(synfig::Layer::Handle layer)
2114{
2115        get_selection_manager()->clear_selected_layers();
2116        if(layer)
2117                get_selection_manager()->set_selected_layer(layer);
2118}
2119
2120void
2121CanvasView::refresh_rend_desc()
2122{
2123        float current_frame_rate = get_canvas()->rend_desc().get_frame_rate();
2124        current_time_widget->set_fps(current_frame_rate);
2125
2126        // "responsive" current time widget width on time format
2127        int current_time_lenght = current_time_widget->get_value().get_string(current_frame_rate, App::get_time_format()).length();
2128#define CURRENT_TIME_MIN_LENGHT 6
2129        current_time_lenght = current_time_lenght < CURRENT_TIME_MIN_LENGHT ? CURRENT_TIME_MIN_LENGHT : current_time_lenght;
2130        current_time_widget->set_width_chars(current_time_lenght);
2131#undef CURRENT_TIME_MIN_LENGHT
2132
2133        jackdial->set_fps(current_frame_rate);
2134        widget_kf_list->set_fps(current_frame_rate);
2135
2136        //????
2137        //synfig::info("Canvasview: Refreshing render desc info");
2138        if(!get_time().is_equal(time_adjustment()->get_value()))
2139        {
2140                time_adjustment()->set_value(get_time());
2141                time_adjustment()->value_changed();
2142        }
2143
2144        Time length(get_canvas()->rend_desc().get_time_end()-get_canvas()->rend_desc().get_time_start());
2145        if(length<DEFAULT_TIME_WINDOW_SIZE)
2146        {
2147                time_window_adjustment()->set_page_increment(length);
2148                time_window_adjustment()->set_page_size(length);
2149        }
2150        else
2151        {
2152                time_window_adjustment()->set_page_increment(DEFAULT_TIME_WINDOW_SIZE);
2153                time_window_adjustment()->set_page_size(DEFAULT_TIME_WINDOW_SIZE);
2154        }
2155
2156        //set the FPS of the timeslider
2157        timeslider->set_global_fps(current_frame_rate);
2158
2159        //set the beginning and ending time of the time slider
2160        Time begin_time=get_canvas()->rend_desc().get_time_start();
2161        Time end_time=get_canvas()->rend_desc().get_time_end();
2162
2163        // Setup the time_window adjustment
2164        time_window_adjustment()->set_lower(begin_time);
2165        time_window_adjustment()->set_upper(end_time);
2166        time_window_adjustment()->set_step_increment(synfig::Time(1.0/current_frame_rate));
2167
2168        //Time length(get_canvas()->rend_desc().get_time_end()-get_canvas()->rend_desc().get_time_start());
2169        if(length < time_window_adjustment()->get_page_size())
2170        {
2171                time_window_adjustment()->set_page_increment(length);
2172                time_window_adjustment()->set_page_size(length);
2173        }
2174
2175        /*synfig::info("w: %p - [%.3f,%.3f] (%.3f,%.3f) child: %p\n",
2176                                &time_window_adjustment_, time_window_adjustment_->get_lower(),
2177                                time_window_adjustment_.get_upper(),time_window_adjustment_->get_value(),
2178                                time_window_adjustment_.get_page_size(),time_window_adjustment_->get_child_adjustment()
2179        );*/
2180
2181        time_window_adjustment()->changed(); //only non-value stuff was changed
2182
2183        // Setup the time adjustment
2184
2185        //NOTE THESE TWO SHOULD BE CHANGED BY THE changed() CALL ABOVE
2186        //time_adjustment()->set_lower(time_window_adjustment()->get_value());
2187        //time_adjustment()->set_upper(time_window_adjustment()->get_value()+time_window_adjustment()->get_page_size());
2188
2189//      time_adjustment()->set_lower(get_canvas()->rend_desc().get_time_start());
2190//      time_adjustment()->set_upper(get_canvas()->rend_desc().get_time_end());
2191        time_adjustment()->set_step_increment(synfig::Time(1.0/current_frame_rate));
2192        time_adjustment()->set_page_increment(synfig::Time(1.0));
2193        time_adjustment()->set_page_size(0);
2194
2195        time_adjustment()->changed();
2196
2197        /*synfig::info("w: %p - [%.3f,%.3f] (%.3f,%.3f) child: %p\n",
2198                                &time_window_adjustment_, time_window_adjustment_->get_lower(),
2199                                time_window_adjustment_.get_upper(),time_window_adjustment_->get_value(),
2200                                time_window_adjustment_.get_page_size(),time_window_adjustment_->get_child_adjustment()
2201        );      */
2202
2203        if(begin_time==end_time)
2204        {
2205                hide_timebar();
2206        }
2207        else
2208        {
2209                show_timebar();
2210        }
2211
2212        //clamp time to big bounds...
2213        if(time_window_adjustment()->get_value() < begin_time)
2214        {
2215                time_window_adjustment()->set_value(begin_time);
2216                time_window_adjustment()->value_changed();
2217        }
2218
2219        if(time_window_adjustment()->get_value() + time_window_adjustment()->get_page_size() > end_time)
2220        {
2221                time_window_adjustment()->set_value(end_time - time_window_adjustment()->get_page_size());
2222                time_window_adjustment()->value_changed();
2223        }
2224
2225        if(time_adjustment()->get_value() < begin_time)
2226        {
2227                time_adjustment()->set_value(begin_time);
2228                time_adjustment()->value_changed();
2229        }
2230
2231        if(time_adjustment()->get_value() > end_time)
2232        {
2233                time_adjustment()->set_value(end_time);
2234                time_adjustment()->value_changed();
2235        }
2236
2237        /*synfig::info("Time stats: \n"
2238                                "w: %p - [%.3f,%.3f] (%.3f,%.3f) child: %p\n"
2239                                "t: %p - [%.3f,%.3f] %.3f",
2240                                &time_window_adjustment_, time_window_adjustment_->get_lower(),
2241                                time_window_adjustment_.get_upper(),time_window_adjustment_->get_value(),
2242                                time_window_adjustment_.get_page_size(),time_window_adjustment_->get_child_adjustment(),
2243                                &time_adjustment_,time_adjustment_.get_lower(),time_adjustment_->get_upper(),
2244                                time_adjustment_->get_value()
2245        );*/
2246
2247        work_area->queue_render_preview();
2248}
2249
2250bool
2251CanvasView::close_view()
2252{
2253        //prevent double click
2254        closebutton->set_sensitive(false);
2255
2256        if(get_instance()->get_visible_canvases()==1)
2257                close_instance();
2258        else
2259                hide();
2260        return false;
2261}
2262
2263static bool _close_instance(etl::handle<Instance> instance)
2264{
2265        etl::handle<Instance> argh(instance);
2266        instance->safe_close();
2267        synfig::info("closed");
2268        return false;
2269}
2270
2271bool
2272CanvasView::close_instance()
2273{
2274#ifdef SINGLE_THREADED
2275        if (get_work_area()->get_updating())
2276        {
2277                get_work_area()->stop_updating(true); // stop and mark as cancelled
2278
2279                // give the workarea chances to stop updating
2280                Glib::signal_timeout().connect(
2281                        sigc::mem_fun(*this, &CanvasView::close_instance),
2282                        250);
2283        }
2284        else
2285#endif
2286                Glib::signal_timeout().connect(
2287                        sigc::bind(sigc::ptr_fun(_close_instance),
2288                                           (etl::handle<Instance>)get_instance()),
2289                        250);
2290        return false;
2291}
2292
2293handle<CanvasView>
2294CanvasView::create(etl::loose_handle<Instance> instance, etl::handle<synfig::Canvas> canvas)
2295{
2296        etl::handle<studio::CanvasView> view(new CanvasView(instance,instance->synfigapp::Instance::find_canvas_interface(canvas)));
2297        return view;
2298}
2299
2300void
2301CanvasView::update_title()
2302{
2303        bool modified = get_instance()->get_action_count() > 0;
2304        bool is_root = get_canvas()->is_root();
2305        string filename = get_instance()->has_real_filename()
2306                                        ? etl::basename(get_instance()->get_file_name()) : "";
2307        string canvas_name = get_canvas()->get_name();
2308        string canvas_id = get_canvas()->get_id();
2309        string &canvas_title = canvas_name.empty() ? canvas_id : canvas_name;
2310
2311        string title = filename.empty() ? canvas_title
2312                             : is_root ? filename
2313                             : filename + " (" + canvas_title + ")";
2314        if (modified) title = "*" + title;
2315
2316        if(get_instance()->synfigapp::Instance::in_repository())
2317        {
2318                title+=" (CVS";
2319                if(get_instance()->synfigapp::Instance::is_modified())
2320                        title+=_("-MODIFIED");
2321                if(get_instance()->synfigapp::Instance::is_updated())
2322                        title+=_("-UPDATED");
2323                title+=')';
2324        }
2325
2326        set_local_name(title);
2327        App::dock_manager->update_window_titles();
2328}
2329
2330void
2331CanvasView::on_hide()
2332{
2333        smach_.egress();
2334        Dockable::on_hide();
2335}
2336
2337Gtk::Widget*
2338CanvasView::create_tab_label()
2339{
2340        Gtk::EventBox* event_box(manage(new Gtk::EventBox()));
2341
2342        attach_dnd_to(*event_box);
2343
2344        Glib::ustring text(get_local_name());
2345       
2346        Gtk::HBox* box(manage(new Gtk::HBox()));
2347        event_box->add(*box);
2348        box->show();
2349
2350        Gtk::Label* label(manage(new Gtk::Label(text)));
2351        box->pack_start(*label, false, true);
2352        if (this == App::get_selected_canvas_view().get())
2353        {
2354                Pango::AttrList list;
2355                Pango::AttrInt attr = Pango::Attribute::create_attr_weight(Pango::WEIGHT_BOLD);
2356                list.insert(attr);
2357                label->set_attributes(list);
2358        }
2359        label->show();
2360
2361        closebutton = manage(new Gtk::Button());
2362        box->pack_end(*closebutton, false, false, 0);
2363        Gtk::Image* closebutton_image(manage(new Gtk::Image(
2364                        Gtk::StockID("gtk-close"),
2365                        Gtk::IconSize::from_name("synfig-small_icon") )));
2366        closebutton->add(*closebutton_image);
2367        closebutton->signal_clicked().connect(
2368                sigc::hide_return(sigc::mem_fun(*this,&studio::CanvasView::close_view)));
2369        closebutton->set_relief(Gtk::RELIEF_NONE);
2370        closebutton->show_all();
2371
2372        return event_box;
2373}
2374
2375bool
2376CanvasView::on_button_press_event(GdkEventButton * /* event */)
2377{
2378        if (this != App::get_selected_canvas_view())
2379                App::set_selected_canvas_view(this);
2380        return false;
2381        //return Dockable::on_button_press_event(event);
2382}
2383
2384bool
2385CanvasView::on_key_press_event(GdkEventKey* event)
2386{
2387        Gtk::Widget* focused_widget = App::main_window->get_focus();
2388        if(focused_widget && focused_widget_has_priority(focused_widget))
2389        {
2390                if(focused_widget->event((GdkEvent*)event))
2391                return true;
2392        }
2393        else if(Dockable::on_key_press_event(event))
2394                        return true;
2395                else
2396                        if (focused_widget) return focused_widget->event((GdkEvent*)event);
2397        return false;
2398}
2399
2400bool
2401CanvasView::focused_widget_has_priority(Gtk::Widget * focused)
2402{
2403        if(dynamic_cast<Gtk::Entry*>(focused))
2404                return true;
2405        return false;
2406}
2407
2408void
2409CanvasView::refresh_tables()
2410{
2411//      if(layer_tree_store_)layer_tree_store_->refresh();
2412//      if(children_tree_store_)children_tree_store_->refresh();
2413}
2414
2415void
2416CanvasView::rebuild_tables()
2417{
2418//      layer_tree_store_->rebuild();
2419//      children_tree_store_->rebuild();
2420}
2421
2422void
2423CanvasView::build_tables()
2424{
2425//      layer_tree_store_->rebuild();
2426//      children_tree_store_->rebuild();
2427}
2428
2429void
2430CanvasView::on_layer_toggle(synfig::Layer::Handle layer)
2431{
2432        synfigapp::Action::Handle action(synfigapp::Action::create("LayerActivate"));
2433        assert(action);
2434
2435        if(!action)
2436                return;
2437
2438        action->set_param("canvas",Canvas::Handle(layer->get_canvas()));
2439        if(!action->set_param("canvas_interface",canvas_interface()))
2440//      if(!action->set_param("canvas_interface",get_instance()->find_canvas_interface(layer->get_canvas())))
2441                synfig::error("LayerActivate didn't like CanvasInterface...?");
2442        action->set_param("time",get_time());
2443        action->set_param("layer",layer);
2444        action->set_param("new_status",!layer->active());
2445
2446        assert(action->is_ready());
2447
2448        canvas_interface()->get_instance()->perform_action(action);
2449}
2450
2451void
2452CanvasView::popup_param_menu(synfigapp::ValueDesc value_desc, float location, bool bezier)
2453{
2454        std::vector<Widget*> children = parammenu.get_children();
2455        for(std::vector<Widget*>::iterator i = children.begin(); i != children.end(); ++i)
2456                parammenu.remove(**i);
2457        get_instance()->make_param_menu(&parammenu,get_canvas(),value_desc,location,bezier);
2458        parammenu.popup(3,gtk_get_current_event_time());
2459}
2460
2461void
2462CanvasView::add_actions_to_menu(Gtk::Menu *menu, const synfigapp::Action::ParamList &param_list,synfigapp::Action::Category category)const
2463{
2464        get_instance()->add_actions_to_menu(menu, param_list, category);
2465}
2466
2467bool
2468CanvasView::on_layer_user_click(int button, Gtk::TreeRow /*row*/, LayerTree::ColumnID /*column_id*/)
2469{
2470        switch(button)
2471        {
2472        case 3:
2473                {
2474                        Gtk::MenuItem* menu = dynamic_cast<Gtk::MenuItem*>(App::ui_manager()->get_widget("/menu-main/menu-layer"));
2475                        if(menu && menu->get_submenu())
2476                        {
2477                                //menu->set_accel_group(App::ui_manager()->get_accel_group());
2478                                //menu->accelerate(*this);
2479                                menu->get_submenu()->popup(button,gtk_get_current_event_time());
2480                        }
2481
2482                        #if 0
2483                        bool multiple_selected=true;
2484
2485                        if(layer_tree->get_selection()->count_selected_rows()<=1)
2486                                multiple_selected=false;
2487
2488                        // If the clicked row is not selected, then unselect
2489                        // everything that isn't selected and select this row
2490                        if(multiple_selected && !layer_tree->get_selection()->is_selected(row))
2491                        {
2492                                layer_tree->get_selection()->unselect_all();
2493                                layer_tree->get_selection()->select(row);
2494                                multiple_selected=false;
2495                        }
2496
2497                        if(column_id==COLUMNID_TIME_TRACK)
2498                                return false;
2499
2500                        //synfigapp::ValueDesc value_desc(row[layer_param_tree_model.value_desc]);
2501                        //ValueNode::Handle value_node(row[layer_param_tree_model.value_node]);
2502                        //ValueNode::Handle parent_value_node;
2503                        //ValueBase value=row[layer_param_tree_model.value];
2504
2505                        //if(row.parent())
2506                        //{
2507                        //      parent_value_node=(*row.parent())[layer_tree_model.value_node];
2508                        //}
2509
2510                        {
2511                                Layer::Handle layer(row[layer_tree_model.layer]);
2512                                synfigapp::Action::ParamList param_list;
2513                                param_list.add("time",canvas_interface()->get_time());
2514                                param_list.add("canvas",Canvas::Handle(row[layer_tree_model.canvas]));
2515                                param_list.add("canvas_interface",canvas_interface());
2516                                if(!multiple_selected)
2517                                        param_list.add("layer",layer);
2518                                else
2519                                {
2520                                        synfigapp::SelectionManager::LayerList layer_list(get_selection_manager()->get_selected_layers());
2521                                        synfigapp::SelectionManager::LayerList::iterator iter;
2522
2523                                        for(iter=layer_list.begin();iter!=layer_list.end();++iter)
2524                                                param_list.add("layer",Layer::Handle(*iter));
2525                                }
2526
2527                                parammenu.items().clear();
2528
2529                                Gtk::Menu *newlayers(manage(new Gtk::Menu()));
2530                                // do we need this?  the code is all #ifdef'ed out anyway
2531                                // newlayers->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), newlayers));
2532                                build_new_layer_menu(*newlayers);
2533
2534                                parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("New Layer"),*newlayers));
2535                                if(!multiple_selected && etl::handle<Layer_PasteCanvas>::cast_dynamic(layer))
2536                                {
2537                                        parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Select All Children"),
2538                                                sigc::bind(
2539                                                        sigc::mem_fun(
2540                                                                *layer_tree,
2541                                                                &studio::LayerTree::select_all_children_layers
2542                                                        ),
2543                                                        layer
2544                                                )
2545                                        ));
2546                                }
2547
2548                                add_actions_to_menu(&parammenu, param_list,synfigapp::Action::CATEGORY_LAYER);
2549                                parammenu.popup(button,gtk_get_current_event_time());
2550                                return true;
2551                        }
2552/*
2553                        else if(column_id==LayerTree::COLUMNID_TIME_TRACK && value_node && handle<synfig::ValueNode_Animated>::cast_dynamic(value_node))
2554                        {
2555                                // Right-click on time track with animated
2556//                              trackmenu.popup(0,0);
2557                                return true;
2558                        }
2559                        else
2560                        {
2561                                if(!multiple_selected)
2562                                {
2563                                        popup_param_menu(value_desc);
2564                                        return true;
2565                                }
2566                                else
2567                                {
2568#warning update me!
2569#if 0
2570                                        parammenu.items().clear();
2571                                        parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Connect"),
2572                                                hide_return(sigc::mem_fun(*canvas_interface().get(),&synfigapp::CanvasInterface::connect_selected_layer_params))
2573                                        ));
2574                                        parammenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Disconnect"),
2575                                                hide_return(sigc::mem_fun(*canvas_interface().get(),&synfigapp::CanvasInterface::disconnect_selected_layer_params))
2576                                        ));
2577                                        parammenu.popup(0,0);
2578#endif
2579                                }
2580                                return true;
2581                        }
2582                */
2583#endif
2584}
2585                return true;
2586
2587        default:
2588                break;
2589        }
2590        return false;
2591}
2592
2593bool
2594CanvasView::on_children_user_click(int button, Gtk::TreeRow row, ChildrenTree::ColumnID column_id)
2595{
2596        switch(button)
2597        {
2598        case 3:
2599                {
2600                        if(column_id==COLUMNID_TIME_TRACK)
2601                                return false;
2602                        if(!(bool)row[children_tree_model.is_canvas])
2603                        {
2604                                synfigapp::ValueDesc value_desc=row[children_tree_model.value_desc];
2605                                if (!value_desc)
2606                                {
2607                                        //! \todo fix properly -- what is the child dialog for?
2608                                        synfig::info("preventing child dialog right-click crash");
2609                                        return true;
2610                                }
2611                                assert(value_desc);
2612                                popup_param_menu(value_desc);
2613                                return true;
2614                        }
2615                }
2616                return true;
2617
2618        default:
2619                break;
2620        }
2621        return false;
2622}
2623
2624bool
2625CanvasView::on_keyframe_tree_event(GdkEvent *event)
2626{
2627    switch(event->type)
2628    {
2629        case GDK_BUTTON_PRESS:
2630                switch(event->button.button)
2631                {
2632                        case 3:
2633                        {
2634                                //keyframemenu.popup(event->button.button,gtk_get_current_event_time());
2635                                return true;
2636                        }
2637                        break;
2638                }
2639                break;
2640        case GDK_MOTION_NOTIFY:
2641                break;
2642        case GDK_BUTTON_RELEASE:
2643                break;
2644        default:
2645                break;
2646        }
2647        return false;
2648}
2649
2650void
2651CanvasView::refresh_time_window()
2652{
2653        //THESE SHOULD AUTOMATICALLY BE TAKEN CARE OF
2654        //time_adjustment()->set_lower(time_window_adjustment()->get_value());
2655        //time_adjustment()->set_upper(time_window_adjustment()->get_value()+time_window_adjustment()->get_page_size());
2656
2657        time_adjustment()->set_page_increment(1.0); // One second
2658        time_adjustment()->set_page_size(0);
2659
2660        if(get_canvas())
2661                time_adjustment()->set_step_increment(1.0/get_canvas()->rend_desc().get_frame_rate());
2662        time_adjustment()->changed();
2663
2664        //NOTE THIS SHOULD HOOK INTO THE CORRECT SIGNALS...
2665        if(children_tree)
2666                children_tree->queue_draw();
2667}
2668
2669void
2670CanvasView::on_time_changed()
2671{
2672        Time time(get_time());
2673
2674        if (!is_time_equal_to_current_frame(soundProcessor.get_position(), 0.5))
2675                soundProcessor.set_position(time);
2676
2677#ifdef WITH_JACK
2678        if (jack_enabled && !jack_synchronizing && !is_time_equal_to_current_frame(jack_time - get_jack_offset()))
2679        {
2680                float fps = get_canvas()->rend_desc().get_frame_rate();
2681                jack_nframes_t sr = jack_get_sample_rate(jack_client);
2682                jack_nframes_t nframes = ((double)sr * (time + get_jack_offset()).round(fps));
2683                jack_transport_locate(jack_client, nframes);
2684        }
2685#endif
2686
2687        current_time_widget->set_value(time);
2688        try {
2689                get_canvas()->keyframe_list().find(time);
2690                current_time_widget->override_color(Gdk::RGBA("#FF0000"));
2691        }catch(...){
2692                current_time_widget->override_color(Gdk::RGBA("#000000"));
2693        }
2694
2695        if(get_time() != time_adjustment()->get_value())
2696        {
2697                //Recenters the window, causing it to jump (possibly undesirably... but whatever)
2698                if(time < time_window_adjustment()->get_value() ||
2699                        time > time_window_adjustment()->get_value()+time_window_adjustment()->get_page_size())
2700                {
2701                        time_window_adjustment()->set_value(
2702                                time-time_window_adjustment()->get_page_size()/2
2703                        );
2704                }
2705                time_adjustment()->set_value(time);
2706                time_adjustment()->value_changed();
2707
2708                // Shouldn't these trees just hook into
2709                // the time changed signal...?
2710                //YES THEY SHOULD...
2711                if(layer_tree)layer_tree->queue_draw();
2712                if(children_tree)children_tree->queue_draw();
2713        }
2714}
2715
2716void
2717CanvasView::time_zoom_in()
2718{
2719        float frame_rate = get_canvas()->rend_desc().get_frame_rate();
2720        Time min_page_size = 2/frame_rate;
2721
2722        time_window_adjustment()->set_page_size(time_window_adjustment()->get_page_size()*0.75);
2723        if (time_window_adjustment()->get_page_size() < min_page_size)
2724                time_window_adjustment()->set_page_size(min_page_size);
2725        time_window_adjustment()->set_page_increment(time_window_adjustment()->get_page_size());
2726        time_window_adjustment()->changed();
2727
2728        refresh_time_window();
2729}
2730
2731void
2732CanvasView::time_zoom_out()
2733{
2734        Time length = (get_canvas()->rend_desc().get_time_end() -
2735                                   get_canvas()->rend_desc().get_time_start());
2736
2737        time_window_adjustment()->set_page_size(time_window_adjustment()->get_page_size()/0.75);
2738        if (time_window_adjustment()->get_page_size() > length)
2739                time_window_adjustment()->set_page_size(length);
2740        time_window_adjustment()->set_page_increment(time_window_adjustment()->get_page_size());
2741        time_window_adjustment()->changed();
2742
2743        refresh_time_window();
2744}
2745
2746void
2747CanvasView::time_was_changed()
2748{
2749        synfig::Time time((synfig::Time)(double)time_adjustment()->get_value());
2750        set_time(time);
2751}
2752
2753void
2754CanvasView::on_edited_value(synfigapp::ValueDesc value_desc,synfig::ValueBase new_value)
2755{
2756        canvas_interface()->change_value(value_desc,new_value);
2757}
2758
2759/*
2760void
2761CanvasView::on_children_edited_value(const Glib::ustring&path_string,synfig::ValueBase value)
2762{
2763        Gtk::TreePath path(path_string);
2764
2765        const Gtk::TreeRow row = *(children_tree->get_model()->get_iter(path));
2766
2767        assert((bool)row[children_tree_model.is_value_node]);
2768
2769        synfigapp::ValueDesc value_desc=row[children_tree_model.value_desc];
2770        assert(value_desc);
2771
2772        on_edited_value(value_desc,value);
2773}
2774*/
2775
2776void
2777CanvasView::on_id_changed()
2778{
2779        update_title();
2780}
2781
2782void
2783CanvasView::on_mode_changed(synfigapp::CanvasInterface::Mode mode)
2784{
2785        if(toggling_animate_mode_)
2786                return;
2787        toggling_animate_mode_=true;
2788        // If the animate flag was set in mode...
2789        Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon_16x16");
2790        if(mode&synfigapp::MODE_ANIMATE)
2791        {
2792                Gtk::Image *icon;
2793                icon=manage(new Gtk::Image(Gtk::StockID("synfig-animate_mode_on"),iconsize));
2794                animatebutton->remove();
2795                animatebutton->add(*icon);
2796                animatebutton->set_tooltip_text(_("Turn off animate editing mode"));
2797                icon->set_padding(0,0);
2798                icon->show();
2799                animatebutton->set_active(true);
2800        }
2801        else
2802        {
2803                Gtk::Image *icon;
2804                icon=manage(new Gtk::Image(Gtk::StockID("synfig-animate_mode_off"),iconsize));
2805                animatebutton->remove();
2806                animatebutton->add(*icon);
2807                animatebutton->set_tooltip_text(_("Turn on animate editing mode"));
2808                icon->set_padding(0,0);
2809                icon->show();
2810                animatebutton->set_active(false);
2811        }
2812        //Keyframe lock icons
2813        if(mode&synfigapp::MODE_ANIMATE_FUTURE)
2814        {
2815                Gtk::Image *icon;
2816                icon=manage(new Gtk::Image(Gtk::StockID("synfig-keyframe_lock_future_on"),iconsize));
2817                futurekeyframebutton->remove();
2818                futurekeyframebutton->add(*icon);
2819                futurekeyframebutton->set_tooltip_text(_("Unlock future keyframes"));
2820                icon->set_padding(0,0);
2821                icon->show();
2822                futurekeyframebutton->set_active(true);
2823        }
2824        else
2825        {
2826                Gtk::Image *icon;
2827                icon=manage(new Gtk::Image(Gtk::StockID("synfig-keyframe_lock_future_off"),iconsize));
2828                futurekeyframebutton->remove();
2829                futurekeyframebutton->add(*icon);
2830                futurekeyframebutton->set_tooltip_text(_("Lock future keyframes"));
2831                icon->set_padding(0,0);
2832                icon->show();
2833                futurekeyframebutton->set_active(false);
2834        }
2835        if(mode&synfigapp::MODE_ANIMATE_PAST)
2836        {
2837                Gtk::Image *icon;
2838                icon=manage(new Gtk::Image(Gtk::StockID("synfig-keyframe_lock_past_on"),iconsize));
2839                pastkeyframebutton->remove();
2840                pastkeyframebutton->add(*icon);
2841                pastkeyframebutton->set_tooltip_text(_("Unlock past keyframes"));
2842                icon->set_padding(0,0);
2843                icon->show();
2844                pastkeyframebutton->set_active(true);
2845        }
2846        else
2847        {
2848                Gtk::Image *icon;
2849                icon=manage(new Gtk::Image(Gtk::StockID("synfig-keyframe_lock_past_off"),iconsize));
2850                pastkeyframebutton->remove();
2851                pastkeyframebutton->add(*icon);
2852                pastkeyframebutton->set_tooltip_text(_("Lock past  keyframes"));
2853                icon->set_padding(0,0);
2854                icon->show();
2855                pastkeyframebutton->set_active(false);
2856        }
2857
2858        work_area->queue_draw();
2859        toggling_animate_mode_=false;
2860}
2861
2862void
2863CanvasView::toggle_animatebutton()
2864{
2865        if(toggling_animate_mode_)
2866                return;
2867        if(get_mode()&synfigapp::MODE_ANIMATE)
2868                set_mode(get_mode()-synfigapp::MODE_ANIMATE);
2869        else
2870                set_mode(get_mode()|synfigapp::MODE_ANIMATE);
2871}
2872
2873void
2874CanvasView::toggle_timetrackbutton()
2875{
2876        if (timetrackbutton->get_active())
2877                timetrack->set_visible(true);
2878        else
2879                timetrack->set_visible(false);
2880}
2881
2882void
2883CanvasView::toggle_past_keyframe_button()
2884{
2885        if(toggling_animate_mode_)
2886                return;
2887        synfigapp::CanvasInterface::Mode mode(get_mode());
2888        if((mode&synfigapp::MODE_ANIMATE_PAST) )
2889                set_mode(get_mode()-synfigapp::MODE_ANIMATE_PAST);
2890        else
2891                set_mode((get_mode()|synfigapp::MODE_ANIMATE_PAST));
2892}
2893
2894
2895void
2896CanvasView::toggle_future_keyframe_button()
2897{
2898        if(toggling_animate_mode_)
2899                return;
2900        synfigapp::CanvasInterface::Mode mode(get_mode());
2901        if((mode&synfigapp::MODE_ANIMATE_FUTURE) )
2902                set_mode(get_mode()-synfigapp::MODE_ANIMATE_FUTURE);
2903        else
2904                set_mode(get_mode()|synfigapp::MODE_ANIMATE_FUTURE);
2905}
2906
2907bool
2908CanvasView::duck_change_param(const synfig::Point &value,synfig::Layer::Handle layer, synfig::String param_name)
2909{
2910        return canvas_interface()->change_value(synfigapp::ValueDesc(layer,param_name),value);
2911}
2912
2913void
2914CanvasView::selected_layer_color_set(synfig::Color color)
2915{
2916        synfigapp::SelectionManager::LayerList selected_list(get_selection_manager()->get_selected_layers());
2917        synfigapp::SelectionManager::LayerList::iterator iter;
2918
2919        // Create the action group
2920        //synfigapp::PassiveGrouper group(canvas_interface()->get_instance(),_("Set Colors"));
2921
2922        Layer::Handle layer;
2923        for(iter=selected_list.begin();iter!=selected_list.end();++iter)
2924        {
2925                if(*iter==layer)
2926                        continue;
2927                layer=*iter;
2928                on_edited_value(synfigapp::ValueDesc(layer,"color"),color);
2929        }
2930}
2931
2932void
2933CanvasView::queue_rebuild_ducks()
2934{
2935#if 0
2936        if(rebuild_ducks_queued)
2937                return;
2938#else
2939        if(rebuild_ducks_queued)
2940                queue_rebuild_ducks_connection.disconnect();
2941#endif
2942
2943        queue_rebuild_ducks_connection=Glib::signal_timeout().connect(
2944                sigc::bind_return(
2945                        sigc::mem_fun(*this,&CanvasView::rebuild_ducks),
2946                        false
2947                ),
2948                50
2949        );
2950
2951        rebuild_ducks_queued=true;
2952}
2953
2954void
2955CanvasView::rebuild_ducks()
2956{
2957        /*static int i=0;
2958        i++;
2959        if(i>30)
2960                synfig::info("%d",i/(i-i));
2961        */
2962
2963        rebuild_ducks_queued=false;
2964        //queue_rebuild_ducks_connection.disconnect();
2965
2966        if(work_area->is_dragging())
2967        {
2968                queue_rebuild_ducks();
2969                return;
2970        }
2971
2972        if(!duck_refresh_flag)
2973        {
2974                duck_refresh_needed=true;
2975                return;
2976        }
2977
2978        bbox=Rect::zero();
2979
2980        work_area->clear_ducks();
2981        work_area->clear_curr_transform_stack();
2982        work_area->set_time(get_time());
2983        get_canvas()->set_time(get_time());
2984
2985        //get_canvas()->set_time(get_time());
2986
2987        // First do the layers...
2988        do{
2989                synfigapp::SelectionManager::LayerList selected_list(get_selection_manager()->get_selected_layers());
2990                std::set<synfig::Layer::Handle> layer_set(selected_list.begin(),selected_list.end());
2991
2992                synfig::TransformStack transform_stack;
2993
2994                work_area->add_ducks_layers(get_canvas(), layer_set, this,transform_stack);
2995
2996        }while(0);
2997
2998        // Now do the children
2999        do{
3000                synfigapp::SelectionManager::ChildrenList selected_list(get_selection_manager()->get_selected_children());
3001                synfigapp::SelectionManager::ChildrenList::iterator iter;
3002                synfig::TransformStack transform_stack;
3003
3004                if(selected_list.empty())
3005                {
3006                        break;
3007                }
3008                else
3009                {
3010                        for(iter=selected_list.begin();iter!=selected_list.end();++iter)
3011                        {
3012                                work_area->add_to_ducks(*iter,this,transform_stack);
3013                        }
3014                }
3015        }while(0);
3016        work_area->refresh_selected_ducks();
3017        work_area->queue_draw_preview();
3018}
3019
3020void
3021CanvasView::decrease_low_res_pixel_size()
3022{
3023        if(changing_resolution_)
3024                return;
3025        changing_resolution_=true;
3026        list<int> sizes = CanvasView::get_pixel_sizes();
3027        int pixel_size = work_area->get_low_res_pixel_size();
3028        for (list<int>::iterator iter = sizes.begin(); iter != sizes.end(); iter++)
3029                if (*iter == pixel_size)
3030                {
3031                        if (iter == sizes.begin())
3032                                // we already have the smallest low-res pixels possible - turn off low-res instead
3033                                work_area->set_low_resolution_flag(false);
3034                        else
3035                        {
3036                                iter--;
3037                                Glib::RefPtr<Gtk::Action> action = action_group->get_action(strprintf("lowres-pixel-%d", *iter));
3038                                action->activate(); // to make sure the radiobutton in the menu is updated too
3039                                work_area->set_low_resolution_flag(true);
3040                        }
3041                        break;
3042                }
3043        // Update the "toggle-low-res" action
3044        Glib::RefPtr<Gtk::ToggleAction> action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("toggle-low-res"));
3045        action->set_active(work_area->get_low_resolution_flag());
3046        // Update toggle low res button
3047        resolutiondial.update_lowres(work_area->get_low_resolution_flag());
3048        changing_resolution_=false;
3049}
3050
3051void
3052CanvasView::increase_low_res_pixel_size()
3053{
3054        if(changing_resolution_)
3055                return;
3056        changing_resolution_=true;
3057        list<int> sizes = CanvasView::get_pixel_sizes();
3058        int pixel_size = work_area->get_low_res_pixel_size();
3059        if (!work_area->get_low_resolution_flag())
3060        {
3061                // We were using "hi res" so change it to low res.
3062                work_area->set_low_resolution_flag(true);
3063                // Update the "toggle-low-res" action
3064                Glib::RefPtr<Gtk::ToggleAction> action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("toggle-low-res"));
3065                action->set_active(true);
3066                // Update the toggle low res button
3067                resolutiondial.update_lowres(true);
3068                changing_resolution_=false;
3069                return;
3070        }
3071
3072        for (list<int>::iterator iter = sizes.begin(); iter != sizes.end(); iter++)
3073                if (*iter == pixel_size)
3074                {
3075                        iter++;
3076                        if (iter != sizes.end())
3077                        {
3078                                Glib::RefPtr<Gtk::Action> action = action_group->get_action(strprintf("lowres-pixel-%d", *iter));
3079                                action->activate(); // to make sure the radiobutton in the menu is updated too
3080                                work_area->set_low_resolution_flag(true);
3081                        }
3082                        break;
3083                }
3084        // Update the "toggle-low-res" action
3085        Glib::RefPtr<Gtk::ToggleAction> action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("toggle-low-res"));
3086        action->set_active(work_area->get_low_resolution_flag());
3087        // Update toggle low res button
3088        resolutiondial.update_lowres(work_area->get_low_resolution_flag());
3089        changing_resolution_=false;
3090}
3091
3092void
3093CanvasView::toggle_low_res_pixel_flag()
3094{
3095        if(changing_resolution_)
3096                return;
3097        changing_resolution_=true;
3098        work_area->toggle_low_resolution_flag();
3099        // Update the toggle low res button
3100        resolutiondial.update_lowres(work_area->get_low_resolution_flag());
3101        // Update the "toggle-low-res" action
3102        Glib::RefPtr<Gtk::ToggleAction> action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("toggle-low-res"));
3103        action->set_active(work_area->get_low_resolution_flag());
3104        changing_resolution_=false;
3105}
3106
3107void
3108CanvasView::update_quality()
3109{
3110        //if(working_depth)
3111        //              return;
3112        if(updating_quality_)
3113                return;
3114        updating_quality_=true;
3115        work_area->set_quality((int) quality_spin->get_value());
3116        // Update Quality Radio actions
3117        Glib::RefPtr<Gtk::RadioAction> action=Glib::RefPtr<Gtk::RadioAction>::cast_dynamic(
3118                action_group->get_action(strprintf("quality-%02d",(int) quality_spin->get_value()))
3119                );
3120        action->set_active();
3121
3122        updating_quality_=false;
3123}
3124
3125void
3126CanvasView::set_quality(int x)
3127{
3128        if(updating_quality_)
3129                return;
3130        work_area->set_quality(x);
3131
3132        // quality_spin creation is commented at QUALITY_SPIN_DISABLED in CanvasView::create_display_bar
3133        // Update the quality spin button
3134        // quality_spin->set_value(x);
3135}
3136
3137void
3138CanvasView::set_onion_skins()
3139{
3140        if(toggling_onion_skin)
3141                return;
3142        int onion_skins[2];
3143        onion_skins[0]=past_onion_spin->get_value();
3144        onion_skins[1]=future_onion_spin->get_value();
3145        work_area->set_onion_skins(onion_skins);
3146}
3147
3148void
3149CanvasView::toggle_show_grid()
3150{
3151        if(toggling_show_grid)
3152                return;
3153        toggling_show_grid=true;
3154        work_area->toggle_grid();
3155        // Update the toggle grid show action
3156        set_grid_show_toggle(work_area->grid_status());
3157        // Update the toggle grid show check button
3158        show_grid->set_active(work_area->grid_status());
3159        toggling_show_grid=false;
3160}
3161
3162void
3163CanvasView::toggle_snap_grid()
3164{
3165        if(toggling_snap_grid)
3166                return;
3167        toggling_snap_grid=true;
3168        work_area->toggle_grid_snap();
3169        // Update the toggle grid snap action
3170        set_grid_snap_toggle(work_area->get_grid_snap());
3171        // Update the toggle grid snap check button
3172        snap_grid->set_active(work_area->get_grid_snap());
3173        toggling_snap_grid=false;
3174}
3175
3176void
3177CanvasView::toggle_onion_skin()
3178{
3179        if(toggling_onion_skin)
3180                return;
3181        toggling_onion_skin=true;
3182        work_area->toggle_onion_skin();
3183        // Update the toggle onion skin action
3184        set_onion_skin_toggle(work_area->get_onion_skin());
3185        // Update the toggle grid snap check button
3186        onion_skin->set_active(work_area->get_onion_skin());
3187        toggling_onion_skin=false;
3188}
3189
3190void
3191CanvasView::on_dirty_preview()
3192{
3193        if(!is_playing_)
3194        {
3195                IsWorking is_working(*this);
3196
3197                work_area->queue_render_preview();
3198        }
3199}
3200
3201void
3202CanvasView::play_async()
3203{
3204        if(is_playing())return;
3205
3206        playing_timer.reset();
3207        playing_time = work_area->get_time();
3208
3209        // If we are already at the end of time, start over
3210        if(playing_time == get_canvas()->rend_desc().get_time_end())
3211                playing_time = get_canvas()->rend_desc().get_time_start();
3212
3213        is_playing_=true;
3214
3215        work_area->clear_ducks();
3216
3217        float fps = get_canvas()->rend_desc().get_frame_rate();
3218        int timeout = fps <= 0.f ? 0 : (int)roundf(500.f/fps);
3219        if (timeout < 10) timeout = 10;
3220
3221        framedial->toggle_play_pause_button(!is_playing());
3222
3223        soundProcessor.clear();
3224        canvas_interface()->get_canvas()->fill_sound_processor(soundProcessor);
3225        soundProcessor.set_position(canvas_interface()->get_canvas()->get_time());
3226        soundProcessor.set_playing(true);
3227
3228        playing_connection = Glib::signal_timeout().connect(
3229                sigc::bind_return( sigc::mem_fun(*this, &studio::CanvasView::on_play_timeout), true ),
3230                timeout,
3231                Glib::PRIORITY_LOW);
3232}
3233
3234void
3235CanvasView::stop_async()
3236{
3237        playing_connection.disconnect();
3238        soundProcessor.set_playing(false);
3239        is_playing_=false;
3240        framedial->toggle_play_pause_button(!is_playing());
3241}
3242
3243void
3244CanvasView::on_play_timeout()
3245{
3246        Time time;
3247        // Used ifdef WITH_JACK
3248        Time starttime = get_canvas()->rend_desc().get_time_start();
3249        Time endtime = get_canvas()->rend_desc().get_time_end();
3250
3251        if (jack_enabled)
3252        {
3253#ifdef WITH_JACK
3254                jack_position_t pos;
3255                jack_transport_query(jack_client, &pos);
3256                jack_time = Time((Time::value_type)pos.frame/(Time::value_type)pos.frame_rate);
3257                time = jack_time - get_jack_offset();
3258                if (time > endtime) time = endtime;
3259                if (time < starttime) time = starttime;
3260#endif
3261        }
3262        else
3263        {
3264                time = playing_time + playing_timer();
3265                if (time >= endtime) {
3266                        time_adjustment()->set_value(endtime);
3267                        time_adjustment()->value_changed();
3268                        stop_async();
3269                        return;
3270                }
3271        }
3272
3273        //Clamp the time window so we can see the time value as it races across the horizon
3274        bool timewindreset = false;
3275
3276        while( time > Time(time_window_adjustment()->get_sub_upper()) )
3277        {
3278                time_window_adjustment()->set_value(
3279                                min(
3280                                        time_window_adjustment()->get_value()+time_window_adjustment()->get_page_size()/2,
3281                                        time_window_adjustment()->get_upper()-time_window_adjustment()->get_page_size() )
3282                        );
3283                timewindreset = true;
3284        }
3285
3286        while( time < Time(time_window_adjustment()->get_sub_lower()) )
3287        {
3288                time_window_adjustment()->set_value(
3289                        max(
3290                                time_window_adjustment()->get_value()-time_window_adjustment()->get_page_size()/2,
3291                                time_window_adjustment()->get_lower())
3292                );
3293
3294                timewindreset = true;
3295        }
3296
3297        //we need to tell people that the value changed
3298        if(timewindreset) time_window_adjustment()->value_changed();
3299
3300        //update actual time to next step
3301        time_adjustment()->set_value(time);
3302        time_adjustment()->value_changed();
3303
3304        if(!work_area->sync_render_preview())
3305                stop_async();
3306}
3307
3308
3309
3310void
3311CanvasView::play()
3312{
3313        assert(get_canvas());
3314
3315        // If we are already busy, don't play!
3316        if(working_depth)return;
3317
3318        // Set us up as working
3319        IsWorking is_working(*this);
3320
3321        etl::clock timer;
3322        Time
3323                time=work_area->get_time(),
3324                endtime=get_canvas()->rend_desc().get_time_end();
3325
3326        // If we are already at the end of time, start over
3327        if(time==endtime)
3328                time=get_canvas()->rend_desc().get_time_start();
3329
3330        is_playing_=true;
3331
3332        work_area->clear_ducks();
3333
3334        for(timer.reset(); time + timer() < endtime;)
3335        {
3336                //Clamp the time window so we can see the time value as it races across the horizon
3337                bool timewindreset = false;
3338
3339                while( time + timer() > Time(time_window_adjustment()->get_sub_upper()) )
3340                {
3341                        time_window_adjustment()->set_value(
3342                                        min(
3343                                                time_window_adjustment()->get_value()+time_window_adjustment()->get_page_size()/2,
3344                                                time_window_adjustment()->get_upper()-time_window_adjustment()->get_page_size() )
3345                                );
3346                        timewindreset = true;
3347                }
3348
3349                while( time + timer() < Time(time_window_adjustment()->get_sub_lower()) )
3350                {
3351                        time_window_adjustment()->set_value(
3352                                max(
3353                                        time_window_adjustment()->get_value()-time_window_adjustment()->get_page_size()/2,
3354                                        time_window_adjustment()->get_lower())
3355                        );
3356
3357                        timewindreset = true;
3358                }
3359
3360                //we need to tell people that the value changed
3361                if(timewindreset) time_window_adjustment()->value_changed();
3362
3363                //update actual time to next step
3364                time_adjustment()->set_value(time+timer());
3365                time_adjustment()->value_changed();
3366
3367                if(!work_area->sync_render_preview())
3368                        break;
3369
3370                // wait for the workarea to refresh itself
3371                while (studio::App::events_pending())
3372                        studio::App::iteration(false);
3373
3374                if(get_cancel_status())
3375                {
3376                        is_playing_=false;
3377                        return;
3378                }
3379        }
3380
3381        is_playing_=false;
3382        time_adjustment()->set_value(endtime);
3383        time_adjustment()->value_changed();
3384}
3385
3386void
3387CanvasView::show_tables()
3388{
3389/*
3390        Smach::event_result x(process_event_key(EVENT_TABLES_SHOW));
3391        if(x==Smach::RESULT_OK || x==Smach::RESULT_ACCEPT)
3392        {
3393                Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon");
3394                treetogglebutton->remove();
3395                treetogglebutton->add(*manage(new Gtk::Image(Gtk::StockID("gtk-go-down"),iconsize)));
3396                treetogglebutton->show_all();
3397                notebook->show();
3398        }
3399*/
3400}
3401
3402void
3403CanvasView::hide_tables()
3404{
3405/*
3406        Smach::event_result x(process_event_key(EVENT_TABLES_HIDE));
3407        if(x==Smach::RESULT_OK || x==Smach::RESULT_ACCEPT)
3408        {
3409                Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon");
3410                treetogglebutton->remove();
3411                treetogglebutton->add(*manage(new Gtk::Image(Gtk::StockID("gtk-go-up"),iconsize)));
3412                treetogglebutton->show_all();
3413                notebook->hide();
3414        }
3415*/
3416}
3417
3418bool
3419CanvasView::tables_are_visible()
3420{
3421//      return notebook->is_visible();
3422        return false;
3423}
3424
3425void
3426CanvasView::toggle_tables()
3427{
3428//      if(tables_are_visible())
3429//              hide_tables();
3430//      else
3431//              show_tables();
3432}
3433
3434void
3435CanvasView::show_timebar()
3436{
3437        timebar->show();
3438        //current_time_widget->show(); // not needed now that belongs to the timebar
3439
3440        //keyframe_tab_child->show();
3441        if(layer_tree)
3442                layer_tree->set_show_timetrack(true);
3443        if(children_tree)
3444                children_tree->set_show_timetrack(true);
3445}
3446
3447void
3448CanvasView::hide_timebar()
3449{
3450        timebar->hide();
3451        //current_time_widget->hide(); // not needed now that belongs to the timebar
3452        //keyframe_tab_child->hide();
3453        if(layer_tree)
3454                layer_tree->set_show_timetrack(false);
3455        if(children_tree)
3456                children_tree->set_show_timetrack(false);
3457}
3458
3459void
3460CanvasView::set_sensitive_timebar(bool sensitive)
3461{
3462        timebar->set_sensitive(sensitive);
3463        //current_time_widget->set_sensitive(sensitive); //not needed now that belongs to timebar
3464        //keyframe_tab_child->set_sensitive(sensitive);
3465        if(layer_tree)
3466                layer_tree->set_sensitive(sensitive);
3467        if(children_tree)
3468                children_tree->set_sensitive(sensitive);
3469}
3470
3471static void
3472set_waypoint_model(std::set<synfig::Waypoint, std::less<UniqueID> > waypoints,
3473                                   Waypoint::Model model,
3474                                   etl::loose_handle<synfigapp::CanvasInterface> canvas_interface)
3475{
3476        // Create the action group
3477        synfigapp::Action::PassiveGrouper group(canvas_interface->get_instance().get(),_("Change Waypoint Group"));
3478
3479        std::set<synfig::Waypoint, std::less<UniqueID> >::const_iterator iter;
3480        for(iter=waypoints.begin();iter!=waypoints.end();++iter)
3481        {
3482                Waypoint waypoint(*iter);
3483                waypoint.apply_model(model);
3484
3485                synfigapp::Action::Handle action(synfigapp::Action::create("WaypointSet"));
3486
3487                assert(action);
3488
3489                action->set_param("canvas",canvas_interface->get_canvas());
3490                action->set_param("canvas_interface",canvas_interface);
3491
3492                action->set_param("waypoint",waypoint);
3493                action->set_param("value_node",waypoint.get_parent_value_node());
3494
3495                if(!canvas_interface->get_instance()->perform_action(action))
3496                {
3497                        group.cancel();
3498                        return;
3499                }
3500        }
3501}
3502
3503static void
3504duplicate_waypoints(std::set<synfig::Waypoint, std::less<UniqueID> > waypoints,
3505                                        etl::loose_handle<synfigapp::CanvasInterface> canvas_interface)
3506{
3507        // Create the action group
3508        synfigapp::Action::PassiveGrouper group(canvas_interface->get_instance().get(),_("Duplicate Waypoints"));
3509
3510        std::set<synfig::Waypoint, std::less<UniqueID> >::const_iterator iter;
3511        for (iter = waypoints.begin(); iter != waypoints.end(); iter++)
3512        {
3513                Waypoint waypoint(*iter);
3514                ValueNode::Handle value_node(iter->get_parent_value_node());
3515                canvas_interface->waypoint_duplicate(value_node, waypoint);
3516        }
3517}
3518
3519static void
3520remove_waypoints(std::set<synfig::Waypoint, std::less<UniqueID> > waypoints,
3521                                 etl::loose_handle<synfigapp::CanvasInterface> canvas_interface)
3522{
3523        // Create the action group
3524        synfigapp::Action::PassiveGrouper group(canvas_interface->get_instance().get(),_("Remove Waypoints"));
3525
3526        std::set<synfig::Waypoint, std::less<UniqueID> >::const_iterator iter;
3527        for (iter = waypoints.begin(); iter != waypoints.end(); iter++)
3528        {
3529                Waypoint waypoint(*iter);
3530                ValueNode::Handle value_node(iter->get_parent_value_node());
3531                canvas_interface->waypoint_remove(value_node, waypoint);
3532        }
3533}
3534
3535void
3536CanvasView::on_waypoint_clicked_canvasview(synfigapp::ValueDesc value_desc,
3537                                                                                   std::set<synfig::Waypoint, std::less<UniqueID> > waypoint_set,
3538                                                                                   int button)
3539{
3540        int size = waypoint_set.size();
3541        Waypoint waypoint(*(waypoint_set.begin()));
3542        Time time(waypoint.get_time());
3543
3544        if (size == 1)
3545        {
3546                waypoint_dialog.set_value_desc(value_desc);
3547                waypoint_dialog.set_waypoint(waypoint);
3548        }
3549
3550        switch(button)
3551        {
3552        case -1:
3553                if (size == 1)
3554                        waypoint_dialog.show();
3555                break;
3556        case 2:
3557        {
3558                Gtk::Menu* waypoint_menu(manage(new Gtk::Menu()));
3559                waypoint_menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), waypoint_menu));
3560
3561                Gtk::Menu* interp_menu_in(manage(new Gtk::Menu()));
3562                Gtk::Menu* interp_menu_out(manage(new Gtk::Menu()));
3563                Gtk::Menu* interp_menu_both(manage(new Gtk::Menu()));
3564                Gtk::MenuItem *item = NULL;
3565
3566                {
3567                        Waypoint::Model model;
3568
3569                        #define APPEND_MENU_ITEM(menu, StockId, Text) \
3570                                item = manage(new Gtk::ImageMenuItem( \
3571                                        *manage(new Gtk::Image(Gtk::StockID(StockId),Gtk::IconSize::from_name("synfig-small_icon"))), \
3572                                        _(Text) )); \
3573                                item->set_use_underline(true); \
3574                                item->signal_activate().connect( \
3575                                        sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface())); \
3576                                item->show_all(); \
3577                                menu->append(*item);
3578
3579                        #define APPEND_ITEMS_TO_ALL_MENUS3(Interpolation, StockId, TextIn, TextOut, TextBoth) \
3580                                model.reset(); \
3581                                model.set_before(Interpolation); \
3582                                APPEND_MENU_ITEM(interp_menu_in, StockId, TextIn) \
3583                                model.reset(); \
3584                                model.set_after(Interpolation); \
3585                                APPEND_MENU_ITEM(interp_menu_out, StockId, TextOut) \
3586                                model.set_before(Interpolation); \
3587                                APPEND_MENU_ITEM(interp_menu_both, StockId, TextBoth)
3588
3589                        #define APPEND_ITEMS_TO_ALL_MENUS(Interpolation, StockId, Text) \
3590                                APPEND_ITEMS_TO_ALL_MENUS3(Interpolation, StockId, Text, Text, Text)
3591
3592                        APPEND_ITEMS_TO_ALL_MENUS(INTERPOLATION_TCB, "synfig-interpolation_type_tcb", _("_TCB"))
3593                        APPEND_ITEMS_TO_ALL_MENUS(INTERPOLATION_LINEAR, "synfig-interpolation_type_linear", _("_Linear"))
3594                        APPEND_ITEMS_TO_ALL_MENUS3(INTERPOLATION_HALT, "synfig-interpolation_type_ease", _("_Ease In"), _("_Ease Out"), _("_Ease In/Out"))
3595                        APPEND_ITEMS_TO_ALL_MENUS(INTERPOLATION_CONSTANT, "synfig-interpolation_type_const", _("_Constant"))
3596                        APPEND_ITEMS_TO_ALL_MENUS(INTERPOLATION_CLAMPED, "synfig-interpolation_type_clamped", _("_Clamped"))
3597
3598                        #undef APPEND_ITEMS_TO_ALL_MENUS
3599                        #undef APPEND_ITEMS_TO_ALL_MENUS3
3600                        #undef APPEND_MENU_ITEM
3601                }
3602
3603                // ------------------------------------------------------------------------
3604                if (size == 1)
3605                {
3606                        const synfigapp::ValueDesc value_desc(synfig::ValueNode_Animated::Handle::cast_reinterpret(waypoint.get_parent_value_node()), time);
3607                        get_instance()->make_param_menu(waypoint_menu,canvas_interface()->get_canvas(),value_desc,0.5f);
3608
3609                        // ------------------------------------------------------------------------
3610                        item = manage(new Gtk::SeparatorMenuItem());
3611                        item->show();
3612                        waypoint_menu->append(*item);
3613                }
3614
3615                // ------------------------------------------------------------------------
3616                item = manage(new Gtk::MenuItem(_("_Jump To")));
3617                item->set_use_underline(true);
3618                item->signal_activate().connect(
3619                        sigc::bind(sigc::mem_fun(*canvas_interface(), &synfigapp::CanvasInterface::set_time), time));
3620                item->show();
3621                waypoint_menu->append(*item);
3622
3623                item = manage(new Gtk::MenuItem(_("_Duplicate")));
3624                item->set_use_underline(true);
3625                item->signal_activate().connect(
3626                        sigc::bind(sigc::ptr_fun(duplicate_waypoints), waypoint_set, canvas_interface()));
3627                item->show();
3628                waypoint_menu->append(*item);
3629
3630                item = manage(new Gtk::MenuItem(size == 1 ? _("_Remove") : strprintf(_("_Remove %d Waypoints"), size)));
3631                item->set_use_underline(true);
3632                item->signal_activate().connect(
3633                        sigc::bind(sigc::ptr_fun(remove_waypoints), waypoint_set, canvas_interface()));
3634                item->show();
3635                waypoint_menu->append(*item);
3636
3637                if (size == 1 && value_desc.is_valid())
3638                {
3639                        item = manage(new Gtk::MenuItem(_("_Edit")));
3640                        item->set_use_underline(true);
3641                        item->signal_activate().connect(
3642                                        sigc::mem_fun(waypoint_dialog,&Gtk::Widget::show));
3643                        item->show();
3644                        waypoint_menu->append(*item);
3645                }
3646
3647                // ------------------------------------------------------------------------
3648                item = manage(new Gtk::SeparatorMenuItem());
3649                item->show();
3650                waypoint_menu->append(*item);
3651
3652                // ------------------------------------------------------------------------
3653                item = manage(new Gtk::MenuItem(_("_Both")));
3654                item->set_use_underline(true);
3655                item->set_submenu(*interp_menu_both);
3656                item->show();
3657                waypoint_menu->append(*item);
3658
3659                item = manage(new Gtk::MenuItem(_("_In")));
3660                item->set_use_underline(true);
3661                item->set_submenu(*interp_menu_in);
3662                item->show();
3663                waypoint_menu->append(*item);
3664
3665                item = manage(new Gtk::MenuItem(_("_Out")));
3666                item->set_use_underline(true);
3667                item->set_submenu(*interp_menu_out);
3668                item->show();
3669                waypoint_menu->append(*item);
3670
3671                // ------------------------------------------------------------------------
3672                waypoint_menu->popup(button+1,gtk_get_current_event_time());
3673        }
3674        break;
3675
3676        default:
3677                break;
3678        }
3679}
3680
3681void
3682CanvasView::on_waypoint_changed()
3683{
3684        synfigapp::Action::ParamList param_list;
3685        param_list.add("canvas",get_canvas());
3686        param_list.add("canvas_interface",canvas_interface());
3687        param_list.add("value_node",waypoint_dialog.get_value_desc().get_value_node());
3688        param_list.add("waypoint",waypoint_dialog.get_waypoint());
3689//      param_list.add("time",canvas_interface()->get_time());
3690
3691        get_instance()->process_action("WaypointSetSmart", param_list);
3692}
3693
3694void
3695CanvasView::on_waypoint_delete()
3696{
3697        synfigapp::Action::ParamList param_list;
3698        param_list.add("canvas",get_canvas());
3699        param_list.add("canvas_interface",canvas_interface());
3700        param_list.add("value_node",waypoint_dialog.get_value_desc().get_value_node());
3701        param_list.add("waypoint",waypoint_dialog.get_waypoint());
3702//      param_list.add("time",canvas_interface()->get_time());
3703
3704        get_instance()->process_action("WaypointRemove", param_list);
3705}
3706
3707void
3708CanvasView::on_drop_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int /*x*/, int /*y*/, const Gtk::SelectionData& selection_data_, guint /*info*/, guint time)
3709{
3710        // We will make this true once we have a solid drop
3711        bool success(false);
3712        //synfig::info("Dropped data of type \"%s\"",selection_data.get_data_type());
3713        //synfig::info("Dropped data of target \"%s\"",gdk_atom_name(selection_data->target));
3714        //synfig::info("selection=\"%s\"",gdk_atom_name(selection_data->selection));
3715
3716        if ((selection_data_.get_length() >= 0) && (selection_data_.get_format() == 8))
3717        {
3718                if(synfig::String(selection_data_.get_data_type())=="STRING"
3719                || synfig::String(selection_data_.get_data_type())=="text/plain")do
3720                {
3721                        synfig::String selection_data((gchar *)(selection_data_.get_data()));
3722
3723                        Layer::Handle layer(synfig::Layer::create("Text"));
3724                        if(!layer)
3725                                break;
3726                        if(!layer->set_param("text",ValueBase(selection_data)))
3727                                break;
3728
3729                        synfigapp::Action::Handle       action(synfigapp::Action::create("LayerAdd"));
3730
3731                        assert(action);
3732                        if(!action)
3733                                break;
3734
3735                        action->set_param("canvas",get_canvas());
3736                        action->set_param("canvas_interface",canvas_interface());
3737                        action->set_param("new",layer);
3738
3739                        if(!get_instance()->perform_action(action))
3740                                break;
3741
3742                        // Ok, we have successfully imported at least one item.
3743                        success=true;
3744                } while(0); // END of "STRING"
3745
3746                if(synfig::String(selection_data_.get_data_type())=="text/uri-list")
3747                {
3748                        synfig::String selection_data((gchar *)(selection_data_.get_data()));
3749
3750                        // For some reason, GTK hands us a list of URLs separated
3751                        // by not only Carriage-Returns, but also Line-Feeds.
3752                        // Line-Feeds will mess us up. Remove all the line-feeds.
3753                        while(selection_data.find_first_of('\r')!=synfig::String::npos)
3754                                selection_data.erase(selection_data.begin()+selection_data.find_first_of('\r'));
3755
3756                        std::stringstream stream(selection_data);
3757
3758                        //synfigapp::PassiveGrouper group(canvas_interface()->get_instance(),_("Insert Image"));
3759                        while(stream)
3760                        {
3761                                synfig::String URI;
3762                                getline(stream, URI);
3763
3764                                // If we don't have an URI, move on.
3765                                if(URI.empty())
3766                                        continue;
3767
3768                                // Extract protocol name from URI.
3769                                synfig::String protocol( Glib::uri_parse_scheme(URI) );
3770                                if(protocol.empty())
3771                                {
3772                                        synfig::warning("Cannot extract protocol from URI \"%s\"", URI.c_str());
3773                                        continue;
3774                                }
3775
3776                                // Only 'file' protocol supported
3777                                if(protocol != "file")
3778                                {
3779                                        synfig::warning("Protocol \"%s\" is unsupported (URI \"%s\")", protocol.c_str(), URI.c_str());
3780                                        continue;
3781                                }
3782
3783                                // Converts an escaped UTF-8 encoded URI to a local filename
3784                                // in the encoding used for filenames.
3785                                synfig::String filename( Glib::filename_from_uri(URI) );
3786                                if(filename.empty())
3787                                {
3788                                        synfig::warning("Cannot extract filename from URI \"%s\"", URI.c_str());
3789                                        continue;
3790                                }
3791
3792                                String ext( filename_extension(filename) );
3793                                if(!ext.empty()) ext = ext.substr(1); // skip initial '.'
3794
3795                                // If this is a SIF file, then we need to do things slightly differently
3796                                if(ext == "sketch")
3797                                {
3798                                        if(work_area->load_sketch(filename))
3799                                        {
3800                                                success=true;
3801                                                work_area->queue_draw();
3802                                        }
3803                                }
3804                                else
3805                                {
3806                                        String errors, warnings;
3807                                        if(canvas_interface()->import(filename, errors, warnings, App::resize_imported_images))
3808                                                success=true;
3809                                        if (warnings != "")
3810                                                App::dialog_message_1b(
3811                                                                "WARNING",
3812                                                                strprintf("%s:\n\n%s",_("Warning"),warnings.c_str()),
3813                                                                "details",
3814                                                                _("Close"));
3815                                }
3816                        }
3817                } // END of "text/uri-list"
3818        }
3819        else
3820                ui_interface_->error("Drop failed: bad selection data");
3821
3822        // Finish the drag
3823        context->drag_finish(success, false, time);
3824}
3825
3826void
3827CanvasView::on_keyframe_add_pressed()
3828{
3829        synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeAdd"));
3830
3831        if(!action)
3832        {
3833                ui_interface_->error("I am unable to find the appropriate action");
3834                return;
3835        }
3836
3837        action->set_param("canvas",get_canvas());
3838        action->set_param("canvas_interface",canvas_interface());
3839        action->set_param("keyframe",Keyframe(get_time()));
3840
3841        canvas_interface()->get_instance()->perform_action(action);
3842}
3843
3844void
3845CanvasView::on_keyframe_duplicate_pressed()
3846{
3847        const KeyframeTreeStore::Model model;
3848        const Gtk::TreeRow row(*keyframe_tree->get_selection()->get_selected());
3849        Keyframe keyframe;
3850        if(!row)
3851        {
3852                ui_interface_->error("I am unable to duplicate the keyframe");
3853                return;
3854        }
3855        keyframe=row[model.keyframe];
3856
3857        synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeDuplicate"));
3858
3859        if(!action)
3860        {
3861                ui_interface_->error("I am unable to find the appropriate action");
3862                return;
3863        }
3864
3865        action->set_param("canvas",get_canvas());
3866        action->set_param("canvas_interface",canvas_interface());
3867        action->set_param("keyframe",keyframe);
3868        action->set_param("time",get_time());
3869
3870        canvas_interface()->get_instance()->perform_action(action);
3871}
3872
3873void
3874CanvasView::on_keyframe_remove_pressed()
3875{
3876        const KeyframeTreeStore::Model model;
3877        const Gtk::TreeRow row(*keyframe_tree->get_selection()->get_selected());
3878        Keyframe keyframe;
3879        if(!row)
3880        {
3881                ui_interface_->error("I am unable to remove the keyframe");
3882                return;
3883        }
3884        keyframe=row[model.keyframe];
3885
3886        synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeRemove"));
3887
3888        if(!action)
3889        {
3890                ui_interface_->error("I am unable to find the appropriate action");
3891                return;
3892        }
3893
3894        action->set_param("canvas",get_canvas());
3895        action->set_param("canvas_interface",canvas_interface());
3896        action->set_param("keyframe",keyframe);
3897
3898        canvas_interface()->get_instance()->perform_action(action);
3899}
3900
3901void
3902CanvasView::show_keyframe_dialog()
3903{
3904        Glib::RefPtr<Gtk::TreeSelection> selection(keyframe_tree->get_selection());
3905        if(selection->get_selected())
3906        {
3907                Gtk::TreeRow row(*selection->get_selected());
3908
3909                Keyframe keyframe(row[keyframe_tree->model.keyframe]);
3910
3911                keyframe_dialog.set_keyframe(keyframe);
3912                keyframe_dialog.present();
3913        }
3914}
3915
3916void
3917CanvasView::on_keyframe_toggle()
3918{
3919        Glib::RefPtr<Gtk::TreeSelection> selection(keyframe_tree->get_selection());
3920        if(selection->get_selected())
3921        {
3922                Gtk::TreeRow row(*selection->get_selected());
3923
3924                Keyframe keyframe(row[keyframe_tree->model.keyframe]);
3925
3926                synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeToggl"));
3927
3928                if(!action)
3929                        return;
3930                action->set_param("canvas",canvas_interface()->get_canvas());
3931                action->set_param("canvas_interface",canvas_interface());
3932                action->set_param("keyframe",keyframe);
3933                action->set_param("new_status",!keyframe.active ());
3934
3935                canvas_interface()->get_instance()->perform_action(action);
3936
3937        }
3938}
3939
3940void
3941CanvasView::on_keyframe_description_set()
3942{
3943        Glib::RefPtr<Gtk::TreeSelection> selection(keyframe_tree->get_selection());
3944        if(selection->get_selected())
3945        {
3946                Gtk::TreeRow row(*selection->get_selected());
3947
3948                Keyframe keyframe(row[keyframe_tree->model.keyframe]);
3949
3950                synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeSet"));
3951
3952                if(!action)
3953                        return;
3954
3955                String str(keyframe.get_description ());
3956                if(!studio::App::dialog_entry((action->get_local_name() + _(" Description")),
3957                                        _("Description: "),
3958                                        //action->get_local_name(),
3959                                        str,
3960                                        _("Cancel"),
3961                                        _("Set")))
3962                        return;
3963
3964                keyframe.set_description(str);
3965
3966                action->set_param("canvas",canvas_interface()->get_canvas());
3967                action->set_param("canvas_interface",canvas_interface());
3968                action->set_param("keyframe",keyframe);
3969
3970                canvas_interface()->get_instance()->perform_action(action);
3971
3972        }
3973}
3974
3975void
3976CanvasView::toggle_duck_mask(Duckmatic::Type type)
3977{
3978        if(toggling_ducks_)
3979                return;
3980        toggling_ducks_=true;
3981        if(type & Duck::TYPE_WIDTH)
3982                type=type|Duck::TYPE_WIDTHPOINT_POSITION;
3983        bool is_currently_on(work_area->get_type_mask()&type);
3984
3985        if(is_currently_on)
3986                work_area->set_type_mask(work_area->get_type_mask()-type);
3987        else
3988                work_area->set_type_mask(work_area->get_type_mask()|type);
3989
3990        if (type == Duck::TYPE_BONE_RECURSIVE)
3991                queue_rebuild_ducks();
3992
3993        work_area->queue_draw();
3994        try
3995        {
3996                // Update the toggle ducks actions
3997                Glib::RefPtr<Gtk::ToggleAction> action;
3998                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("mask-position-ducks"));
3999                action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_POSITION));
4000                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("mask-tangent-ducks"));
4001                action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_TANGENT));
4002                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("mask-vertex-ducks"));
4003                action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_VERTEX));
4004                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("mask-radius-ducks"));
4005                action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_RADIUS));
4006                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("mask-width-ducks"));
4007                action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_WIDTH));
4008                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("mask-angle-ducks"));
4009                action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_ANGLE));
4010                // Update toggle ducks buttons
4011                toggleducksdial.update_toggles(work_area->get_type_mask());
4012        }
4013        catch(...)
4014        {
4015                toggling_ducks_=false;
4016        }
4017        toggling_ducks_=false;
4018}
4019
4020void
4021CanvasView::mask_bone_ducks()
4022{
4023        Duck::Type mask(work_area->get_type_mask());
4024        bool recursive(mask & Duck::TYPE_BONE_RECURSIVE);
4025
4026        if (recursive)
4027        {
4028                action_mask_bone_setup_ducks->set_active(true);
4029                action_mask_bone_recursive_ducks->set_active(false);
4030        }
4031        else
4032                action_mask_bone_recursive_ducks->set_active(true);
4033}
4034
4035void
4036CanvasView::on_meta_data_changed()
4037{
4038        // update the buttons and actions that are associated
4039        toggling_show_grid=true;
4040        toggling_snap_grid=true;
4041        toggling_onion_skin=true;
4042        try
4043        {
4044                // Update the toggle ducks actions
4045                Glib::RefPtr<Gtk::ToggleAction> action;
4046                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("toggle-onion-skin"));
4047                action->set_active((bool)(work_area->get_onion_skin()));
4048                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("toggle-grid-show"));
4049                action->set_active((bool)(work_area->grid_status()));
4050                action = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(action_group->get_action("toggle-grid-snap"));
4051                action->set_active((bool)(work_area->get_grid_snap()));
4052                // Update the toggle buttons
4053                onion_skin->set_active(work_area->get_onion_skin());
4054                snap_grid->set_active(work_area->get_grid_snap());
4055                show_grid->set_active(work_area->grid_status());
4056                // Update the onion skin spins
4057                past_onion_spin->set_value(work_area->get_onion_skins()[0]);
4058                future_onion_spin->set_value(work_area->get_onion_skins()[1]);
4059        }
4060        catch(...)
4061        {
4062                toggling_show_grid=false;
4063                toggling_snap_grid=false;
4064                toggling_onion_skin=false;
4065        }
4066        toggling_show_grid=false;
4067        toggling_snap_grid=false;
4068        toggling_onion_skin=false;
4069}
4070
4071void
4072CanvasView::image_import()
4073{
4074        // String filename(dirname(get_canvas()->get_file_name()));
4075        String filename("*.*");
4076        String errors, warnings;
4077        if(App::dialog_open_file(_("Please select a file"), filename, IMAGE_DIR_PREFERENCE))
4078        {
4079                canvas_interface()->import(filename, errors, warnings, App::resize_imported_images);
4080                if (warnings != "")
4081                        App::dialog_message_1b(
4082                                        "WARNING",
4083                                        strprintf("%s:\n\n%s", _("Warning"), warnings.c_str()),
4084                                        "details",
4085                                        _("Close"));
4086        }
4087}
4088
4089Smach::event_result
4090CanvasView::process_event_key(EventKey x)
4091{
4092        return smach_.process_event(x);
4093}
4094
4095void
4096CanvasView::on_input_device_changed(GdkDevice* device)
4097{
4098        if(!device)
4099        {
4100                get_smach().egress();
4101        }
4102        assert(device);
4103
4104        synfigapp::InputDevice::Handle input_device;
4105        input_device=synfigapp::Main::select_input_device(gdk_device_get_name(device));
4106        App::dock_toolbox->change_state(input_device->get_state(), true);
4107        process_event_key(EVENT_INPUT_DEVICE_CHANGED);
4108}
4109
4110void
4111CanvasView::on_preview_option()
4112{
4113        Dialog_PreviewOptions *po = dynamic_cast<Dialog_PreviewOptions *>(get_ext_widget("prevoptions"));
4114
4115        Canvas::Handle  canv = get_canvas();
4116
4117        if(canv)
4118        {
4119                RendDesc &r = canv->rend_desc();
4120                if(r.get_frame_rate())
4121                {
4122                        float rate = 1/r.get_frame_rate();
4123                        float beg = r.get_time_start() + r.get_frame_start()*rate;
4124                        float end = r.get_time_start() + r.get_frame_end()*rate;
4125
4126                        if(!po)
4127                        {
4128                                po = new Dialog_PreviewOptions;
4129                                po->set_zoom(work_area->get_zoom()/2);
4130                                po->set_fps(r.get_frame_rate()/2);
4131                                po->set_begintime(beg);
4132                                po->set_begin_override(false);
4133                                po->set_endtime(end);
4134                                po->set_end_override(false);
4135                                po->set_use_cairo(false);
4136
4137                                set_ext_widget("prevoptions",po);
4138                        }
4139                        /*po->set_zoom(work_area->get_zoom()/2);
4140                        po->set_fps(r.get_frame_rate()/2);
4141                        po->set_begintime(beg);
4142                        po->set_begin_override(false);
4143                        po->set_endtime(end);
4144                        po->set_end_override(false);*/
4145
4146                        po->set_global_fps(r.get_frame_rate());
4147                        po->signal_finish().connect(sigc::mem_fun(*this,&CanvasView::on_preview_create));
4148                        po->present();
4149                }
4150        }
4151}
4152
4153void
4154CanvasView::on_preview_create(const PreviewInfo &info)
4155{
4156        //set all the options
4157        etl::handle<Preview>    prev = new Preview;
4158
4159        prev->set_canvasview(this);
4160        prev->set_zoom(info.zoom);
4161        prev->set_fps(info.fps);
4162        prev->set_overbegin(info.overbegin);
4163        prev->set_begintime(info.begintime);
4164        prev->set_overend(info.overend);
4165        prev->set_endtime(info.endtime);
4166        prev->set_quality(work_area->get_quality());
4167        prev->set_use_cairo(info.use_cairo);
4168#ifdef WITH_JACK
4169        prev->set_jack_offset(get_jack_offset());
4170#endif
4171
4172        //render it out...
4173        prev->render();
4174
4175        Dialog_Preview *pd = preview_dialog.get();
4176        assert(pd);
4177
4178        pd->set_default_size(700,510);
4179        pd->set_preview(prev.get());
4180        pd->present();
4181
4182        // Preview Window created, the action can be enabled
4183        {
4184                Glib::RefPtr< Gtk::Action > action = action_group->get_action("dialog-flipbook");
4185                action->set_sensitive(true);
4186        }
4187
4188}
4189
4190void
4191CanvasView::on_audio_option()
4192{
4193        synfig::warning("Launching Audio Options");
4194        sound_dialog->set_global_fps(get_canvas()->rend_desc().get_frame_rate());
4195        sound_dialog->present();
4196}
4197
4198void
4199CanvasView::on_audio_file_change(const std::string &f)
4200{
4201        //save in meta data - always even when not valid...
4202        canvas_interface()->set_meta_data("audiofile",f);
4203}
4204
4205void
4206CanvasView::on_audio_offset_change(const synfig::Time &t)
4207{
4208    String s;
4209    {
4210        ChangeLocale change_locale(LC_NUMERIC, "C");
4211        s = t.get_string();
4212    }
4213        canvas_interface()->set_meta_data("audiooffset",s);
4214}
4215
4216void
4217CanvasView::on_audio_file_notify()
4218{
4219        std::string file(get_canvas()->get_meta_data("audiofile"));
4220        if(!file.c_str()) return;
4221
4222        if(!audio->load(file,dirname(get_canvas()->get_file_name())+string("/")))
4223        {
4224                if(file != "") synfig::warning("Could not load the file: %s", file.c_str());
4225                get_canvas()->erase_meta_data("audiofile");
4226                disp_audio->hide();
4227                disp_audio->set_profile(etl::handle<AudioProfile>());
4228        }else
4229        {
4230                //save in canvasview
4231                synfig::warning("Getting the profile of the music stuff");
4232
4233                disp_audio->set_profile(audio->get_profile());
4234                disp_audio->show();
4235
4236                synfig::warning("successfully set the profiles and stuff");
4237        }
4238        disp_audio->queue_draw();
4239}
4240
4241void
4242CanvasView::on_audio_offset_notify()
4243{
4244        Time t;
4245        {
4246                ChangeLocale change_locale(LC_NUMERIC, "C");
4247                t = Time(get_canvas()->get_meta_data("audiooffset"),get_canvas()->rend_desc().get_frame_rate());
4248        }
4249        audio->set_offset(t);
4250        sound_dialog->set_offset(t);
4251        disp_audio->queue_draw();
4252
4253        // synfig::info("CanvasView::on_audio_offset_notify(): offset time set to %s",t.get_string(get_canvas()->rend_desc().get_frame_rate()).c_str());
4254}
4255
4256void
4257CanvasView::play_audio(float t)
4258{
4259        if(audio.get())
4260        {
4261                synfig::info("Playing audio at %f s",t);
4262                audio->play(t);
4263        }
4264}
4265
4266void
4267CanvasView::stop_audio()
4268{
4269        if(audio.get())
4270        {
4271                audio->stop();
4272        }
4273}
4274
4275bool
4276CanvasView::on_audio_scrub()
4277{
4278        disp_audio->draw();
4279        return true;
4280}
4281
4282Glib::RefPtr<Glib::ObjectBase>
4283CanvasView::get_ref_obj(const synfig::String& x)
4284{
4285        return ref_obj_book_[x];
4286}
4287
4288Glib::RefPtr<const Glib::ObjectBase>
4289CanvasView::get_ref_obj(const synfig::String& x)const
4290{
4291        return ref_obj_book_.find(x)->second;
4292}
4293
4294void
4295CanvasView::set_ref_obj(const synfig::String& x, Glib::RefPtr<Glib::ObjectBase> y)
4296{
4297        ref_obj_book_[x]=y;
4298}
4299
4300Glib::RefPtr<Gtk::TreeModel>
4301CanvasView::get_tree_model(const synfig::String& x)
4302{
4303        return Glib::RefPtr<Gtk::TreeModel>::cast_dynamic(ref_obj_book_["_tree_model_"+x]);
4304}
4305
4306Glib::RefPtr<const Gtk::TreeModel>
4307CanvasView::get_tree_model(const synfig::String& x)const
4308{
4309        return Glib::RefPtr<Gtk::TreeModel>::cast_dynamic(ref_obj_book_.find("_tree_model_"+x)->second);
4310}
4311
4312void
4313CanvasView::set_tree_model(const synfig::String& x, Glib::RefPtr<Gtk::TreeModel> y)
4314{
4315        ref_obj_book_["_tree_model_"+x]=Glib::RefPtr<Glib::ObjectBase>::cast_static(y);
4316}
4317
4318Gtk::Widget*
4319CanvasView::get_ext_widget(const synfig::String& x)
4320{
4321        return ext_widget_book_[x];
4322}
4323
4324void
4325CanvasView::set_ext_widget(const synfig::String& x, Gtk::Widget* y)
4326{
4327        ext_widget_book_[x]=y;
4328        if(x=="layers_cmp")
4329        {
4330                layer_tree=dynamic_cast<LayerTree*>(y);
4331
4332                layer_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_LAYER_SELECTION_CHANGED));
4333                layer_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
4334                layer_tree->signal_layer_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_layer_user_click));
4335                layer_tree->signal_param_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
4336                layer_tree->signal_waypoint_clicked_layertree().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked_canvasview));
4337        }
4338        if(x=="children")
4339        {
4340                children_tree=dynamic_cast<ChildrenTree*>(y);
4341                if(children_tree)children_tree->signal_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
4342                if(children_tree)children_tree->signal_waypoint_clicked_childrentree().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked_canvasview));
4343                if(children_tree)children_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
4344        }
4345        if(x=="keyframes")
4346                keyframe_tree=dynamic_cast<KeyframeTree*>(y);
4347}
4348
4349Gtk::UIManager::ui_merge_id
4350CanvasView::get_popup_id()
4351{
4352        return merge_id_popup_;
4353}
4354
4355void
4356CanvasView::set_popup_id(Gtk::UIManager::ui_merge_id popup_id)
4357{
4358        merge_id_popup_ = popup_id;
4359}
4360
4361Gtk::UIManager::ui_merge_id
4362CanvasView::get_toolbar_id()
4363{
4364        return merge_id_toolbar_;
4365}
4366
4367void
4368CanvasView::set_toolbar_id(Gtk::UIManager::ui_merge_id toolbar_id)
4369{
4370        merge_id_toolbar_ = toolbar_id;
4371}
4372
4373bool
4374CanvasView::on_delete_event(GdkEventAny* event __attribute__ ((unused)))
4375{
4376        close_view();
4377
4378        //! \todo This causes the window to be deleted straight away - but what if we prompt 'save?' and the user cancels?
4379        //                Is there ever any need to pass on the delete event to the window here?
4380        // if(event) return Gtk::Window::on_delete_event(event);
4381
4382        return true;
4383}
4384
4385//! Modify the play stop button apearence and play stop the animation
4386void
4387CanvasView::on_play_pause_pressed()
4388{
4389        if (jack_enabled)
4390        {
4391#ifdef WITH_JACK
4392                if (jack_is_playing) {
4393                        jack_transport_stop(jack_client);
4394                        on_jack_sync();
4395                        stop_async();
4396                } else
4397                        jack_transport_start(jack_client);
4398#endif
4399        }
4400        else
4401        {
4402                if(!is_playing())
4403                        play_async();
4404                else
4405                        stop_async();
4406        }
4407}
4408
4409bool
4410CanvasView::is_time_equal_to_current_frame(const synfig::Time &time, const synfig::Time &range)
4411{
4412        float fps(get_canvas()->rend_desc().get_frame_rate());
4413        Time starttime = get_canvas()->rend_desc().get_time_start();
4414        Time endtime = get_canvas()->rend_desc().get_time_end();
4415
4416        synfig::Time t0 = get_time();
4417        synfig::Time t1 = time;
4418
4419        if (fps != 0.f) {
4420                t0 = t0.round(fps);
4421                t1 = t1.round(fps);
4422        }
4423
4424        t0 = std::max(starttime, std::min(endtime, t0));
4425        t1 = std::max(starttime, std::min(endtime, t1));
4426        double epsilon = max(range, Time::epsilon());
4427        double dt0 = t0;
4428        double dt1 = t1;
4429
4430        return abs(dt0 - dt1) <= epsilon;
4431}
4432
4433#ifdef WITH_JACK
4434void
4435CanvasView::toggle_jack_button()
4436{
4437        if (!toggling_jack)
4438        {
4439                string message;
4440                string details;
4441                if (get_jack_enabled())
4442                {
4443                        message = strprintf(_("Are you sure you want to disable JACK synchronization?" ));
4444                        details = strprintf(_("The JACK server will remain running."));
4445                } else {
4446                        message = strprintf(_("Are you sure you want to enable JACK synchronization?" ));
4447                        details = strprintf(_("This operation will launch a JACK server, if it isn't started yet."));
4448                }
4449                int answer = get_ui_interface()->confirmation(
4450                                        message,
4451                                        details,
4452                                        _("No"),
4453                                        _("Yes"),
4454                                        synfigapp::UIInterface::RESPONSE_OK);
4455
4456                if(answer == synfigapp::UIInterface::RESPONSE_OK)
4457                        set_jack_enabled(!get_jack_enabled());
4458               
4459                // Update button state
4460                toggling_jack = true;
4461                jackdial->get_toggle_jackbutton()->set_active(get_jack_enabled());
4462                toggling_jack = false;
4463        }
4464}
4465
4466void
4467CanvasView::on_jack_offset_changed()
4468{
4469        set_jack_offset(jackdial->get_offset());
4470        if (get_jack_enabled()) on_jack_sync();
4471}
4472
4473synfig::Time
4474CanvasView::get_jack_offset()const {
4475        return work_area->get_jack_offset();
4476}
4477
4478void
4479CanvasView::set_jack_offset(const synfig::Time &value) {
4480        work_area->set_jack_offset(value);
4481}
4482
4483void
4484CanvasView::on_jack_sync()
4485{
4486        jack_position_t pos;
4487        jack_transport_state_t state = jack_transport_query(jack_client, &pos);
4488
4489        jack_is_playing = state == JackTransportRolling || state == JackTransportStarting;
4490        jack_time = Time((Time::value_type)pos.frame/(Time::value_type)pos.frame_rate);
4491
4492        if (is_playing() != jack_is_playing)
4493        {
4494                if (jack_is_playing)
4495                        play_async();
4496                else
4497                        stop_async();
4498        }
4499
4500        if (!is_time_equal_to_current_frame(jack_time - get_jack_offset()))
4501        {
4502                jack_synchronizing = true;
4503                set_time(jack_time - get_jack_offset());
4504                time_adjustment()->set_value(get_time());
4505                time_adjustment()->value_changed();
4506                jack_synchronizing = false;
4507        }
4508}
4509
4510
4511int
4512CanvasView::jack_sync_callback(jack_transport_state_t /* state */, jack_position_t * /* pos */, void *arg)
4513{
4514        CanvasView *canvasView = static_cast<CanvasView*>(arg);
4515        canvasView->jack_dispatcher.emit();
4516        return 1;
4517}
4518#endif
4519
4520void
4521CanvasView::interpolation_refresh()
4522{
4523        widget_interpolation->set_value(synfigapp::Main::get_interpolation());
4524}
4525
4526void
4527CanvasView::on_interpolation_changed()
4528{
4529        synfigapp::Main::set_interpolation(Waypoint::Interpolation(widget_interpolation->get_value()));
4530}
4531
4532void
4533CanvasView::on_interpolation_event(GdkEvent * /* event */)
4534{
4535        widget_interpolation_scroll->get_hscrollbar()->get_adjustment()->set_value(0);
4536}
Note: See TracBrowser for help on using the repository browser.