Added copyright lines for files I've edited this year.
[synfig.git] / synfig-studio / trunk / src / gtkmm / canvasview.cpp
index 336b452..ad2ab6b 100644 (file)
@@ -6,7 +6,7 @@
 **
 **     \legal
 **     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
-**     Copyright (c) 2007 Chris Moore
+**     Copyright (c) 2007, 2008 Chris Moore
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
@@ -1057,6 +1057,13 @@ void
 CanvasView::on_current_time_widget_changed()
 {
        set_time(current_time_widget->get_value());
+
+       // show the value being used - it will have been rounded to nearest frame
+       // this was already being done elsewhere, but only if the time was really changed;
+       // if the current time was 6f and the user edited it to 6.1f, then the 6.1f would
+       // be left in the display without the following line to fix it
+       current_time_widget->set_value(get_time());
+       current_time_widget->set_position(-1); // leave the cursor at the end
 }
 
 //     Gtk::Widget*
@@ -1073,7 +1080,7 @@ CanvasView::on_current_time_widget_changed()
 //             // Connect Signals
 //             if(children_tree)children_tree->signal_edited_value().connect(sigc::mem_fun(*this, &studio::CanvasView::on_edited_value));
 //             if(children_tree)children_tree->signal_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
-//             if(children_tree)children_tree->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked));
+//             if(children_tree)children_tree->signal_waypoint_clicked_childrentree().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked_canvasview));
 //             if(children_tree)children_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
 //
 //             return children_tree;
@@ -1155,7 +1162,7 @@ CanvasView::on_current_time_widget_changed()
 //             layer_tree->signal_edited_value().connect(sigc::mem_fun(*this, &studio::CanvasView::on_edited_value));
 //             layer_tree->signal_layer_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_layer_user_click));
 //             layer_tree->signal_param_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
-//             layer_tree->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked));
+//             layer_tree->signal_waypoint_clicked_layertree().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked_canvasview));
 //             layer_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
 //
 //             layer_tree->hide();
@@ -1288,7 +1295,7 @@ CanvasView::init_menus()
                        if (i == 10) note = _(" (fastest)");
                        Glib::RefPtr<Gtk::RadioAction> action(Gtk::RadioAction::create(quality_group,strprintf("quality-%02d",i),
                                                                                                                                                   strprintf(_("Set Quality to %d"),i) + note));
