From dac2d41ee2bf658e9c7c841ce9459df43a4bd62b Mon Sep 17 00:00:00 2001 From: Tim Mayberry Date: Tue, 9 Feb 2016 20:39:27 +1000 Subject: [PATCH] Add option to zoom using button press in the time rulers and dragging vertically This is a common operation used for zooming in other DAWs like Ableton Live and Cubase. To support such a usage pattern without changing the existing behaviour of the ruler area I've made it an option that is false by default. The behaviour of RulerDragZoom is intentionally different than a CursorDrag that occurs in the rest of the ruler area in that it doesn't follow the snap to grid setting and no locate related stuff occurs until button release. There are some issues with responsiveness with more than a few hundred regions or a large amount of MIDI events/notes. Implements feature #6768 --- gtk2_ardour/editor.h | 1 + gtk2_ardour/editor_canvas_events.cc | 12 +++++++ gtk2_ardour/editor_drag.cc | 53 +++++++++++++++++++++++++++++ gtk2_ardour/editor_drag.h | 16 +++++++++ gtk2_ardour/rc_option_editor.cc | 8 +++++ gtk2_ardour/ui_config_vars.h | 1 + 6 files changed, 91 insertions(+) diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index e93ee2b21e..ccebaa853e 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -2272,6 +2272,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD friend class ControlPointDrag; friend class LineDrag; friend class RubberbandSelectDrag; + friend class RulerZoomDrag; friend class EditorRubberbandSelectDrag; friend class TimeFXDrag; friend class ScrubDrag; diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 30e2504edc..73570339b3 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -1078,6 +1078,18 @@ Editor::canvas_ruler_event (GdkEvent *event, ArdourCanvas::Item* item, ItemType return handled; } + switch (event->type) { + case GDK_BUTTON_PRESS: + if (UIConfiguration::instance ().get_use_time_rulers_to_zoom_with_vertical_drag () && + Keyboard::no_modifier_keys_pressed (&event->button) && event->button.button == 1) { + _drags->set(new RulerZoomDrag(this, item), event); + return true; + } + break; + default: + break; + } + return typed_event (item, event, type); } diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 01b92564ad..a533e3ddd3 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -6447,3 +6447,56 @@ void RegionCutDrag::aborted (bool) { } + +RulerZoomDrag::RulerZoomDrag (Editor* e, ArdourCanvas::Item* item) + : Drag (e, item, true) +{ +} + +void +RulerZoomDrag::start_grab (GdkEvent* event, Gdk::Cursor* c) +{ + Drag::start_grab (event, c); + + framepos_t where = _editor->canvas_event_sample(event); + + _editor->_dragging_playhead = true; + + _editor->playhead_cursor->set_position (where); +} + +void +RulerZoomDrag::motion (GdkEvent* event, bool) +{ + framepos_t where = _editor->canvas_event_sample(event); + + _editor->playhead_cursor->set_position (where); + + const double movement_limit = 20.0; + const double scale = 1.08; + const double y_delta = last_pointer_y() - current_pointer_y(); + + if (y_delta > 0 && y_delta < movement_limit) { + _editor->temporal_zoom_step_mouse_focus_scale (true, scale); + } else if (y_delta < 0 && y_delta > -movement_limit) { + _editor->temporal_zoom_step_mouse_focus_scale (false, scale); + } +} + +void +RulerZoomDrag::finished (GdkEvent*, bool) +{ + _editor->_dragging_playhead = false; + + Session* s = _editor->session (); + if (s) { + s->request_locate (_editor->playhead_cursor->current_frame (), _was_rolling); + _editor->_pending_locate_request = true; + } + +} + +void +RulerZoomDrag::aborted (bool) +{ +} diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 841752c3a1..1c2a910fcf 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -1189,5 +1189,21 @@ class CrossfadeEdgeDrag : public Drag bool start; }; +class RulerZoomDrag : public Drag +{ +public: + RulerZoomDrag (Editor*, ArdourCanvas::Item*); + + void start_grab (GdkEvent*, Gdk::Cursor* c = 0); + void motion (GdkEvent *, bool); + void finished (GdkEvent*, bool); + void aborted (bool); + + virtual bool allow_vertical_autoscroll () const { + return false; + } + +}; + #endif /* __gtk2_ardour_editor_drag_h_ */ diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index 8379a31ddd..0c15c1ee66 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -2536,6 +2536,14 @@ if (!Profile->get_mixbus()) { )); } // !mixbus + add_option (_("Editor"), + new BoolOption ( + "use-time-rulers-to-zoom-with-vertical-drag", + _("Use time rulers area to zoom when clicking and dragging vertically"), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_time_rulers_to_zoom_with_vertical_drag), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_time_rulers_to_zoom_with_vertical_drag) + )); + add_option (_("Editor"), new BoolOption ( "update-editor-during-summary-drag", diff --git a/gtk2_ardour/ui_config_vars.h b/gtk2_ardour/ui_config_vars.h index e6cd3c1ecb..561bd9d72c 100644 --- a/gtk2_ardour/ui_config_vars.h +++ b/gtk2_ardour/ui_config_vars.h @@ -49,6 +49,7 @@ UI_CONFIG_VARIABLE (bool, sound_midi_notes, "sound-midi-notes", false) UI_CONFIG_VARIABLE (bool, show_plugin_scan_window, "show-plugin-scan-window", false) UI_CONFIG_VARIABLE (bool, show_zoom_tools, "show-zoom-tools", true) UI_CONFIG_VARIABLE (bool, use_mouse_position_as_zoom_focus_on_scroll, "use-mouse-position-as-zoom-focus-on-scroll", true) +UI_CONFIG_VARIABLE (bool, use_time_rulers_to_zoom_with_vertical_drag, "use-time-rulers-to-zoom-with-vertical-drag", false) UI_CONFIG_VARIABLE (bool, widget_prelight, "widget-prelight", true) UI_CONFIG_VARIABLE (bool, use_tooltips, "use-tooltips", true) UI_CONFIG_VARIABLE (std::string, mixer_strip_visibility, "mixer-element-visibility", "Input,PhaseInvert,RecMon,SoloIsoLock,Output,Comments")