diff --git a/synfig-studio/src/gui/canvasview.cpp b/synfig-studio/src/gui/canvasview.cpp index 844a65d..da7eed9 100644 --- a/synfig-studio/src/gui/canvasview.cpp +++ b/synfig-studio/src/gui/canvasview.cpp @@ -857,7 +857,7 @@ Gtk::Widget* CanvasView::create_time_bar() { //Setup the keyframe list widget - widget_kf_list->set_time_adjustment(time_model()->visible_time_adjustment()); + widget_kf_list->set_time_model(time_model()); widget_kf_list->set_canvas_interface(canvas_interface()); widget_kf_list->show(); @@ -1763,7 +1763,6 @@ CanvasView::refresh_rend_desc() current_time_widget->set_fps(current_frame_rate); jackdial->set_fps(current_frame_rate); - widget_kf_list->set_fps(current_frame_rate); timeslider->set_global_fps(current_frame_rate); time_model()->set_bounds(begin_time, end_time, current_frame_rate); diff --git a/synfig-studio/src/gui/docks/dock_curves.cpp b/synfig-studio/src/gui/docks/dock_curves.cpp index e0bf628..6fc8f18 100644 --- a/synfig-studio/src/gui/docks/dock_curves.cpp +++ b/synfig-studio/src/gui/docks/dock_curves.cpp @@ -161,7 +161,7 @@ Dock_Curves::changed_canvas_view_vfunc(etl::loose_handle canvas_view widget_timeslider_.set_bounds_adjustment( Glib::RefPtr() ); widget_timeslider_.set_canvas_view( CanvasView::Handle() ); - widget_kf_list_.set_time_adjustment( Glib::RefPtr() ); + widget_kf_list_.set_time_model( etl::handle() ); widget_kf_list_.set_canvas_interface( etl::loose_handle() ); } @@ -178,7 +178,7 @@ Dock_Curves::changed_canvas_view_vfunc(etl::loose_handle canvas_view widget_timeslider_.set_global_fps(canvas_view->get_canvas()->rend_desc().get_frame_rate()); widget_timeslider_.set_canvas_view(canvas_view); - widget_kf_list_.set_time_adjustment(canvas_view->time_model()->visible_time_adjustment()); + widget_kf_list_.set_time_model(canvas_view->time_model()); widget_kf_list_.set_canvas_interface(canvas_view->canvas_interface()); table_=new Gtk::Table(3, 2); diff --git a/synfig-studio/src/gui/docks/dock_timetrack.cpp b/synfig-studio/src/gui/docks/dock_timetrack.cpp index a10983f..864b1ad 100644 --- a/synfig-studio/src/gui/docks/dock_timetrack.cpp +++ b/synfig-studio/src/gui/docks/dock_timetrack.cpp @@ -502,7 +502,7 @@ Dock_Timetrack::changed_canvas_view_vfunc(etl::loose_handle canvas_v widget_timeslider_.set_bounds_adjustment( Glib::RefPtr() ); widget_timeslider_.set_canvas_view( CanvasView::Handle() ); - widget_kf_list_.set_time_adjustment( Glib::RefPtr() ); + widget_kf_list_.set_time_model( etl::handle() ); widget_kf_list_.set_canvas_interface( etl::loose_handle() ); delete table_; @@ -534,7 +534,7 @@ Dock_Timetrack::changed_canvas_view_vfunc(etl::loose_handle canvas_v widget_timeslider_.set_global_fps(canvas_view->get_canvas()->rend_desc().get_frame_rate()); widget_timeslider_.set_canvas_view(canvas_view); - widget_kf_list_.set_time_adjustment(canvas_view->time_model()->visible_time_adjustment()); + widget_kf_list_.set_time_model(canvas_view->time_model()); widget_kf_list_.set_canvas_interface(canvas_view->canvas_interface()); vscrollbar_.set_adjustment(tree_view->get_vadjustment()); diff --git a/synfig-studio/src/gui/trees/keyframetree.cpp b/synfig-studio/src/gui/trees/keyframetree.cpp index b411c4c..6ee79d9 100644 --- a/synfig-studio/src/gui/trees/keyframetree.cpp +++ b/synfig-studio/src/gui/trees/keyframetree.cpp @@ -350,28 +350,20 @@ KeyframeTree::on_selection_changed() //Connected on treeview::selection::changed //if(send_selection && has_focus () && get_selection()->count_selected_rows()==1) - if(send_selection && get_selection()->count_selected_rows()==1) - { - + if(send_selection && get_selection()->count_selected_rows()==1) { Keyframe keyframe((*get_selection()->get_selected())[model.keyframe]); - if(keyframe && keyframe != selected_kf && keyframe_tree_store_) - { + if(keyframe && keyframe != selected_kf && keyframe_tree_store_) { selected_kf = keyframe; - keyframe_tree_store_->canvas_interface()->signal_keyframe_selected()(keyframe, (void*)this); + keyframe_tree_store_->canvas_interface()->signal_keyframe_selected()(keyframe); } - } } void -KeyframeTree::on_keyframe_selected(synfig::Keyframe keyframe, void* emitter) +KeyframeTree::on_keyframe_selected(synfig::Keyframe keyframe) { Gtk::TreeModel::Path path; - - if((void*)this == emitter) return; - - if(keyframe && keyframe != selected_kf) - { + if (keyframe && keyframe != selected_kf) { selected_kf = keyframe; send_selection = false; if(keyframe_tree_store_ && keyframe_tree_store_->find_keyframe_path(keyframe,path)) diff --git a/synfig-studio/src/gui/trees/keyframetree.h b/synfig-studio/src/gui/trees/keyframetree.h index bb1b339..8d9ec8e 100644 --- a/synfig-studio/src/gui/trees/keyframetree.h +++ b/synfig-studio/src/gui/trees/keyframetree.h @@ -126,7 +126,7 @@ private: void on_selection_changed(); //! Signal handler for select keyframe signal from canvas interface - void on_keyframe_selected(synfig::Keyframe, void* emitter); + void on_keyframe_selected(synfig::Keyframe); sigc::connection keyframeselected; /* diff --git a/synfig-studio/src/gui/widgets/widget_keyframe_list.cpp b/synfig-studio/src/gui/widgets/widget_keyframe_list.cpp index af6f3a4..bb203a9 100644 --- a/synfig-studio/src/gui/widgets/widget_keyframe_list.cpp +++ b/synfig-studio/src/gui/widgets/widget_keyframe_list.cpp @@ -9,6 +9,7 @@ ** Copyright (c) 2007 Chris Moore ** Copyright (c) 2009 Carlos López ** Copyright (c) 2012-2013 Konstantin Dmitriev +** ......... ... 2018 Ivan Mahonin ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as @@ -32,28 +33,22 @@ # include #endif +#include #include - +#include #include "widget_keyframe_list.h" -#include "app.h" -#include -#include -#include - #include #endif /* === U S I N G =========================================================== */ -using namespace std; -using namespace etl; using namespace synfig; +using namespace synfigapp; using namespace studio; - /* === M A C R O S ========================================================= */ -#define WIDGET_KEYFRAME_LIST_DEFAULT_FPS 24.0 + /* === G L O B A L S ======================================================= */ /* === P R O C E D U R E S ================================================= */ @@ -61,43 +56,38 @@ using namespace studio; /* === M E T H O D S ======================================================= */ Widget_Keyframe_List::Widget_Keyframe_List(): - adj_default(Gtk::Adjustment::create(0,0,2,1/WIDGET_KEYFRAME_LIST_DEFAULT_FPS,10/WIDGET_KEYFRAME_LIST_DEFAULT_FPS)), - kf_list_(&default_kf_list_), - time_ratio("4f", WIDGET_KEYFRAME_LIST_DEFAULT_FPS), - dragging_(false), - changed_(false), - selected_(false), - moving_tooltip_y_(0) + kf_list(), + editable(true), + dragging(), + changed(), + selected(), + moving_tooltip(Gtk::WINDOW_POPUP), + moving_tooltip_y() { - editable_=true; - fps=WIDGET_KEYFRAME_LIST_DEFAULT_FPS; - set_size_request(-1,64); - //! The widget respond to mouse button press and release and to - //! left button motion - add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); - add_events(Gdk::BUTTON1_MOTION_MASK /*| Gdk::BUTTON3_MOTION_MASK*/); - add_events(Gdk::POINTER_MOTION_MASK); - set_time_adjustment(adj_default); - queue_draw(); - - //! Create the window of the moving tooltip - moving_tooltip_ = new Gtk::Window(Gtk::WINDOW_POPUP); - moving_tooltip_->set_resizable(false); - moving_tooltip_->set_name("gtk-tooltips"); - moving_tooltip_->set_border_width (4); - moving_tooltip_->set_default_size(10, 10); - moving_tooltip_->set_type_hint(Gdk::WINDOW_TYPE_HINT_TOOLTIP); - - moving_tooltip_label_ = Gtk::manage(new Gtk::Label()); - moving_tooltip_label_->set_alignment(0.5, 0.5); - moving_tooltip_label_->show(); - - moving_tooltip_->add(*moving_tooltip_label_); + set_size_request(-1, 64); + add_events( Gdk::BUTTON_PRESS_MASK + | Gdk::BUTTON_RELEASE_MASK + | Gdk::BUTTON1_MOTION_MASK + | Gdk::POINTER_MOTION_MASK ); + + // Window of the moving tooltip + + moving_tooltip_label.set_alignment(0.5, 0.5); + moving_tooltip_label.show(); + + moving_tooltip.set_resizable(false); + moving_tooltip.set_name("gtk-tooltips"); + moving_tooltip.set_border_width(4); + moving_tooltip.set_default_size(10, 10); + moving_tooltip.set_type_hint(Gdk::WINDOW_TYPE_HINT_TOOLTIP); + moving_tooltip.add(moving_tooltip_label); } Widget_Keyframe_List::~Widget_Keyframe_List() { - delete moving_tooltip_; + set_time_model(etl::handle()); + set_kf_list(NULL); + set_canvas_interface(etl::loose_handle()); } void @@ -106,8 +96,9 @@ Widget_Keyframe_List::draw_arrow( double x, double y, double width, double height, bool fill, - const synfig::Color &color ) + const Color &color ) { + cr->save(); cr->set_source_rgba(color.get_r(), color.get_g(), color.get_b(), color.get_a()); cr->set_line_width(1.0); cr->move_to(x, y); @@ -115,14 +106,30 @@ Widget_Keyframe_List::draw_arrow( cr->line_to(x + 0.5*width, y - height); cr->close_path(); if (fill) cr->fill(); else cr->stroke(); + cr->restore(); } bool Widget_Keyframe_List::on_draw(const Cairo::RefPtr &cr) { - //!Check if the window we want draw is ready - Glib::RefPtr window = get_window(); - if(!window) return true; + // Check if the window we want draw is ready + if (!time_model) + return false; + + // TODO: hardcoded colors + // Colors + Color background(0.46, 0.55, 0.70, 1.0); + Color normal(0.0, 0.0, 0.0, 1.0); + Color selected(1.0, 1.0, 1.0, 1.0); + Color drag_old_position(1.0, 1.0, 1.0, 0.6); + Color drag_new_position(1.0, 1.0, 1.0, 1.0); + + if (!editable) { + normal.set_a(0.5); + selected.set_a(0.5); + drag_old_position.set_a(0.3); + drag_new_position.set_a(0.5); + } const double h(get_height()); const double w(get_width()); @@ -130,194 +137,156 @@ Widget_Keyframe_List::on_draw(const Cairo::RefPtr &cr) const double ah(h - 4); const double aw(2*ah); - //!Boundaries of the drawing area in time units. - synfig::Time top(adj_timescale->get_upper()); - synfig::Time bottom(adj_timescale->get_lower()); + if (w <= 0 || h <= 0) + return false; - //! The style of the widget. - Glib::RefPtr style = get_style_context(); + // Boundaries of the drawing area in time units. + Time lower(time_model->get_visible_lower()); + Time upper(time_model->get_visible_upper()); - //TODO hardcoded colors - //! Colors - Color background(0.46, 0.55, 0.70, 1.0); - Color normal(0.0, 0.0, 0.0, 1.0); - Color selected(1.0, 1.0, 1.0, 1.0); - Color drag_old_position(1.0, 1.0, 1.0, 0.6); - Color drag_new_position(1.0, 1.0, 1.0, 1.0); + time_ratio = (upper - lower)*(0.5*(double)aw/(double)w); + Time lower_ex = lower - time_ratio; + Time upper_ex = upper + time_ratio; + double k = (double)w/(double)(upper - lower); - //! Draw a background + // Draw a background cr->save(); cr->set_source_rgba(background.get_r(), background.get_g(), background.get_b(), background.get_a()); cr->rectangle(0.0, 0.0, w, h); cr->fill(); cr->restore(); - if(!editable_) - { - return true; //needs fixing! - } - //!Returns if there are not keyframes to draw. - if (kf_list_->empty()) return false; - - //!Loop all the keyframes - synfig::KeyframeList::iterator iter,selected_iter; - bool show_selected(false); - - for(iter=kf_list_->begin();iter!=kf_list_->end();iter++) - { - if (iter->get_time()>top || iter->get_time()get_time()-bottom) * (w/(top-bottom)); - draw_arrow(cr, x, y, aw, ah, iter->active(), normal); - } - else - { - selected_iter=iter; - show_selected=true; + // Returns if there are not keyframes to draw. + if (!kf_list || kf_list->empty()) return true; + + // draw all keyframes + bool selected_visible = NULL; + for(KeyframeList::const_iterator i = kf_list->begin(); i != kf_list->end(); ++i) + if (lower_ex < i->get_time() && i->get_time() < upper_ex) { + if (*i == selected_kf) { + selected_visible = true; + } else { + const double x = k*(double)(i->get_time() - lower); + draw_arrow(cr, x, y, aw, ah, i->active(), normal); + } } - } // we do this so that we can be sure that // the selected keyframe is shown on top - if(show_selected) - { - if (!dragging_) - { - const double x = (double)(selected_iter->get_time()-bottom) * (w/(top-bottom)); - draw_arrow(cr, x, y, aw, ah, selected_iter->active(), selected); - } - else - { - const double prev_x = (double)(selected_iter->get_time()-bottom) * (w/(top-bottom)); - const double new_x = (double)(dragging_kf_time-bottom) * (w/(top-bottom)); - draw_arrow(cr, prev_x, y, aw, ah, selected_iter->active(), drag_old_position); - draw_arrow(cr, new_x, y, aw, ah, selected_iter->active(), drag_new_position); + if (selected_visible) { + const double x = k*(double)(selected_kf.get_time() - lower); + if (dragging) { + const double new_x = k*(double)(dragging_kf_time - lower); + draw_arrow(cr, x, y, aw, ah, selected_kf.active(), drag_old_position); + draw_arrow(cr, new_x, y, aw, ah, selected_kf.active(), drag_new_position); + } else { + draw_arrow(cr, x, y, aw, ah, selected_kf.active(), selected); } } + return true; } +void +Widget_Keyframe_List::set_kf_list(KeyframeList *x) +{ + if (kf_list == x) return; + kf_list = x; + reset_selected_keyframe(); +} void -Widget_Keyframe_List::set_kf_list(synfig::KeyframeList* x) +Widget_Keyframe_List::reset_selected_keyframe() { - kf_list_=x; - set_selected_keyframe(selected_none); - selected_=false; - dragging_=false; + selected = false; + dragging = false; } void -Widget_Keyframe_List::set_selected_keyframe(const synfig::Keyframe &x) +Widget_Keyframe_List::set_selected_keyframe(const Keyframe &x) { - if (x == selected_none) return; - - if (x == selected_kf) - { - // synfig::Keyframe::operator== only on uniqueid::operator== - // \see synfig::UniqueID::operator== - // In all case, refresh keyframe description to do not loose it - selected_kf.set_description(x.get_description()); - // refresh keyframe time also. - selected_kf.set_time(x.get_time()); - // and activation status - selected_kf.set_active(x.active()); + if (selected && x == selected_kf) { + // Keyframe::operator== only on uniqueid::operator== + // \see UniqueID::operator== + // In all case, refresh keyframe description, time and activation status to do not loose it + selected_kf = x; return; } - selected_kf=x; - selected_=true; - dragging_kf_time=selected_kf.get_time(); + selected_kf = x; + selected = true; + dragging = false; + dragging_kf_time = selected_kf.get_time(); - if(canvas_interface_) - canvas_interface_->signal_keyframe_selected()(selected_kf, (void*)this); + if (canvas_interface) + canvas_interface->signal_keyframe_selected()(selected_kf); - dragging_=false; queue_draw(); } void -Widget_Keyframe_List::on_keyframe_selected(synfig::Keyframe keyframe, void* emitter) +Widget_Keyframe_List::on_keyframe_selected(Keyframe keyframe) { - if((void*)this == emitter) return; - - if (keyframe == selected_kf) return; - - selected_kf=keyframe; - selected_=true; - - dragging_kf_time=selected_kf.get_time(); - dragging_=false; - queue_draw(); + set_selected_keyframe(keyframe); } bool -Widget_Keyframe_List::perform_move_kf(bool delta=false) +Widget_Keyframe_List::perform_move_kf(bool delta) { - if(!selected_) + if (!kf_list) + return false; + if (!selected) return false; - if(dragging_kf_time == selected_kf.get_time()) + if (dragging_kf_time == selected_kf.get_time()) return false; // change this checking if not sticked to integer frames + Time selected_kf_time(selected_kf.get_time()); Time prev, next; - kf_list_->find_prev_next(selected_kf_time, prev, next); + kf_list->find_prev_next(selected_kf_time, prev, next); + // Not possible to set delta to the first keyframe // perform normal movement // As suggested by Zelgadis it is better to not perform anything. - if (prev==Time::begin() && delta==true) - { - synfig::info(_("Not possible to ALT-drag the first keyframe")); + if (prev == Time::begin() && delta) { + info(_("Not possible to ALT-drag the first keyframe")); return false; } - if(!delta) - { - synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeSet")); - if(!action) - return false; - selected_kf.set_time(dragging_kf_time); - action->set_param("canvas",canvas_interface_->get_canvas()); - action->set_param("canvas_interface",canvas_interface_); - action->set_param("keyframe",selected_kf); - try - { - canvas_interface_->get_instance()->perform_action(action); - canvas_interface_->signal_keyframe_selected()(selected_kf, (void*)this); - } - catch(...) - { - return false; - } - } - else - { - // find prev from selected kf time including deactivated kf - Keyframe prev_kf(*kf_list_->find_prev(selected_kf_time, false)); - Time prev_kf_time(prev_kf.get_time()); - if (prev_kf_time >= dragging_kf_time) //Not allowed - { - synfig::warning(_("Delta set not allowed")); - synfig::info("Widget_Keyframe_List::perform_move_kf(%i)::prev_kf_time=%s", delta, prev_kf_time.get_string().c_str()); - synfig::info("Widget_Keyframe_List::perform_move_kf(%i)::dragging_kf_time=%s", delta, dragging_kf_time.get_string().c_str()); + if (!delta) { + Action::Handle action(Action::create("KeyframeSet")); + if (!action) return false; + selected_kf.set_time(dragging_kf_time); + action->set_param("canvas", canvas_interface->get_canvas()); + action->set_param("canvas_interface", canvas_interface); + action->set_param("keyframe", selected_kf); + try { + canvas_interface->get_instance()->perform_action(action); + canvas_interface->signal_keyframe_selected()(selected_kf); + } catch(...) { return false; } + } else { + // find prev from selected kf time including deactivated kf + Keyframe prev_kf(*kf_list->find_prev(selected_kf_time, false)); + Time prev_kf_time(prev_kf.get_time()); + if (prev_kf_time >= dragging_kf_time) { // Not allowed + warning(_("Delta set not allowed")); + info("Widget_Keyframe_List::perform_move_kf(%i)::prev_kf_time=%s", delta, prev_kf_time.get_string().c_str()); + info("Widget_Keyframe_List::perform_move_kf(%i)::dragging_kf_time=%s", delta, dragging_kf_time.get_string().c_str()); + return false; + } else { + Time old_delta_time(selected_kf_time-prev_kf_time); + Time new_delta_time(dragging_kf_time-prev_kf_time); + Time change_delta(new_delta_time-old_delta_time); + Action::Handle action(Action::create("KeyframeSetDelta")); + if (!action) return false; - } - else - { - Time old_delta_time(selected_kf_time-prev_kf_time); - Time new_delta_time(dragging_kf_time-prev_kf_time); - Time change_delta(new_delta_time-old_delta_time); - synfigapp::Action::Handle action(synfigapp::Action::create("KeyframeSetDelta")); - if(!action) - return false; - action->set_param("canvas",canvas_interface_->get_canvas()); - action->set_param("canvas_interface",canvas_interface_); - action->set_param("keyframe",prev_kf); - action->set_param("delta",change_delta); - canvas_interface_->get_instance()->perform_action(action); - } + action->set_param("canvas", canvas_interface->get_canvas()); + action->set_param("canvas_interface", canvas_interface); + action->set_param("keyframe", prev_kf); + action->set_param("delta", change_delta); + canvas_interface->get_instance()->perform_action(action); } + } + queue_draw(); return true; } @@ -325,278 +294,168 @@ Widget_Keyframe_List::perform_move_kf(bool delta=false) bool Widget_Keyframe_List::on_event(GdkEvent *event) { - //Do not respond mouse events if the list is empty - if(!kf_list_->size()) - return true; + if (!time_model || get_width() <= 0 || !kf_list || !editable) + return false; + + const int x = (int)event->button.x; + + // Boundaries of the drawing area in time units. + Time lower(time_model->get_visible_lower()); + Time upper(time_model->get_visible_upper()); - const int x(static_cast(event->button.x)); - //const int y(static_cast(event->button.y)); - //!Boundaries of the drawing area in time units. - synfig::Time top(adj_timescale->get_upper()); - synfig::Time bottom(adj_timescale->get_lower()); - //!pos is the [0,1] relative horizontal place on the widget - float pos((float)x/(get_width())); - if(pos<0.0f)pos=0.0f; - if(pos>1.0f)pos=1.0f; - //! The time where the event x is - synfig::Time t((float)(bottom+pos*(top-bottom))); - - //! here the guts of the event - switch(event->type) - { - case GDK_MOTION_NOTIFY: - if(editable_) - { + // The time where the event x is + Time t = lower + (upper - lower)*((double)x/(double)get_width()); + t = std::max(lower, std::min(upper, t)); + + // here the guts of the event + switch(event->type) { + case GDK_MOTION_NOTIFY: { + if (event->motion.state & GDK_BUTTON1_MASK) { // here is captured mouse motion // AND left or right mouse button pressed - if (event->motion.state & (GDK_BUTTON1_MASK /*| GDK_BUTTON3_MASK*/)) - { - if (!selected_) return true; - // stick to integer frames. It can be optional in the future - if(fps) t = floor(t*fps + 0.5)/fps; - dragging_kf_time=t; - dragging_=true; - queue_draw(); - - //! Moving tooltip displaying the dragging time - { - int x_root = static_cast(event->button.x_root); - int x_origin; int y_origin; - get_window()->get_origin (x_origin, y_origin); - - Glib::ustring tooltip_label (_("Time : ")); - tooltip_label.append( dragging_kf_time.get_string(fps,App::get_time_format()) ); - tooltip_label.append("\n"); - tooltip_label.append( _("Old Time : ") ); - tooltip_label.append(selected_kf.get_time().get_string(fps,App::get_time_format())); - moving_tooltip_label_->set_text (tooltip_label); - - if(!moving_tooltip_->get_visible ()) - { - //! Show the tooltip and fix his y coordinate (up to the widget) - moving_tooltip_->show(); - moving_tooltip_y_ = y_origin - moving_tooltip_->get_height(); - } - //! Move the tooltip to a nice position - moving_tooltip_->move(x_root, moving_tooltip_y_); - } + if (!selected) return true; - } + + // stick to integer frames + t = time_model->round_time(t); + + dragging_kf_time = t; + dragging = true; + + // Moving tooltip displaying the dragging time + int x_root = static_cast(event->button.x_root); + int x_origin; int y_origin; + get_window()->get_origin (x_origin, y_origin); + + moving_tooltip_label.set_text( + String(_("Time : ")) + + dragging_kf_time.get_string(time_model->get_frame_rate(), App::get_time_format()) + + "\n" + + _("Old Time : ") + + selected_kf.get_time().get_string(time_model->get_frame_rate(), App::get_time_format()) ); + + // Show the tooltip and move to a nice position + if (!moving_tooltip.get_visible()) moving_tooltip.show(); + moving_tooltip.move(x_root, y_origin - moving_tooltip.get_height()); + } else { // here is captured mouse motion // AND NOT left or right mouse button pressed - else + String ttip; + Time p_t, n_t; + kf_list->find_prev_next(t, p_t, n_t); + if ( (p_t == Time::begin() && n_t == Time::end()) + || (t - p_t > time_ratio && n_t - t > time_ratio) ) { - Glib::ustring ttip=""; - synfig::Time p_t,n_t; - kf_list_->find_prev_next(t, p_t, n_t); - if( (p_t==Time::begin() && n_t==Time::end()) - || - ((t-p_t)>time_ratio && (n_t-t)>time_ratio) - ) - { - ttip = _("Click and drag keyframes"); - } - else if ((t-p_t)<(n_t-t)) - { - synfig::Keyframe kf(*kf_list_->find_prev(t)); - synfig::String kf_name(kf.get_description().c_str()); - ttip = (kf_name.length() == 0)? _("No name") : kf_name.c_str(); - } - else - { - synfig::Keyframe kf(*kf_list_->find_next(t)); - synfig::String kf_name(kf.get_description().c_str()); - ttip = (kf_name.length() == 0)? _("No name") : kf_name.c_str(); - } - set_tooltip_text(ttip); - dragging_=false; - queue_draw(); - return true; + ttip = _("Click and drag keyframes"); + } else + if (t - p_t < n_t - t) { + Keyframe kf = *kf_list->find_prev(t); + ttip = kf.get_description().empty() ? String(_("No name")) : kf.get_description(); + } else { + Keyframe kf(*kf_list->find_next(t)); + ttip = kf.get_description().empty() ? String(_("No name")) : kf.get_description(); } + set_tooltip_text(ttip); + dragging = false; } - break; - case GDK_BUTTON_PRESS: - changed_=false; - dragging_=false; - if(event->button.button==1 || event->button.button==3) - { - if(editable_) - { - synfig::Time prev_t,next_t; - kf_list_->find_prev_next(t, prev_t, next_t, false); - if( (prev_t==Time::begin() && next_t==Time::end()) - || - ((t-prev_t)>time_ratio && (next_t-t)>time_ratio) - ) - { - switch(event->button.button) - { - case 1: - set_selected_keyframe(selected_none); - selected_=false; - queue_draw(); - break; - case 3: - Gtk::Menu* menu = dynamic_cast(App::ui_manager()->get_widget("/menu-keyframe")); - if(menu) - { - menu->popup(event->button.button,gtk_get_current_event_time()); - } - break; - } - } - else if ((t-prev_t)<(next_t-t)) - { - switch(event->button.button) - { - case 1: - set_selected_keyframe(*(kf_list_->find_prev(t, false))); - queue_draw(); - selected_=true; - break; - case 3: - set_selected_keyframe(*(kf_list_->find_prev(t, false))); - queue_draw(); - selected_=true; - - Gtk::Menu* menu = dynamic_cast(App::ui_manager()->get_widget("/menu-keyframe")); - if(menu) - { - menu->popup(event->button.button,gtk_get_current_event_time()); - } - break; - } - } - else - { - switch(event->button.button) - { - case 1: - set_selected_keyframe(*(kf_list_->find_next(t, false))); - queue_draw(); - selected_=true; - break; - case 3: - set_selected_keyframe(*(kf_list_->find_next(t, false))); - queue_draw(); - selected_=true; - - Gtk::Menu* menu = dynamic_cast(App::ui_manager()->get_widget("/menu-keyframe")); - if(menu) - { - menu->popup(event->button.button,gtk_get_current_event_time()); - } - break; - } - } - return true; - } - else - { - return false; - } + queue_draw(); + return true; + } + case GDK_BUTTON_PRESS: { + changed = false; + dragging = false; + + const Keyframe *kf = NULL; + Time prev_t, next_t; + kf_list->find_prev_next(t, prev_t, next_t, false); + if (t - prev_t < next_t - t) { + if (t - prev_t <= time_ratio) + kf = &*kf_list->find_prev(t, false); + } else { + if (next_t - t <= time_ratio) + kf = &*kf_list->find_next(t, false); } - break; - case GDK_2BUTTON_PRESS: - if(event->button.button==1) - { - if(selected_ && editable_ && canvas_interface_) - { - canvas_interface_->signal_keyframe_properties()(); - } + switch(event->button.button) { + case 1: + if (kf) set_selected_keyframe(*kf); else reset_selected_keyframe(); + break; + case 3: + if (kf) set_selected_keyframe(*kf); + if (Gtk::Menu* menu = dynamic_cast(App::ui_manager()->get_widget("/menu-keyframe"))) + menu->popup(event->button.button,gtk_get_current_event_time()); + break; + default: + return false; + } + + queue_draw(); + return true; + } + case GDK_2BUTTON_PRESS: { + if (event->button.button == 1) { + if (selected && canvas_interface) + canvas_interface->signal_keyframe_properties()(); + return true; } break; - case GDK_BUTTON_RELEASE: - if(editable_ && (event->button.button==1 /*|| event->button.button==3*/)) - { - // stick to integer frames. - if(fps) t = floor(t*fps + 0.5)/fps; - bool stat=false; - if(dragging_) - { - //if (event->button.button==3) - if(event->button.state & GDK_MOD1_MASK) - { - stat=perform_move_kf(true); - } - else - { - stat=perform_move_kf(false); - } - moving_tooltip_->hide(); - } - dragging_=false; - return stat; + } + case GDK_BUTTON_RELEASE: { + if (event->button.button == 1 && dragging) { + moving_tooltip.hide(); + perform_move_kf((bool)(event->button.state & GDK_MOD1_MASK)); + dragging = false; } + if (event->button.button == 1 || event->button.button == 3) + return true; // we captured press of buttons 1 and 3, so capture release too break; + } default: break; } + return false; } -void Widget_Keyframe_List::set_time_adjustment(const Glib::RefPtr &x) +void Widget_Keyframe_List::set_time_model(const etl::handle &x) { - //disconnect old connections - time_value_change.disconnect(); - time_other_change.disconnect(); - - //connect update function to new adjustment - adj_timescale = x; - - if(x) - { - time_value_change = x->signal_value_changed().connect(sigc::mem_fun(*this,&Widget_Keyframe_List::queue_draw)); - time_other_change = x->signal_changed().connect(sigc::mem_fun(*this,&Widget_Keyframe_List::queue_draw)); - } + if (time_model == x) return; + time_model_change.disconnect(); + time_model = x; + if (time_model) + time_model_change = x->signal_visible_changed().connect( + sigc::mem_fun(*this, &Widget_Keyframe_List::queue_draw) ); } void -Widget_Keyframe_List::set_fps(float d) +Widget_Keyframe_List::set_canvas_interface(const etl::loose_handle &x) { - if(fps != d) - { - fps = d; - //update everything since we need to redraw already - queue_draw(); - } -} + if (canvas_interface == x) return; -void -Widget_Keyframe_List::set_canvas_interface(etl::loose_handle h) -{ - canvas_interface_=h; - // Store the values used from the canvas interface. - if (canvas_interface_) - { - set_fps(canvas_interface_->get_canvas()->rend_desc().get_frame_rate()); - set_kf_list(&canvas_interface_->get_canvas()->keyframe_list()); - canvas_interface_->signal_keyframe_added().connect( + keyframe_added.disconnect(); + keyframe_changed.disconnect(); + keyframe_removed.disconnect(); + keyframe_selected.disconnect(); + + canvas_interface = x; + set_kf_list(canvas_interface ? &canvas_interface->get_canvas()->keyframe_list() : NULL); + + if (canvas_interface) { + keyframe_added = canvas_interface->signal_keyframe_added().connect( sigc::hide_return( sigc::hide( - sigc::mem_fun(*this,&studio::Widget_Keyframe_List::queue_draw) - ) - ) - ); - canvas_interface_->signal_keyframe_changed().connect( + sigc::mem_fun(*this,&Widget_Keyframe_List::queue_draw) ))); + keyframe_changed = canvas_interface->signal_keyframe_changed().connect( sigc::hide_return( sigc::hide( - sigc::mem_fun(*this,&studio::Widget_Keyframe_List::queue_draw) - ) - ) - ); - canvas_interface_->signal_keyframe_removed().connect( + sigc::mem_fun(*this,&Widget_Keyframe_List::queue_draw) ))); + keyframe_removed = canvas_interface->signal_keyframe_removed().connect( sigc::hide_return( sigc::hide( - sigc::mem_fun(*this,&studio::Widget_Keyframe_List::queue_draw) - ) - ) - ); - canvas_interface_->signal_keyframe_selected().connect( - sigc::mem_fun(*this,&studio::Widget_Keyframe_List::on_keyframe_selected) - ); + sigc::mem_fun(*this,&Widget_Keyframe_List::queue_draw) ))); + keyframe_selected = canvas_interface->signal_keyframe_selected().connect( + sigc::mem_fun(*this,&Widget_Keyframe_List::on_keyframe_selected) ); } } diff --git a/synfig-studio/src/gui/widgets/widget_keyframe_list.h b/synfig-studio/src/gui/widgets/widget_keyframe_list.h index ebdc568..de0d3df 100644 --- a/synfig-studio/src/gui/widgets/widget_keyframe_list.h +++ b/synfig-studio/src/gui/widgets/widget_keyframe_list.h @@ -7,6 +7,7 @@ ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley ** Copyright (c) 2009 Carlos López +** ......... ... 2018 Ivan Mahonin ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as @@ -28,14 +29,17 @@ /* === H E A D E R S ======================================================= */ +#include + #include -#include #include #include + #include -#include -#include +#include + +#include /* === M A C R O S ========================================================= */ @@ -47,83 +51,77 @@ namespace studio { class Widget_Keyframe_List : public Gtk::DrawingArea { - //! The canvas interface being watched - etl::loose_handle canvas_interface_; - - //! Time adjustment window - Glib::RefPtr adj_default; - Glib::RefPtr adj_timescale; + //! The list of keyframes to be drawn on the widget and moved with mouse + synfig::KeyframeList* kf_list; - //!The list of keyframes to be drawn on the widget and moved with mouse - synfig::KeyframeList default_kf_list_; - mutable synfig::KeyframeList* kf_list_; + //! The canvas interface being watched + etl::loose_handle canvas_interface; - //! The frames per second of the canvas - float fps; + //! Time model + etl::handle time_model; - //! Time radius to click a keyframe - synfig::Time time_ratio; + //! True if it is editable. Keyframes can be moved. + bool editable; - //!True if it is editable. Keyframes can be moved. - bool editable_; + //! True if a keyframe is being dragged. + bool dragging; - //!True if a keyframe is being dragged. - bool dragging_; + //! True if a keyframe has been moved + bool changed; - //!True if a keyframe has been moved - bool changed_; + synfig::Time time_ratio; - //!Holds the selected keyframe of the keyframe list + //! Holds the selected keyframe of the keyframe list synfig::Keyframe selected_kf; - synfig::Keyframe selected_none; - bool selected_; + bool selected; - //!The time of the selected keyframe + //! The time of the selected keyframe synfig::Time selected_kf_time; - //!The time of the selected keyframe during draging + //! The time of the selected keyframe during draging synfig::Time dragging_kf_time; - //!Connectors for handling the signals of the time adjustment - sigc::connection time_value_change; - sigc::connection time_other_change; + //! The Moving handmade tooltip window + Gtk::Window moving_tooltip; + //! The Moving handmade tooltip label + Gtk::Label moving_tooltip_label; + //! The Moving handmade tooltip y fixed coordinate + int moving_tooltip_y; -public: + //! Connectors for handling the signal of the time model + sigc::connection time_model_change; - //!Default constructor - Widget_Keyframe_List(); + //! Connectors for handling the signal of the time model + sigc::connection keyframe_added; + sigc::connection keyframe_changed; + sigc::connection keyframe_removed; + sigc::connection keyframe_selected; - //!Destructror +public: + Widget_Keyframe_List(); ~Widget_Keyframe_List(); //!Loads a new keyframe list on the widget. - void set_kf_list(synfig::KeyframeList* x); + void set_kf_list(synfig::KeyframeList *x); + synfig::KeyframeList* get_kf_list() const { return kf_list; } - //!Member for private data. - synfig::KeyframeList* get_kf_list()const { return kf_list_; } + //! Set the canvas interface, it's the place where signals are connected + //! This function also replaces the keyframe list (see: set_fk_list()) + void set_canvas_interface(const etl::loose_handle &x); + const etl::loose_handle& get_canvas_interface() const { return canvas_interface; } - //!Member for private data - void set_editable(bool x=true) { editable_=x; } + //! Set the time model and proper connects its change signals + void set_time_model(const etl::handle &x); + const etl::handle& get_time_model() const { return time_model; } - //!Member for private data - bool get_editable()const { return editable_; } + void set_editable(bool x = true) { editable = x; } + bool get_editable() const { return editable; } //!Store the selected keyframe value and fired keyframe selected signal + void reset_selected_keyframe(); void set_selected_keyframe(const synfig::Keyframe &x); - - //!Returns the selected keyframe - // \return The selected keyframe - const synfig::Keyframe& get_selected_keyframe() { return selected_kf; } - - //! Set the time adjustment and proper connects its change signals - void set_time_adjustment(const Glib::RefPtr &x); - - //! Affect the global frames per second - // \param x[in] Value for the frames per second - void set_fps(float x); - - //! Set the canvas interface, it's the place where signals are connected - void set_canvas_interface(etl::loose_handle h); + bool is_keyframe_selected() const { return selected; } + const synfig::Keyframe& get_selected_keyframe() const { return selected_kf; } //! Performs the keyframe movement. Returns true if it was sucessful //! \param[in] delta If false permorm normal move. If true perform delta movement. @@ -137,31 +135,10 @@ public: bool fill, const synfig::Color &color ); - -/* ======================= EVENTS HANDLERS ===========================*/ + // Events handlers bool on_draw(const Cairo::RefPtr &cr); - - //! Gtk Widget main loop event, catch the Mouse events. bool on_event(GdkEvent *event); - - //! Signal handler for the selected keyframe from the canvas interface - // \param[in] keyframe The selected keyframe - // \param[in] emitter The widget who emit the signal - void on_keyframe_selected(synfig::Keyframe keyframe, void* emitter); - - /* - -- ** -- P R I V A T E D A T A --------------------------------------------- - */ - -private: - - //! The Moving handmade tooltip window - Gtk::Window *moving_tooltip_; - //! The Moving handmade tooltip label - Gtk::Label *moving_tooltip_label_; - //! The Moving handmade tooltip y fixed coordinate - int moving_tooltip_y_; - + void on_keyframe_selected(synfig::Keyframe keyframe); }; // END of class Keyframe_List }; // END of namespace studio diff --git a/synfig-studio/src/synfigapp/canvasinterface.h b/synfig-studio/src/synfigapp/canvasinterface.h index 85f2de8..afbaa37 100644 --- a/synfig-studio/src/synfigapp/canvasinterface.h +++ b/synfig-studio/src/synfigapp/canvasinterface.h @@ -92,7 +92,7 @@ private: sigc::signal signal_keyframe_added_; sigc::signal signal_keyframe_removed_; sigc::signal signal_keyframe_changed_; - sigc::signal signal_keyframe_selected_; + sigc::signal signal_keyframe_selected_; sigc::signal signal_keyframe_properties_; sigc::signal signal_id_changed_; @@ -189,7 +189,7 @@ public: // Signal Interface sigc::signal& signal_keyframe_changed() { return signal_keyframe_changed_; } //! Signal called when a keyframe is selected /*! Second parameter (void*) hold 'this*' of the signal emiter class (to prevent endless loop)*/ - sigc::signal& signal_keyframe_selected() { return signal_keyframe_selected_; } + sigc::signal& signal_keyframe_selected() { return signal_keyframe_selected_; } //! Signal called when the properties dialog of the selected keyframe must be shown sigc::signal& signal_keyframe_properties() { return signal_keyframe_properties_; }