X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Ftrunk%2Fsrc%2Fgtkmm%2Fcanvasview.cpp;h=7ffc505fb96f00fd01242876063d9df60427fd19;hb=9459638ad6797b8139f1e9f0715c96076dbf0890;hp=ad2ab6be9aa8d1ed479bb2e93408f1371d4b94f9;hpb=756c0d29ac1742f231e6615f9a577e574e35a4af;p=synfig.git diff --git a/synfig-studio/trunk/src/gtkmm/canvasview.cpp b/synfig-studio/trunk/src/gtkmm/canvasview.cpp index ad2ab6b..7ffc505 100644 --- a/synfig-studio/trunk/src/gtkmm/canvasview.cpp +++ b/synfig-studio/trunk/src/gtkmm/canvasview.cpp @@ -7,6 +7,7 @@ ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley ** Copyright (c) 2007, 2008 Chris Moore +** Copyright (c) 2009 Carlos López ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as @@ -41,6 +42,7 @@ #include #include #include +#include #include #include @@ -53,6 +55,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -95,6 +101,7 @@ #include "preview.h" #include "audiocontainer.h" #include "widget_timeslider.h" +#include "keyframedial.h" #include #include @@ -155,7 +162,6 @@ using namespace sigc; /* === C L A S S E S ======================================================= */ - class studio::UniversalScrubber { CanvasView *canvas_view; @@ -226,7 +232,6 @@ public: } }; - class studio::CanvasViewUIInterface : public synfigapp::UIInterface { CanvasView *view; @@ -236,7 +241,6 @@ public: CanvasViewUIInterface(CanvasView *view): view(view) { - view->statusbar->push(_("Idle")); } @@ -246,6 +250,37 @@ public: //view->progressbar->set_fraction(0); } + virtual Response confirmation(const std::string &title, + const std::string &primaryText, + const std::string &secondaryText, + const std::string &confirmPhrase, + const std::string &cancelPhrase, + Response defaultResponse=RESPONSE_OK) + { + view->present(); + //while(studio::App::events_pending())studio::App::iteration(false); + Gtk::MessageDialog dialog( + *view, // Parent + primaryText, // Message + false, // Markup + Gtk::MESSAGE_WARNING, // Type + Gtk::BUTTONS_NONE, // Buttons + true // Modal + ); + + if (! title.empty()) + dialog.set_title(title); + if (! secondaryText.empty()) + dialog.set_secondary_text(secondaryText); + + dialog.add_button(cancelPhrase, RESPONSE_CANCEL); + dialog.add_button(confirmPhrase, RESPONSE_OK); + dialog.set_default_response(defaultResponse); + + dialog.show_all(); + return (Response) dialog.run(); + } + virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES) { view->present(); @@ -385,13 +420,9 @@ class studio::CanvasViewSelectionManager : public synfigapp::SelectionManager CanvasView *view; CanvasView::LayerTreeModel layer_tree_model; CanvasView::ChildrenTreeModel children_tree_model; -public: - - CanvasViewSelectionManager(CanvasView *view): view(view) -{ - - } +public: + CanvasViewSelectionManager(CanvasView *view): view(view) { } private: void _set_selected_layer(const synfig::Layer::Handle &layer) @@ -484,8 +515,6 @@ public: view->layer_tree->clear_selected_layers(); } - - //! Returns the number of value_nodes selected. virtual int get_selected_children_count()const { @@ -566,8 +595,6 @@ public: return; } - - int get_selected_layer_parameter_count()const { return get_selected_layer_parameters().size(); @@ -623,7 +650,6 @@ public: }; // END of class SelectionManager - CanvasView::IsWorking::IsWorking(CanvasView &canvas_view_): canvas_view_(canvas_view_) { @@ -658,9 +684,13 @@ CanvasView::CanvasView(etl::loose_handle instance,etl::handle instance,etl::handle instance,etl::handlepack2(*notebook, Gtk::SHRINK); //vpaned->show_all(); - //notebook->show(); //notebook->append_page(*create_layer_tree(),_("Layers")); @@ -712,13 +747,13 @@ CanvasView::CanvasView(etl::loose_handle instance,etl::handleattach(*vpaned, 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); layout_table->attach(*create_work_area(), 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + layout_table->attach(*create_display_bar(), 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); init_menus(); //layout_table->attach(*App::ui_manager()->get_widget("/menu-main"), 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); - layout_table->attach(*create_time_bar(), 0, 1, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); layout_table->attach(*create_status_bar(), 0, 1, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); @@ -750,7 +785,6 @@ CanvasView::CanvasView(etl::loose_handle instance,etl::handlesignal_layer_selected().connect(sigc::mem_fun(*this,&studio::CanvasView::workarea_layer_selected)); work_area->signal_input_device_changed().connect(sigc::mem_fun(*this,&studio::CanvasView::on_input_device_changed)); @@ -773,7 +807,6 @@ CanvasView::CanvasView(etl::loose_handle instance,etl::handle instance,etl::handle listTargets; listTargets.push_back( Gtk::TargetEntry("STRING") ); listTargets.push_back( Gtk::TargetEntry("text/plain") ); @@ -819,7 +849,6 @@ CanvasView::CanvasView(etl::loose_handle instance,etl::handlerend_desc().get_time_end()-get_canvas()->rend_desc().get_time_start()); if(length<10.0) @@ -864,7 +893,6 @@ CanvasView::CanvasView(etl::loose_handle instance,etl::handlerend_desc().get_time_start()); time_window_adjustment().value_changed(); - GRAB_HINT_DATA("canvas_view"); /* { @@ -916,8 +944,6 @@ CanvasView::~CanvasView() synfig::info("CanvasView::~CanvasView(): Deleted"); } - - std::list& CanvasView::get_pixel_sizes() { @@ -933,37 +959,36 @@ CanvasView::create_time_bar() { Gtk::Image *icon; + //Setup the Time Slider and the Time window scroll Gtk::HScrollbar *time_window_scroll = manage(new class Gtk::HScrollbar(time_window_adjustment())); //Gtk::HScrollbar *time_scroll = manage(new class Gtk::HScrollbar(time_adjustment())); //TIME BAR TEMPORARY POSITION //Widget_Timeslider *time_scroll = manage(new Widget_Timeslider); - timeslider->show(); timeslider->set_time_adjustment(&time_adjustment()); timeslider->set_bounds_adjustment(&time_window_adjustment()); //layout_table->attach(*timeslider, 0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL); - + //Setup the keyframe list widget + widget_kf_list->set_time_adjustment(&time_adjustment()); + widget_kf_list->set_canvas_interface(canvas_interface()); + widget_kf_list->show(); tooltips.set_tip(*time_window_scroll,_("Moves the time window")); tooltips.set_tip(*timeslider,_("Changes the current time")); time_window_scroll->show(); timeslider->show(); - time_window_scroll->set_flags(Gtk::CAN_FOCUS); + //time_window_scroll->set_flags(Gtk::CAN_FOCUS); // Uncomment this produce bad render of the HScroll timeslider->set_flags(Gtk::CAN_FOCUS); //time_scroll->signal_value_changed().connect(sigc::mem_fun(*work_area, &studio::WorkArea::render_preview_hook)); //time_scroll->set_update_policy(Gtk::UPDATE_DISCONTINUOUS); - NORMAL_BUTTON(animatebutton,"gtk-yes",_("Animate")); + //Setup the Animation Mode Button and the Keyframe Lock button + Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon"); + SMALL_BUTTON(animatebutton,"gtk-yes",_("Animate")); animatebutton->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_animate_button_pressed)); animatebutton->show(); - NORMAL_BUTTON(keyframebutton,"synfig-keyframe_lock_all",_("All Keyframes Locked")); - keyframebutton->signal_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_button_pressed)); - keyframebutton->show(); - - Gtk::Table *table= manage(new class Gtk::Table(2, 3, false)); - - //setup the audio display + //Setup the audio display disp_audio->set_size_request(-1,32); //disp_audio->show(); disp_audio->set_time_adjustment(&time_adjustment()); disp_audio->signal_start_scrubbing().connect( @@ -975,16 +1000,69 @@ CanvasView::create_time_bar() disp_audio->signal_stop_scrubbing().connect( sigc::mem_fun(*audio,&AudioContainer::stop_scrubbing) ); + //Setup the current time widget + current_time_widget=manage(new Widget_Time); + current_time_widget->set_value(get_time()); + current_time_widget->set_fps(get_canvas()->rend_desc().get_frame_rate()); + current_time_widget->signal_value_changed().connect( + sigc::mem_fun(*this,&CanvasView::on_current_time_widget_changed) + ); + current_time_widget->set_size_request(0,-1); // request horizontal shrink + tooltips.set_tip(*current_time_widget,_("Current time")); + current_time_widget->show(); - table->attach(*manage(disp_audio), 0, 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK); - table->attach(*timeslider, 0, 1, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); - table->attach(*time_window_scroll, 0, 1, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0); + //Setup the FrameDial widget + framedial = manage(new class FrameDial()); + framedial->signal_seek_begin().connect( + sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time), Time::begin()) + ); + framedial->signal_seek_prev_frame().connect( + sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_frame), -1) + ); + framedial->signal_play_stop().connect( + sigc::mem_fun(*this, &studio::CanvasView::on_play_stop_pressed) + ); + framedial->signal_seek_next_frame().connect( + sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_frame), 1) + ); + framedial->signal_seek_end().connect( + sigc::bind(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::seek_time), Time::end()) + ); + framedial->show(); + + //Setup the KeyFrameDial widget + KeyFrameDial *keyframedial = Gtk::manage(new class KeyFrameDial()); + keyframedial->signal_seek_prev_keyframe().connect(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_prev_keyframe)); + keyframedial->signal_seek_next_keyframe().connect(sigc::mem_fun(*canvas_interface().get(), &synfigapp::CanvasInterface::jump_to_next_keyframe)); + keyframedial->signal_lock_keyframe().connect(sigc::mem_fun(*this, &studio::CanvasView::on_keyframe_button_pressed)); + keyframedial->show(); + keyframebutton=keyframedial->get_lock_button(); + + timebar = Gtk::manage(new class Gtk::Table(5, 4, false)); + + //Adjust both widgets to be the same as the + int header_height = 0; + if(getenv("SYNFIG_TIMETRACK_HEADER_HEIGHT")) + header_height = atoi(getenv("SYNFIG_TIMETRACK_HEADER_HEIGHT")); + if (header_height < 3) + header_height = 24; + timeslider->set_size_request(-1,header_height-header_height/3+1); + widget_kf_list->set_size_request(-1,header_height/3+1); + + //Attach widgets to the timebar + //timebar->attach(*manage(disp_audio), 1, 5, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK); + timebar->attach(*current_time_widget, 0, 1, 0, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); + timebar->attach(*framedial, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK); + timebar->attach(*timeslider, 1, 3, 1, 2, Gtk::FILL|Gtk::SHRINK, Gtk::FILL|Gtk::SHRINK); + timebar->attach(*widget_kf_list, 1, 3, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::SHRINK); + timebar->attach(*time_window_scroll, 1, 3, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK); + timebar->attach(*keyframedial, 3, 4, 0, 2, Gtk::SHRINK, Gtk::SHRINK); + timebar->attach(*animatebutton, 4, 5, 0, 2, Gtk::SHRINK, Gtk::SHRINK); + //timebar->attach(*keyframebutton, 1, 2, 3, 4, Gtk::SHRINK, Gtk::SHRINK); + + timebar->show(); - table->attach(*animatebutton, 1, 2, 0, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - table->attach(*keyframebutton, 2, 3, 0, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - timebar=table; - table->show(); - return table; + return timebar; } Gtk::Widget * @@ -1000,7 +1078,6 @@ CanvasView::create_work_area() return work_area.get(); } - Gtk::Widget* CanvasView::create_status_bar() { @@ -1009,7 +1086,7 @@ CanvasView::create_status_bar() cancel=false; // Create the status bar at the bottom of the window - Gtk::Table *statusbartable= manage(new class Gtk::Table(7, 1, false)); + Gtk::Table *statusbartable= manage(new class Gtk::Table(5, 1, false)); // statusbar = manage(new class Gtk::Statusbar()); // This is already done at construction progressbar =manage(new class Gtk::ProgressBar()); SMALL_BUTTON(stopbutton,"gtk-stop",_("Stop")); @@ -1021,19 +1098,10 @@ CanvasView::create_status_bar() // statusbartable->attach(*lowerbutton, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); // statusbartable->attach(*raisebutton, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - - current_time_widget=manage(new Widget_Time); - current_time_widget->set_value(get_time()); - current_time_widget->set_fps(get_canvas()->rend_desc().get_frame_rate()); - current_time_widget->signal_value_changed().connect( - sigc::mem_fun(*this,&CanvasView::on_current_time_widget_changed) - ); - - statusbartable->attach(*current_time_widget, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); - statusbartable->attach(*statusbar, 3, 4, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); - statusbartable->attach(*progressbar, 4, 5, 0, 1, Gtk::SHRINK, Gtk::EXPAND|Gtk::FILL, 0, 0); - statusbartable->attach(*refreshbutton, 5, 6, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); - statusbartable->attach(*stopbutton, 6, 7, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); + statusbartable->attach(*statusbar, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 0); + statusbartable->attach(*progressbar, 2, 3, 0, 1, Gtk::SHRINK, Gtk::EXPAND|Gtk::FILL, 0, 0); + statusbartable->attach(*refreshbutton, 3, 4, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); + statusbartable->attach(*stopbutton, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0, 0); statusbar->set_has_resize_grip(false); statusbar->show(); stopbutton->show(); @@ -1048,11 +1116,137 @@ CanvasView::create_status_bar() refreshbutton->signal_clicked().connect(SLOT_EVENT(EVENT_REFRESH)); stopbutton->signal_clicked().connect(SLOT_EVENT(EVENT_STOP)); - statusbartable->show_all(); return statusbartable; } +Gtk::Widget* +CanvasView::create_display_bar() +{ + displaybar = manage(new class Gtk::Table(1, 7, false)); + + // Setup the ToggleDuckDial widget + toggleducksdial = Gtk::manage(new class ToggleDucksDial()); + + Duck::Type m = work_area->get_type_mask(); + toggleducksdial->update_toggles(m); + + toggleducksdial->signal_ducks_position().connect( + sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_POSITION) + ); + toggleducksdial->signal_ducks_vertex().connect( + sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_VERTEX) + ); + toggleducksdial->signal_ducks_tangent().connect( + sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_TANGENT) + ); + toggleducksdial->signal_ducks_radius().connect( + sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_RADIUS) + ); + toggleducksdial->signal_ducks_width().connect( + sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_WIDTH) + ); + toggleducksdial->signal_ducks_angle().connect( + sigc::bind(sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask),Duck::TYPE_ANGLE) + ); + toggleducksdial->show(); + + // Set up the ResolutionDial widget + resolutiondial=Gtk::manage(new class ResolutionDial()); + + resolutiondial->update_lowres(work_area->get_low_resolution_flag()); + resolutiondial->signal_increase_resolution().connect( + sigc::mem_fun(*this, &studio::CanvasView::decrease_low_res_pixel_size)); + resolutiondial->signal_decrease_resolution().connect( + sigc::mem_fun(*this, &studio::CanvasView::increase_low_res_pixel_size)); + resolutiondial->signal_use_low_resolution().connect( + sigc::mem_fun(*this, &studio::CanvasView::toggle_low_res_pixel_flag)); + resolutiondial->show(); + + // Set up a separator + Gtk::VSeparator *separator1 = Gtk::manage(new class Gtk::VSeparator()); + separator1->show(); + Gtk::VSeparator *separator2 = Gtk::manage(new class Gtk::VSeparator()); + separator2->show(); + + // Set up quality spin button + quality_spin=Gtk::manage(new class Gtk::SpinButton(quality_adjustment_)); + quality_spin->signal_value_changed().connect( + sigc::mem_fun(*this, &studio::CanvasView::update_quality)); + tooltips.set_tip(*quality_spin, _("Quality (lower is better)")); + quality_spin->show(); + + // Set up the show grid toggle button + show_grid = Gtk::manage(new class Gtk::ToggleButton()); + show_grid->set_active(work_area->grid_status()); + Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_show_grid"), Gtk::IconSize::from_name("synfig-small_icon"))); + icon->set_padding(0, 0); + icon->show(); + show_grid->add(*icon); + show_grid->signal_toggled().connect( + sigc::mem_fun(*this, &studio::CanvasView::toggle_show_grid)); + tooltips.set_tip(*show_grid, _("Show grid when enabled")); + show_grid->set_relief(Gtk::RELIEF_NONE); + show_grid->show(); + + // Set up the snap to grid toggle button + snap_grid = Gtk::manage(new class Gtk::ToggleButton()); + snap_grid->set_active(work_area->grid_status()); + Gtk::Image *icon2 = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_snap_grid"), Gtk::IconSize::from_name("synfig-small_icon"))); + icon2->set_padding(0, 0); + icon2->show(); + snap_grid->add(*icon2); + snap_grid->signal_toggled().connect( + sigc::mem_fun(*this, &studio::CanvasView::toggle_snap_grid)); + tooltips.set_tip(*snap_grid, _("Snap grid when enabled")); + snap_grid->set_relief(Gtk::RELIEF_NONE); + snap_grid->show(); + + // Set up the onion skin toggle button + onion_skin = Gtk::manage(new class Gtk::ToggleButton()); + onion_skin->set_active(work_area->get_onion_skin()); + Gtk::Image *icon3 = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_onion_skin"), Gtk::IconSize::from_name("synfig-small_icon"))); + icon3->set_padding(0, 0); + icon3->show(); + onion_skin->add(*icon3); + onion_skin->signal_toggled().connect( + sigc::mem_fun(*this, &studio::CanvasView::toggle_onion_skin)); + tooltips.set_tip(*onion_skin, _("Shows onion skin when enabled")); + onion_skin->set_relief(Gtk::RELIEF_NONE); + onion_skin->show(); + + // Set up past onion skin spin button + past_onion_spin=Gtk::manage(new class Gtk::SpinButton(past_onion_adjustment_)); + past_onion_spin->signal_value_changed().connect( + sigc::mem_fun(*this, &studio::CanvasView::set_onion_skins)); + tooltips.set_tip(*past_onion_spin, _("Past onion skins")); + past_onion_spin->show(); + + // Set up future onion skin spin button + future_onion_spin=Gtk::manage(new class Gtk::SpinButton(future_onion_adjustment_)); + future_onion_spin->signal_value_changed().connect( + sigc::mem_fun(*this, &studio::CanvasView::set_onion_skins)); + tooltips.set_tip(*future_onion_spin, _("Future onion skins")); + future_onion_spin->show(); + + + displaybar->attach(*toggleducksdial, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + displaybar->attach(*separator1, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL); + displaybar->attach(*resolutiondial, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + displaybar->attach(*separator2, 3, 4, 0, 1, Gtk::FILL, Gtk::FILL); + displaybar->attach(*quality_spin, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + displaybar->attach(*show_grid, 5, 6, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + displaybar->attach(*snap_grid, 6, 7, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + displaybar->attach(*past_onion_spin, 7, 8, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + displaybar->attach(*onion_skin, 8, 9, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + displaybar->attach(*future_onion_spin, 9, 10, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + + displaybar->show(); + + return displaybar; + +} + void CanvasView::on_current_time_widget_changed() { @@ -1203,7 +1397,7 @@ CanvasView::init_menus() sigc::hide_return(sigc::ptr_fun(&studio::App::new_instance)) ); action_group->add( Gtk::Action::create("open", Gtk::Stock::OPEN), - sigc::hide_return(sigc::ptr_fun(&studio::App::dialog_open)) + sigc::hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::open)) ); action_group->add( Gtk::Action::create("save", Gtk::Stock::SAVE), hide_return(sigc::mem_fun(*get_instance().get(), &studio::Instance::save)) @@ -1263,6 +1457,14 @@ CanvasView::init_menus() sigc::mem_fun(*work_area,&studio::WorkArea::select_all_ducks) ); + action_group->add( Gtk::Action::create("unselect-all-ducks", _("Unselect All Ducks")), + sigc::mem_fun(*work_area,&studio::WorkArea::unselect_all_ducks) + ); + + action_group->add( Gtk::Action::create("select-all-layers", _("Select All Layers")), + sigc::mem_fun(*this,&CanvasView::on_select_layers) + ); + action_group->add( Gtk::Action::create("unselect-all-layers", _("Unselect All Layers")), sigc::mem_fun(*this,&CanvasView::on_unselect_layers) ); @@ -1302,7 +1504,7 @@ CanvasView::init_menus() } action_group->add( action, sigc::bind( - sigc::mem_fun(*work_area, &studio::WorkArea::set_quality), + sigc::mem_fun(*this, &studio::CanvasView::set_quality), i ) ); @@ -1344,20 +1546,20 @@ CanvasView::init_menus() sigc::mem_fun(*this, &studio::CanvasView::play) ); - action_group->add( Gtk::Action::create("dialog-flipbook", _("Flipbook Dialog")), + action_group->add( Gtk::Action::create("dialog-flipbook", _("Preview Window")), sigc::mem_fun0(*preview_dialog, &studio::Dialog_Preview::present) ); { Glib::RefPtr action; - action = Gtk::ToggleAction::create("toggle-grid-show", _("Show Grid")); - action->set_active(work_area->grid_status()); - action_group->add(action, sigc::mem_fun(*work_area, &studio::WorkArea::toggle_grid)); + grid_show_toggle = Gtk::ToggleAction::create("toggle-grid-show", _("Show Grid")); + grid_show_toggle->set_active(work_area->grid_status()); + action_group->add(grid_show_toggle, sigc::mem_fun(*this, &studio::CanvasView::toggle_show_grid)); - action = Gtk::ToggleAction::create("toggle-grid-snap", _("Snap to Grid")); - action->set_active(work_area->get_grid_snap()); - action_group->add(action, sigc::mem_fun(*work_area, &studio::WorkArea::toggle_grid_snap)); + grid_snap_toggle = Gtk::ToggleAction::create("toggle-grid-snap", _("Snap to Grid")); + grid_snap_toggle->set_active(work_area->get_grid_snap()); + action_group->add(grid_snap_toggle, sigc::mem_fun(*this, &studio::CanvasView::toggle_snap_grid)); action = Gtk::ToggleAction::create("toggle-guide-show", _("Show Guides")); action->set_active(work_area->get_show_guides()); @@ -1365,11 +1567,11 @@ CanvasView::init_menus() action = Gtk::ToggleAction::create("toggle-low-res", _("Use Low-Res")); action->set_active(work_area->get_low_resolution_flag()); - action_group->add(action, sigc::mem_fun(*work_area, &studio::WorkArea::toggle_low_resolution_flag)); + action_group->add(action, sigc::mem_fun(*this, &studio::CanvasView::toggle_low_res_pixel_flag)); action = Gtk::ToggleAction::create("toggle-onion-skin", _("Show Onion Skin")); action->set_active(work_area->get_onion_skin()); - action_group->add(action, sigc::mem_fun(*work_area, &studio::WorkArea::toggle_onion_skin)); + action_group->add(action, sigc::mem_fun(*this, &studio::CanvasView::toggle_onion_skin)); } action_group->add( Gtk::Action::create("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit")), @@ -1418,23 +1620,26 @@ CanvasView::init_menus() } + { + Glib::RefPtr action; + +#define DUCK_MASK(lower,upper,string) \ + action=Gtk::ToggleAction::create("mask-" #lower "-ducks", string); \ + action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_##upper)); \ + action_group->add(action, \ + sigc::bind( \ + sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask), \ + Duck::TYPE_##upper)) + + DUCK_MASK(position,POSITION,_("Show Position Ducks")); + DUCK_MASK(tangent,TANGENT,_("Show Tangent Ducks")); + DUCK_MASK(vertex,VERTEX,_("Show Vertex Ducks")); + DUCK_MASK(radius,RADIUS,_("Show Radius Ducks")); + DUCK_MASK(width,WIDTH,_("Show Width Ducks")); + DUCK_MASK(angle,ANGLE,_("Show Angle Ducks")); -#define DUCK_MASK(lower,upper,string) \ - duck_mask_##lower=Gtk::ToggleAction::create("mask-" #lower "-ducks", string); \ - duck_mask_##lower->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_##upper)); \ - action_group->add( duck_mask_##lower, \ - sigc::bind( \ - sigc::mem_fun(*this, &studio::CanvasView::toggle_duck_mask), \ - Duck::TYPE_##upper \ - ) \ - ) - DUCK_MASK(position,POSITION,_("Show Position Ducks")); - DUCK_MASK(tangent,TANGENT,_("Show Tangent Ducks")); - DUCK_MASK(vertex,VERTEX,_("Show Vertex Ducks")); - DUCK_MASK(radius,RADIUS,_("Show Radius Ducks")); - DUCK_MASK(width,WIDTH,_("Show Width Ducks")); - DUCK_MASK(angle,ANGLE,_("Show Angle Ducks")); #undef DUCK_MASK + } add_accel_group(App::ui_manager()->get_accel_group()); @@ -1493,8 +1698,6 @@ CanvasView::init_menus() } */ - - #if 0 // // //Test some key stuff @@ -1542,6 +1745,8 @@ CanvasView::init_menus() // editmenu.items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-paste"),NOT_IMPLEMENTED_SLOT)); // editmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem()); // editmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Select All Ducks"),Gtk::AccelKey('E',Gdk::CONTROL_MASK),sigc::mem_fun(*work_area,&studio::WorkArea::select_all_ducks))); +// editmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Unselect All Ducks"),Gtk::AccelKey('E',Gdk::CONTROL_MASK),sigc::mem_fun(*work_area,&studio::WorkArea::unselect_all_ducks))); +// editmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Select All Layers"),Gtk::AccelKey('A',Gdk::CONTROL_MASK),sigc::mem_fun(*this,&CanvasView::on_select_layers))); // editmenu.items().push_back(Gtk::Menu_Helpers::MenuElem(_("Unselect All Layers"),Gtk::AccelKey('D',Gdk::CONTROL_MASK),sigc::mem_fun(*this,&CanvasView::on_unselect_layers))); // editmenu.items().push_back(Gtk::Menu_Helpers::SeparatorElem()); // @@ -1741,6 +1946,14 @@ CanvasView::init_menus() } void +CanvasView::on_select_layers() +{ + Canvas::Handle canvas(get_canvas()); + for (CanvasBase::iterator iter = canvas->begin(); iter != canvas->end(); iter++) + layer_tree->select_all_children_layers(*iter); +} + +void CanvasView::on_unselect_layers() { layer_tree->clear_selected_layers(); @@ -1780,7 +1993,6 @@ CanvasView::add_layer(synfig::String x) target_depth=canvas->get_depth(*layer_list.begin()); } - Layer::Handle layer(canvas_interface()->add_layer_to(x,canvas,target_depth)); if(layer) { @@ -1903,13 +2115,11 @@ CanvasView::workarea_layer_selected(synfig::Layer::Handle layer) get_selection_manager()->set_selected_layer(layer); } - void CanvasView::refresh_rend_desc() { current_time_widget->set_fps(get_canvas()->rend_desc().get_frame_rate()); - //???? //synfig::info("Canvasview: Refreshing render desc info"); if(!get_time().is_equal(time_adjustment().get_value())) @@ -1987,6 +2197,18 @@ CanvasView::refresh_rend_desc() } //clamp time to big bounds... + if(time_window_adjustment().get_value() < begin_time) + { + time_window_adjustment().set_value(begin_time); + time_window_adjustment().value_changed(); + } + + if(time_window_adjustment().get_value() + time_window_adjustment().get_page_size() > end_time) + { + time_window_adjustment().set_value(end_time - time_window_adjustment().get_page_size()); + time_window_adjustment().value_changed(); + } + if(time_adjustment().get_value() < begin_time) { time_adjustment().set_value(begin_time); @@ -2012,7 +2234,6 @@ CanvasView::refresh_rend_desc() work_area->queue_render_preview(); } - bool CanvasView::close_view() { @@ -2034,6 +2255,7 @@ static bool _close_instance(etl::handle instance) bool CanvasView::close_instance() { +#ifdef SINGLE_THREADED if (get_work_area()->get_updating()) { get_work_area()->stop_updating(true); // stop and mark as cancelled @@ -2044,6 +2266,7 @@ CanvasView::close_instance() 250); } else +#endif Glib::signal_timeout().connect( sigc::bind(sigc::ptr_fun(_close_instance), (etl::handle)get_instance()), @@ -2065,14 +2288,20 @@ CanvasView::update_title() { string title; - if(get_instance()->synfigapp::Instance::get_action_count()) - title="*"; - title+=etl::basename(get_instance()->get_file_name()) - +" : "; - if(get_canvas()->get_name().empty()) - title+='"'+get_canvas()->get_id()+'"'; - else - title+='"'+get_canvas()->get_name()+'"'; + title = strprintf("%s%s\"%s\"", + ( + get_instance()->get_action_count() + ? "*" + : "" + ), ( + get_instance()->has_real_filename() + ? (etl::basename(get_instance()->get_file_name()) + " : ").c_str() + : "" + ), ( + get_canvas()->get_name().empty() + ? get_canvas()->get_id().c_str() + : get_canvas()->get_name().c_str() + )); if(get_instance()->synfigapp::Instance::in_repository()) { @@ -2090,7 +2319,6 @@ CanvasView::update_title() set_title(title); } - void CanvasView::on_hide() { @@ -2162,7 +2390,7 @@ CanvasView::build_tables() void CanvasView::on_layer_toggle(synfig::Layer::Handle layer) { - synfigapp::Action::Handle action(synfigapp::Action::create("layer_activate")); + synfigapp::Action::Handle action(synfigapp::Action::create("LayerActivate")); assert(action); if(!action) @@ -2181,12 +2409,11 @@ CanvasView::on_layer_toggle(synfig::Layer::Handle layer) canvas_interface()->get_instance()->perform_action(action); } - void -CanvasView::popup_param_menu(synfigapp::ValueDesc value_desc, float location) +CanvasView::popup_param_menu(synfigapp::ValueDesc value_desc, float location, bool bezier) { parammenu.items().clear(); - get_instance()->make_param_menu(¶mmenu,get_canvas(),value_desc,location); + get_instance()->make_param_menu(¶mmenu,get_canvas(),value_desc,location,bezier); parammenu.popup(3,gtk_get_current_event_time()); } @@ -2204,7 +2431,6 @@ CanvasView::on_layer_user_click(int button, Gtk::TreeRow /*row*/, LayerTree::Col { case 3: { - Gtk::MenuItem* menu = dynamic_cast(App::ui_manager()->get_widget("/menu-main/menu-layer")); if(menu && menu->get_submenu()) { @@ -2213,7 +2439,6 @@ CanvasView::on_layer_user_click(int button, Gtk::TreeRow /*row*/, LayerTree::Col menu->get_submenu()->popup(button,gtk_get_current_event_time()); } - #if 0 bool multiple_selected=true; @@ -2326,8 +2551,6 @@ CanvasView::on_layer_user_click(int button, Gtk::TreeRow /*row*/, LayerTree::Col } } - - bool CanvasView::on_children_user_click(int button, Gtk::TreeRow row, ChildrenTree::ColumnID column_id) { @@ -2386,7 +2609,6 @@ CanvasView::on_keyframe_tree_event(GdkEvent *event) return false; } - void CanvasView::refresh_time_window() { @@ -2421,7 +2643,6 @@ CanvasView::on_time_changed() if(get_time() != time_adjustment().get_value()) { - //Recenters the window, causing it to jump (possibly undesirably... but whatever) if(time < time_window_adjustment().get_value() || time > time_window_adjustment().get_value()+time_window_adjustment().get_page_size()) @@ -2450,6 +2671,7 @@ CanvasView::time_zoom_in() time_window_adjustment().set_page_size(time_window_adjustment().get_page_size()*0.75); if (time_window_adjustment().get_page_size() < min_page_size) time_window_adjustment().set_page_size(min_page_size); + time_window_adjustment().set_page_increment(time_window_adjustment().get_page_size()); time_window_adjustment().changed(); refresh_time_window(); @@ -2464,6 +2686,7 @@ CanvasView::time_zoom_out() time_window_adjustment().set_page_size(time_window_adjustment().get_page_size()/0.75); if (time_window_adjustment().get_page_size() > length) time_window_adjustment().set_page_size(length); + time_window_adjustment().set_page_increment(time_window_adjustment().get_page_size()); time_window_adjustment().changed(); refresh_time_window(); @@ -2505,15 +2728,15 @@ CanvasView::on_id_changed() update_title(); } - void CanvasView::on_mode_changed(synfigapp::CanvasInterface::Mode mode) { // If the animate flag was set in mode... + Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon"); if(mode&synfigapp::MODE_ANIMATE) { Gtk::Image *icon; - icon=manage(new Gtk::Image(Gtk::StockID("gtk-no"),Gtk::ICON_SIZE_BUTTON)); + icon=manage(new Gtk::Image(Gtk::StockID("gtk-no"),iconsize)); animatebutton->remove(); animatebutton->add(*icon); tooltips.set_tip(*animatebutton,_("In Animate Editing Mode")); @@ -2523,7 +2746,7 @@ CanvasView::on_mode_changed(synfigapp::CanvasInterface::Mode mode) else { Gtk::Image *icon; - icon=manage(new Gtk::Image(Gtk::StockID("gtk-yes"),Gtk::ICON_SIZE_BUTTON)); + icon=manage(new Gtk::Image(Gtk::StockID("gtk-yes"),iconsize)); animatebutton->remove(); animatebutton->add(*icon); tooltips.set_tip(*animatebutton,_("Not in Animate Editing Mode")); @@ -2612,25 +2835,118 @@ CanvasView::duck_change_param(const synfig::Point &value,synfig::Layer::Handle l bool CanvasView::on_duck_changed(const synfig::Point &value,const synfigapp::ValueDesc& value_desc) { + if (ValueNode_BLineCalcWidth::Handle bline_width = ValueNode_BLineCalcWidth::Handle::cast_dynamic(value_desc.get_value_node())) + { + Real old_width((*bline_width)(get_time()).get(Real())); + Real new_width(value.mag()); + int scale_index(bline_width->get_link_index_from_name("scale")); + Real scale((*(bline_width->get_link(scale_index)))(get_time()).get(Real())); + return canvas_interface()->change_value(synfigapp::ValueDesc(bline_width,scale_index), new_width * scale / old_width); + } + + if (ValueNode_BLineCalcVertex::Handle bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(value_desc.get_value_node())) + { + ValueNode_BLine::Handle bline = ValueNode_BLine::Handle::cast_dynamic(bline_vertex->get_link(bline_vertex->get_link_index_from_name("bline"))); + Real radius = 0.0; + Real amount = synfig::find_closest_point((*bline)(get_time()), value, radius, bline->get_loop()); + return canvas_interface()->change_value(synfigapp::ValueDesc(bline_vertex,bline_vertex->get_link_index_from_name("amount")), amount); + } + + if (ValueNode_BLineCalcTangent::Handle bline_tangent = ValueNode_BLineCalcTangent::Handle::cast_dynamic(value_desc.get_value_node())) + { + switch(value_desc.get_value_type()) + { + case ValueBase::TYPE_REAL: + { + Real old_length = (*bline_tangent)(get_time()).get(Real()); + Real new_length = value.mag(); + int scale_index(bline_tangent->get_link_index_from_name("scale")); + int fixed_length_index(bline_tangent->get_link_index_from_name("fixed_length")); + Real scale((*(bline_tangent->get_link(scale_index)))(get_time()).get(Real())); + bool fixed_length((*(bline_tangent->get_link(fixed_length_index)))(get_time()).get(bool())); + if (fixed_length) + return canvas_interface()->change_value(synfigapp::ValueDesc(bline_tangent,scale_index), new_length); + if (old_length == 0) + return true; + return canvas_interface()->change_value(synfigapp::ValueDesc(bline_tangent,scale_index), new_length * scale / old_length); + } + + case ValueBase::TYPE_ANGLE: + assert(0); // doesn't happen? + break; + + case ValueBase::TYPE_VECTOR: + { + Vector old_tangent = (*bline_tangent)(get_time()).get(Vector()); + Angle old_angle = old_tangent.angle(); + Real old_length = old_tangent.mag(); + Angle new_angle = value.angle(); + Real new_length = value.mag(); + int offset_index(bline_tangent->get_link_index_from_name("offset")); + int scale_index(bline_tangent->get_link_index_from_name("scale")); + int fixed_length_index(bline_tangent->get_link_index_from_name("fixed_length")); + Angle old_offset((*(bline_tangent->get_link(offset_index)))(get_time()).get(Angle())); + Real scale((*(bline_tangent->get_link(scale_index)))(get_time()).get(Real())); + bool fixed_length((*(bline_tangent->get_link(fixed_length_index)))(get_time()).get(bool())); + if (fixed_length) + { + if (!(canvas_interface()->change_value(synfigapp::ValueDesc(bline_tangent,scale_index), new_length))) + return false; + } + else if (old_length != 0 && !(canvas_interface()->change_value(synfigapp::ValueDesc(bline_tangent,scale_index), new_length * scale / old_length))) + return false; + return canvas_interface()->change_value(synfigapp::ValueDesc(bline_tangent,offset_index), old_offset + new_angle - old_angle); + } + default: + break; + } + } + + if (ValueNode_Scale::Handle scale_value_node = ValueNode_Scale::Handle::cast_dynamic(value_desc.get_value_node())) + { + int link_index(scale_value_node->get_link_index_from_name("link")); + if(scale_value_node->is_invertible(get_time())) + return canvas_interface()->change_value( + synfigapp::ValueDesc(scale_value_node,link_index), + scale_value_node->get_inverse(get_time(), value) + ); + else + return false; + } + switch(value_desc.get_value_type()) { case ValueBase::TYPE_REAL: return canvas_interface()->change_value(value_desc,value.mag()); - break; case ValueBase::TYPE_ANGLE: return canvas_interface()->change_value(value_desc,Angle::tan(value[1],value[0])); - break; default: return canvas_interface()->change_value(value_desc,value); - break; } - - return true; } bool CanvasView::on_duck_angle_changed(const synfig::Angle &rotation,const synfigapp::ValueDesc& value_desc) { + if (ValueNode_BLineCalcTangent::Handle bline_tangent = ValueNode_BLineCalcTangent::Handle::cast_dynamic(value_desc.get_value_node())) + { + int offset_index(bline_tangent->get_link_index_from_name("offset")); + Angle old_offset((*(bline_tangent->get_link(offset_index)))(get_time()).get(Angle())); + return canvas_interface()->change_value(synfigapp::ValueDesc(bline_tangent,offset_index), old_offset + rotation); + } + + if (ValueNode_Scale::Handle scale_value_node = ValueNode_Scale::Handle::cast_dynamic(value_desc.get_value_node())) + { + int link_index(scale_value_node->get_link_index_from_name("link")); + if(scale_value_node->is_invertible(get_time())) + return canvas_interface()->change_value( + synfigapp::ValueDesc(scale_value_node,link_index), + scale_value_node->get_inverse(get_time(), rotation) + ); + else + return false; + + } // \todo will this really always be the case? assert(value_desc.get_value_type() == ValueBase::TYPE_ANGLE); return canvas_interface()->change_value(value_desc, value_desc.get_value(get_time()).get(Angle()) + rotation); @@ -2768,15 +3084,16 @@ CanvasView::rebuild_ducks_layer_(synfig::TransformStack& transform_stack, synfig Vector origin(layer->get_param("origin").get(Vector())); Canvas::Handle child_canvas(layer->get_param("canvas").get(Canvas::Handle())); + Vector focus(layer->get_param("focus").get(Vector())); if(!scale.is_equal_to(Vector(1,1))) - transform_stack.push(new Transform_Scale(scale,origin)); - if(!scale.is_equal_to(Vector(0,0))) - transform_stack.push(new Transform_Translate(origin)); + transform_stack.push(new Transform_Scale(layer->get_guid(), scale,origin+focus)); + if(!origin.is_equal_to(Vector(0,0))) + transform_stack.push(new Transform_Translate(layer->get_guid(), origin)); rebuild_ducks_layer_(transform_stack,child_canvas,selected_list); - if(!scale.is_equal_to(Vector(0,0))) + if(!origin.is_equal_to(Vector(0,0))) transform_stack.pop(); if(!scale.is_equal_to(Vector(1,1))) transform_stack.pop(); @@ -2888,9 +3205,11 @@ CanvasView::rebuild_ducks() void CanvasView::decrease_low_res_pixel_size() { + if(changing_resolution_) + return; + changing_resolution_=true; list sizes = CanvasView::get_pixel_sizes(); int pixel_size = work_area->get_low_res_pixel_size(); - for (list::iterator iter = sizes.begin(); iter != sizes.end(); iter++) if (*iter == pixel_size) { @@ -2906,17 +3225,32 @@ CanvasView::decrease_low_res_pixel_size() } break; } + // Update the "toggle-low-res" action + Glib::RefPtr action = Glib::RefPtr::cast_dynamic(action_group->get_action("toggle-low-res")); + action->set_active(work_area->get_low_resolution_flag()); + // Update toggle low res button + resolutiondial->update_lowres(work_area->get_low_resolution_flag()); + changing_resolution_=false; } void CanvasView::increase_low_res_pixel_size() { + if(changing_resolution_) + return; + changing_resolution_=true; list sizes = CanvasView::get_pixel_sizes(); int pixel_size = work_area->get_low_res_pixel_size(); - if (!work_area->get_low_resolution_flag()) { + // We were using "hi res" so change it to low res. work_area->set_low_resolution_flag(true); + // Update the "toggle-low-res" action + Glib::RefPtr action = Glib::RefPtr::cast_dynamic(action_group->get_action("toggle-low-res")); + action->set_active(true); + // Update the toggle low res button + resolutiondial->update_lowres(true); + changing_resolution_=false; return; } @@ -2932,6 +3266,109 @@ CanvasView::increase_low_res_pixel_size() } break; } + // Update the "toggle-low-res" action + Glib::RefPtr action = Glib::RefPtr::cast_dynamic(action_group->get_action("toggle-low-res")); + action->set_active(work_area->get_low_resolution_flag()); + // Update toggle low res button + resolutiondial->update_lowres(work_area->get_low_resolution_flag()); + changing_resolution_=false; +} + +void +CanvasView::toggle_low_res_pixel_flag() +{ + if(changing_resolution_) + return; + changing_resolution_=true; + work_area->toggle_low_resolution_flag(); + // Update the toggle low res button + resolutiondial->update_lowres(work_area->get_low_resolution_flag()); + // Update the "toggle-low-res" action + Glib::RefPtr action = Glib::RefPtr::cast_dynamic(action_group->get_action("toggle-low-res")); + action->set_active(work_area->get_low_resolution_flag()); + changing_resolution_=false; +} + +void +CanvasView::update_quality() +{ + //if(working_depth) + // return; + if(updating_quality_) + return; + updating_quality_=true; + work_area->set_quality((int) quality_spin->get_value()); + // Update Quality Radio actions + Glib::RefPtr action=Glib::RefPtr::cast_dynamic( + action_group->get_action(strprintf("quality-%02d",(int) quality_spin->get_value())) + ); + action->set_active(); + + updating_quality_=false; +} + +void +CanvasView::set_quality(int x) +{ + if(updating_quality_) + return; + work_area->set_quality(x); + // Update the quality spin button + quality_spin->set_value(x); +} + +void +CanvasView::set_onion_skins() +{ + if(toggling_onion_skin) + return; + int onion_skins[2]; + onion_skins[0]=past_onion_spin->get_value(); + onion_skins[1]=future_onion_spin->get_value(); + work_area->set_onion_skins(onion_skins); +} + +void +CanvasView::toggle_show_grid() +{ + if(toggling_show_grid) + return; + toggling_show_grid=true; + work_area->toggle_grid(); + // Update the toggle grid show action + set_grid_show_toggle(work_area->grid_status()); + // Update the toggle grid show check button + show_grid->set_active(work_area->grid_status()); + toggling_show_grid=false; +} + +void +CanvasView::toggle_snap_grid() +{ + if(toggling_snap_grid) + return; + toggling_snap_grid=true; + work_area->toggle_grid_snap(); + // Update the toggle grid snap action + set_grid_snap_toggle(work_area->get_grid_snap()); + // Update the toggle grid snap check button + snap_grid->set_active(work_area->get_grid_snap()); + toggling_snap_grid=false; +} + +void +CanvasView::toggle_onion_skin() +{ + if(toggling_onion_skin) + return; + toggling_onion_skin=true; + work_area->toggle_onion_skin(); + // Update the toggle onion skin action + Glib::RefPtr action = Glib::RefPtr::cast_dynamic(action_group->get_action("toggle-onion-skin")); + action->set_active(work_area->get_onion_skin()); + // Update the toggle grid snap check button + onion_skin->set_active(work_area->get_onion_skin()); + toggling_onion_skin=false; } void @@ -3015,8 +3452,8 @@ CanvasView::play() return; } } + on_play_stop_pressed(); is_playing_=false; - time_adjustment().set_value(endtime); time_adjustment().value_changed(); } @@ -3073,7 +3510,7 @@ void CanvasView::show_timebar() { timebar->show(); - current_time_widget->show(); + //current_time_widget->show(); // not needed now that belongs to the timebar //keyframe_tab_child->show(); if(layer_tree) @@ -3086,7 +3523,7 @@ void CanvasView::hide_timebar() { timebar->hide(); - current_time_widget->hide(); + //current_time_widget->hide(); // not needed now that belongs to the timebar //keyframe_tab_child->hide(); if(layer_tree) layer_tree->set_show_timetrack(false); @@ -3098,7 +3535,7 @@ void CanvasView::set_sensitive_timebar(bool sensitive) { timebar->set_sensitive(sensitive); - current_time_widget->set_sensitive(sensitive); + //current_time_widget->set_sensitive(sensitive); //not needed now that belongs to timebar //keyframe_tab_child->set_sensitive(sensitive); if(layer_tree) layer_tree->set_sensitive(sensitive); @@ -3106,7 +3543,6 @@ CanvasView::set_sensitive_timebar(bool sensitive) children_tree->set_sensitive(sensitive); } - static void set_waypoint_model(std::set > waypoints, Waypoint::Model model, @@ -3121,7 +3557,7 @@ set_waypoint_model(std::set > waypoints, Waypoint waypoint(*iter); waypoint.apply_model(model); - synfigapp::Action::Handle action(synfigapp::Action::create("waypoint_set")); + synfigapp::Action::Handle action(synfigapp::Action::create("WaypointSet")); assert(action); @@ -3174,8 +3610,7 @@ remove_waypoints(std::set > waypoints, void CanvasView::on_waypoint_clicked_canvasview(synfigapp::ValueDesc value_desc, std::set > waypoint_set, - int button, - synfig::Waypoint::Side side) + int button) { int size = waypoint_set.size(); Waypoint waypoint(*(waypoint_set.begin())); @@ -3198,52 +3633,65 @@ CanvasView::on_waypoint_clicked_canvasview(synfigapp::ValueDesc value_desc, Gtk::Menu* waypoint_menu(manage(new Gtk::Menu())); waypoint_menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), waypoint_menu)); - Waypoint::Model model; - String side_string(String(" ") + (side==Waypoint::SIDE_LEFT ? _("In") : _("Out"))); + Gtk::Menu* interp_menu_in(manage(new Gtk::Menu())); + Gtk::Menu* interp_menu_out(manage(new Gtk::Menu())); + Gtk::Menu* interp_menu_both(manage(new Gtk::Menu())); - // ------------------------------------------------------------------------ - if(side==Waypoint::SIDE_LEFT) model.set_before(INTERPOLATION_TCB); - else model.set_after(INTERPOLATION_TCB); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_TCB") + side_string, - sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); - - if(side==Waypoint::SIDE_LEFT) model.set_before(INTERPOLATION_LINEAR); - else model.set_after(INTERPOLATION_LINEAR); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Linear") + side_string, - sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); - - if(side==Waypoint::SIDE_LEFT) model.set_before(INTERPOLATION_HALT); - else model.set_after(INTERPOLATION_HALT); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Ease") + side_string, - sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); - - if(side==Waypoint::SIDE_LEFT) model.set_before(INTERPOLATION_CONSTANT); - else model.set_after(INTERPOLATION_CONSTANT); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Constant") + side_string, - sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + { + Waypoint::Model model; + + model.reset(); model.set_before(INTERPOLATION_TCB); + interp_menu_in->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_TCB"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + model.reset(); model.set_after(INTERPOLATION_TCB); + interp_menu_out->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_TCB"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + model.set_before(INTERPOLATION_TCB); + interp_menu_both->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_TCB"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + + model.reset(); model.set_before(INTERPOLATION_LINEAR); + interp_menu_in->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Linear"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + model.reset(); model.set_after(INTERPOLATION_LINEAR); + interp_menu_out->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Linear"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + model.set_before(INTERPOLATION_LINEAR); + interp_menu_both->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Linear"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + + model.reset(); model.set_before(INTERPOLATION_HALT); + interp_menu_in->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Ease In"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + model.reset(); model.set_after(INTERPOLATION_HALT); + interp_menu_out->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Ease Out"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + model.set_before(INTERPOLATION_HALT); + interp_menu_both->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Ease In/Out"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + + model.reset(); model.set_before(INTERPOLATION_CONSTANT); + interp_menu_in->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Constant"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + model.reset(); model.set_after(INTERPOLATION_CONSTANT); + interp_menu_out->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Constant"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + model.set_before(INTERPOLATION_CONSTANT); + interp_menu_both->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Constant"), + sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + } // ------------------------------------------------------------------------ - waypoint_menu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); - - model.set_after(INTERPOLATION_TCB); model.set_before(INTERPOLATION_TCB); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("TC_B Both"), - sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); - - model.set_after(INTERPOLATION_LINEAR); model.set_before(INTERPOLATION_LINEAR); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Li_near Both"), - sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); - - model.set_after(INTERPOLATION_HALT); model.set_before(INTERPOLATION_HALT); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Ea_se Both"), - sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + if (size == 1) + { + const synfigapp::ValueDesc value_desc(synfig::ValueNode_Animated::Handle::cast_reinterpret(waypoint.get_parent_value_node()), time); + get_instance()->make_param_menu(waypoint_menu,canvas_interface()->get_canvas(),value_desc,0.5f); - model.set_after(INTERPOLATION_CONSTANT); model.set_before(INTERPOLATION_CONSTANT); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("C_onstant Both"), - sigc::bind(sigc::ptr_fun(set_waypoint_model), waypoint_set, model, canvas_interface()))); + // ------------------------------------------------------------------------ + waypoint_menu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + } // ------------------------------------------------------------------------ - waypoint_menu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Jump To"), sigc::bind(sigc::mem_fun(*canvas_interface(), &synfigapp::CanvasInterface::set_time), time))); @@ -3254,9 +3702,18 @@ CanvasView::on_waypoint_clicked_canvasview(synfigapp::ValueDesc value_desc, sigc::bind(sigc::ptr_fun(remove_waypoints), waypoint_set, canvas_interface()))); if (size == 1 && value_desc.is_valid()) - waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Properties"), + waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Edit"), sigc::mem_fun(waypoint_dialog,&Gtk::Widget::show))); + // ------------------------------------------------------------------------ + waypoint_menu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); + + // ------------------------------------------------------------------------ + waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Both"), *interp_menu_both)); + waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_In"), *interp_menu_in)); + waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Out"), *interp_menu_out)); + + // ------------------------------------------------------------------------ waypoint_menu->popup(button+1,gtk_get_current_event_time()); } break; @@ -3276,7 +3733,7 @@ CanvasView::on_waypoint_changed() param_list.add("waypoint",waypoint_dialog.get_waypoint()); // param_list.add("time",canvas_interface()->get_time()); - get_instance()->process_action("waypoint_set_smart", param_list); + get_instance()->process_action("WaypointSetSmart", param_list); } void @@ -3289,7 +3746,7 @@ CanvasView::on_waypoint_delete() param_list.add("waypoint",waypoint_dialog.get_waypoint()); // param_list.add("time",canvas_interface()->get_time()); - get_instance()->process_action("waypoint_remove", param_list); + get_instance()->process_action("WaypointRemove", param_list); } void @@ -3313,7 +3770,7 @@ CanvasView::on_drop_drag_data_received(const Glib::RefPtr& con if(!layer->set_param("text",ValueBase(selection_data))) break; - synfigapp::Action::Handle action(synfigapp::Action::create("layer_add")); + synfigapp::Action::Handle action(synfigapp::Action::create("LayerAdd")); assert(action); if(!action) @@ -3377,8 +3834,11 @@ CanvasView::on_drop_drag_data_received(const Glib::RefPtr& con } else { - if(canvas_interface()->import(filename)) + String errors, warnings; + if(canvas_interface()->import(filename, errors, warnings, App::resize_imported_images)) success=true; + if (warnings != "") + App::dialog_warning_blocking(_("Warnings"), strprintf("%s:\n\n%s", _("Warnings"), warnings.c_str())); } continue; @@ -3395,7 +3855,7 @@ CanvasView::on_drop_drag_data_received(const Glib::RefPtr& con void CanvasView::on_keyframe_add_pressed() { - synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_add")); + synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeAdd")); if(!action) { @@ -3423,7 +3883,7 @@ CanvasView::on_keyframe_duplicate_pressed() } keyframe=row[model.keyframe]; - synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_duplicate")); + synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeDuplicate")); if(!action) { @@ -3452,7 +3912,7 @@ CanvasView::on_keyframe_remove_pressed() } keyframe=row[model.keyframe]; - synfigapp::Action::Handle action(synfigapp::Action::create("keyframe_remove")); + synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeRemove")); if(!action) { @@ -3467,65 +3927,58 @@ CanvasView::on_keyframe_remove_pressed() canvas_interface()->get_instance()->perform_action(action); } - void CanvasView::toggle_duck_mask(Duckmatic::Type type) { + if(toggling_ducks_) + return; + toggling_ducks_=true; bool is_currently_on(work_area->get_type_mask()&type); - switch(type) - { - case Duck::TYPE_POSITION: - if(duck_mask_position) - duck_mask_position->set_active(!is_currently_on); - break; - - case Duck::TYPE_VERTEX: - if(duck_mask_vertex) - duck_mask_vertex->set_active(!is_currently_on); - break; - - case Duck::TYPE_TANGENT: - if(duck_mask_tangent) - duck_mask_tangent->set_active(!is_currently_on); - break; - - case Duck::TYPE_RADIUS: - if(duck_mask_radius) - duck_mask_radius->set_active(!is_currently_on); - break; - - case Duck::TYPE_WIDTH: - if(duck_mask_width) - duck_mask_width->set_active(!is_currently_on); - break; - - case Duck::TYPE_ANGLE: - if(duck_mask_angle) - duck_mask_angle->set_active(!is_currently_on); - break; - - default: - synfig::warning("CanvasView::toggle_duck_mask():Unknown duck type!"); - break; - } - if(is_currently_on) work_area->set_type_mask(work_area->get_type_mask()-type); else work_area->set_type_mask(work_area->get_type_mask()|type); work_area->queue_draw(); + try + { + // Update the toggle ducks actions + Glib::RefPtr action; + action = Glib::RefPtr::cast_dynamic(action_group->get_action("mask-position-ducks")); + action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_POSITION)); + action = Glib::RefPtr::cast_dynamic(action_group->get_action("mask-tangent-ducks")); + action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_TANGENT)); + action = Glib::RefPtr::cast_dynamic(action_group->get_action("mask-vertex-ducks")); + action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_VERTEX)); + action = Glib::RefPtr::cast_dynamic(action_group->get_action("mask-radius-ducks")); + action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_RADIUS)); + action = Glib::RefPtr::cast_dynamic(action_group->get_action("mask-width-ducks")); + action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_WIDTH)); + action = Glib::RefPtr::cast_dynamic(action_group->get_action("mask-angle-ducks")); + action->set_active((bool)(work_area->get_type_mask()&Duck::TYPE_ANGLE)); + // Update toggle ducks buttons + toggleducksdial->update_toggles(work_area->get_type_mask()); + } + catch(...) + { + toggling_ducks_=false; + } + toggling_ducks_=false; } - void CanvasView::image_import() { // String filename(dirname(get_canvas()->get_file_name())); String filename("*.*"); + String errors, warnings; if(App::dialog_open_file(_("Import Image"), filename, IMAGE_DIR_PREFERENCE)) - canvas_interface()->import(filename); + { + canvas_interface()->import(filename, errors, warnings, App::resize_imported_images); + if (warnings != "") + App::dialog_warning_blocking(_("Warnings"), strprintf("%s:\n\n%s", _("Warnings"), warnings.c_str())); + } } Smach::event_result @@ -3713,8 +4166,6 @@ CanvasView::on_audio_scrub() return true; } - - Glib::RefPtr CanvasView::get_ref_obj(const synfig::String& x) { @@ -3793,3 +4244,30 @@ CanvasView::on_delete_event(GdkEventAny* event __attribute__ ((unused))) return true; } + +//! Modify the play stop button apearence and play stop the animation +void +CanvasView::on_play_stop_pressed() +{ + Gtk::Image *icon; + Gtk::Button *stop_button; + stop_button=framedial->get_play_button(); + bool play_flag; + if(!is_playing()) + { + icon = manage(new Gtk::Image(Gtk::Stock::MEDIA_STOP, Gtk::IconSize::from_name("synfig-small_icon"))); + stop_button->set_relief(Gtk::RELIEF_NORMAL); + play_flag=true; + } + else + { + icon = manage(new Gtk::Image(Gtk::Stock::MEDIA_PLAY, Gtk::IconSize::from_name("synfig-small_icon"))); + stop_button->set_relief(Gtk::RELIEF_NONE); + play_flag=false; + } + stop_button->remove(); + stop_button->add(*icon); + icon->set_padding(0, 0); + icon->show(); + if(play_flag) play(); else stop(); +}