-                       if(i==9)                        // default quality
+                       if (i==8)                       // default quality
                        {
                                action->set_active();
                                work_area->set_quality(i);
@@ -2437,7 +2444,12 @@ CanvasView::on_time_changed()
 void
 CanvasView::time_zoom_in()
 {
+       float frame_rate = get_canvas()->rend_desc().get_frame_rate();
+       Time min_page_size = 2/frame_rate;
+
        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().changed();
 
        refresh_time_window();
@@ -2446,7 +2458,12 @@ CanvasView::time_zoom_in()
 void
 CanvasView::time_zoom_out()
 {
+       Time length = (get_canvas()->rend_desc().get_time_end() -
+                                  get_canvas()->rend_desc().get_time_start());
+
        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().changed();
 
        refresh_time_window();
@@ -3090,66 +3107,160 @@ CanvasView::set_sensitive_timebar(bool sensitive)
 }
 
 
+static void
+set_waypoint_model(std::set<synfig::Waypoint, std::less<UniqueID> > waypoints,
+                                  Waypoint::Model model,
+                                  etl::loose_handle<synfigapp::CanvasInterface> canvas_interface)
+{
+       // Create the action group
+       synfigapp::Action::PassiveGrouper group(canvas_interface->get_instance().get(),_("Change Waypoint Group"));
+
+       std::set<synfig::Waypoint, std::less<UniqueID> >::const_iterator iter;
+       for(iter=waypoints.begin();iter!=waypoints.end();++iter)
+       {
+               Waypoint waypoint(*iter);
+               waypoint.apply_model(model);
+
+               synfigapp::Action::Handle action(synfigapp::Action::create("waypoint_set"));
+
+               assert(action);
+
+               action->set_param("canvas",canvas_interface->get_canvas());
+               action->set_param("canvas_interface",canvas_interface);
+
+               action->set_param("waypoint",waypoint);
+               action->set_param("value_node",waypoint.get_parent_value_node());
+
+               if(!canvas_interface->get_instance()->perform_action(action))
+               {
+                       group.cancel();
+                       return;
+               }
+       }
+}
+
+static void
+duplicate_waypoints(std::set<synfig::Waypoint, std::less<UniqueID> > waypoints,
+                                       etl::loose_handle<synfigapp::CanvasInterface> canvas_interface)
+{
+       // Create the action group
+       synfigapp::Action::PassiveGrouper group(canvas_interface->get_instance().get(),_("Duplicate Waypoints"));
+
+       std::set<synfig::Waypoint, std::less<UniqueID> >::const_iterator iter;
+       for (iter = waypoints.begin(); iter != waypoints.end(); iter++)
+       {
+               Waypoint waypoint(*iter);
+               ValueNode::Handle value_node(iter->get_parent_value_node());
+               canvas_interface->waypoint_duplicate(value_node, waypoint);
+       }
+}
+
+static void
+remove_waypoints(std::set<synfig::Waypoint, std::less<UniqueID> > waypoints,
+                                etl::loose_handle<synfigapp::CanvasInterface> canvas_interface)
+{
+       // Create the action group
+       synfigapp::Action::PassiveGrouper group(canvas_interface->get_instance().get(),_("Remove Waypoints"));
+
+       std::set<synfig::Waypoint, std::less<UniqueID> >::const_iterator iter;
+       for (iter = waypoints.begin(); iter != waypoints.end(); iter++)
+       {
+               Waypoint waypoint(*iter);
+               ValueNode::Handle value_node(iter->get_parent_value_node());
+               canvas_interface->waypoint_remove(value_node, waypoint);
+       }
+}
+
 void
-CanvasView::on_waypoint_clicked(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint,int button)
+CanvasView::on_waypoint_clicked_canvasview(synfigapp::ValueDesc value_desc,
+                                                                                  std::set<synfig::Waypoint, std::less<UniqueID> > waypoint_set,
+                                                                                  int button,
+                                                                                  synfig::Waypoint::Side side)
 {
-       waypoint_dialog.set_value_desc(value_desc);
-       waypoint_dialog.set_waypoint(waypoint);
+       int size = waypoint_set.size();
+       Waypoint waypoint(*(waypoint_set.begin()));
+       Time time(waypoint.get_time());
+
+       if (size == 1)
+       {
+               waypoint_dialog.set_value_desc(value_desc);
+               waypoint_dialog.set_waypoint(waypoint);
+       }
 
        switch(button)
        {
        case -1:
-               waypoint_dialog.show();
+               if (size == 1)
+                       waypoint_dialog.show();
                break;
        case 2:
-               {
-                       Gtk::Menu* waypoint_menu(manage(new Gtk::Menu()));
-                       waypoint_menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), waypoint_menu));
+       {
+               Gtk::Menu* waypoint_menu(manage(new Gtk::Menu()));
+               waypoint_menu->signal_hide().connect(sigc::bind(sigc::ptr_fun(&delete_widget), waypoint_menu));
 
-                       waypoint_menu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-jump-to"),
-                               sigc::bind(
-                                       sigc::mem_fun(
-                                               *canvas_interface(),
-                                               &synfigapp::CanvasInterface::set_time
-                                       ),
-                                       waypoint.get_time()
-                               )
-                       ));
+               Waypoint::Model model;
+               String side_string(String(" ") + (side==Waypoint::SIDE_LEFT ? _("In") : _("Out")));
 
-                       waypoint_menu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID(_("Edit Waypoint")),
-                               sigc::mem_fun(
-                                       waypoint_dialog,
-                                       &Gtk::Widget::show
-                               )
-                       ));
+               // ------------------------------------------------------------------------
+               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_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())));
+
+               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::MenuElem(_("_Jump To"),
+                       sigc::bind(sigc::mem_fun(*canvas_interface(), &synfigapp::CanvasInterface::set_time), time)));
+
+               waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("_Duplicate"),
+                        sigc::bind(sigc::ptr_fun(duplicate_waypoints), waypoint_set, canvas_interface())));
+
+               waypoint_menu->items().push_back(Gtk::Menu_Helpers::MenuElem((size == 1) ? _("_Remove") : strprintf(_("_Remove %d Waypoints"), size),
+                        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"),
+                               sigc::mem_fun(waypoint_dialog,&Gtk::Widget::show)));
+
+               waypoint_menu->popup(button+1,gtk_get_current_event_time());
+       }
+       break;
 
-                       waypoint_menu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("synfig-duplicate"),
-                               sigc::bind(
-                                       sigc::bind(
-                                               sigc::mem_fun(
-                                                       *canvas_interface(),
-                                                       &synfigapp::CanvasInterface::waypoint_duplicate
-                                               ),
-                                               waypoint
-                                       ),
-                                       value_desc
-                               )
-                       ));
-                       waypoint_menu->items().push_back(Gtk::Menu_Helpers::StockMenuElem(Gtk::StockID("gtk-delete"),
-                               sigc::bind(
-                                       sigc::bind(
-                                               sigc::mem_fun(
-                                                       *canvas_interface(),
-                                                       &synfigapp::CanvasInterface::waypoint_remove
-                                               ),
-                                               waypoint
-                                       ),
-                                       value_desc
-                               )
-                       ));
-                       waypoint_menu->popup(button+1,gtk_get_current_event_time());
-               }
-               break;
        default:
                break;
        }
@@ -3658,13 +3769,13 @@ CanvasView::set_ext_widget(const synfig::String& x, Gtk::Widget* y)
                layer_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
                layer_tree->signal_layer_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_layer_user_click));
                layer_tree->signal_param_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
-               layer_tree->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked));
+               layer_tree->signal_waypoint_clicked_layertree().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked_canvasview));
        }
        if(x=="children")
        {
                children_tree=dynamic_cast<ChildrenTree*>(y);
                if(children_tree)children_tree->signal_user_click().connect(sigc::mem_fun(*this, &studio::CanvasView::on_children_user_click));
-               if(children_tree)children_tree->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked));
+               if(children_tree)children_tree->signal_waypoint_clicked_childrentree().connect(sigc::mem_fun(*this, &studio::CanvasView::on_waypoint_clicked_canvasview));
                if(children_tree)children_tree->get_selection()->signal_changed().connect(SLOT_EVENT(EVENT_REFRESH_DUCKS));
        }
        if(x=="keyframes")