From 6874bca886ad9778a7bedd78a25d56f0bd277cf3 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 19 Mar 2015 20:32:59 +0100 Subject: vertical scroll stop on automation lanes --- gtk2_ardour/editor.h | 4 +- gtk2_ardour/editor_ops.cc | 120 +++++++++++++++++++++++++++++++++++++++----- gtk2_ardour/public_editor.h | 4 +- 3 files changed, 112 insertions(+), 16 deletions(-) diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index e7f1cd2807..2e2593dbf1 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -363,8 +363,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void scroll_tracks_down_line (); void scroll_tracks_up_line (); - bool scroll_up_one_track (); - bool scroll_down_one_track (); + bool scroll_up_one_track (bool skip_child_views = false); + bool scroll_down_one_track (bool skip_child_views = false); void prepare_for_cleanup (); void finish_cleanup (); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 2683020cbf..266a6b585e 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -1411,10 +1411,9 @@ Editor::scroll_tracks_up_line () } bool -Editor::scroll_down_one_track () +Editor::scroll_down_one_track (bool skip_child_views) { TrackViewList::reverse_iterator next = track_views.rend(); - std::pair res; const double top_of_trackviews = vertical_adjustment.get_value(); for (TrackViewList::reverse_iterator t = track_views.rbegin(); t != track_views.rend(); ++t) { @@ -1422,14 +1421,51 @@ Editor::scroll_down_one_track () continue; } - /* If this is the upper-most visible trackview, we want to display - the one above it (next) - */ - - res = (*t)->covers_y_position (top_of_trackviews); + * the one above it (next) + * + * Note that covers_y_position() is recursive and includes child views + */ + std::pair res = (*t)->covers_y_position (top_of_trackviews); if (res.first) { + if (skip_child_views) { + break; + } + /* automation lane (one level, non-recursive) + * + * - if no automation lane exists -> move to next tack + * - if the first (here: bottom-most) matches -> move to next tack + * - if no y-axis match is found -> the current track is at the top + * -> move to last (here: top-most) automation lane + */ + TimeAxisView::Children kids = (*t)->get_child_list(); + TimeAxisView::Children::reverse_iterator nkid = kids.rend(); + + for (TimeAxisView::Children::reverse_iterator ci = kids.rbegin(); ci != kids.rend(); ++ci) { + if ((*ci)->hidden()) { + continue; + } + + std::pair dev; + dev = (*ci)->covers_y_position (top_of_trackviews); + if (dev.first) { + /* some automation lane is currently at the top */ + if (ci == kids.rbegin()) { + /* first (bottom-most) autmation lane is at the top. + * -> move to next track + */ + nkid = kids.rend(); + } + break; + } + nkid = ci; + } + + if (nkid != kids.rend()) { + ensure_time_axis_view_is_visible (**nkid, true); + return true; + } break; } next = t; @@ -1446,10 +1482,9 @@ Editor::scroll_down_one_track () } bool -Editor::scroll_up_one_track () +Editor::scroll_up_one_track (bool skip_child_views) { TrackViewList::iterator prev = track_views.end(); - std::pair res; double top_of_trackviews = vertical_adjustment.get_value (); for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) { @@ -1458,10 +1493,55 @@ Editor::scroll_up_one_track () continue; } - /* find the trackview at the top of the trackview group */ - res = (*t)->covers_y_position (top_of_trackviews); + /* find the trackview at the top of the trackview group + * + * Note that covers_y_position() is recursive and includes child views + */ + std::pair res = (*t)->covers_y_position (top_of_trackviews); if (res.first) { + if (skip_child_views) { + break; + } + /* automation lane (one level, non-recursive) + * + * - if no automation lane exists -> move to prev tack + * - if no y-axis match is found -> the current track is at the top -> move to prev track + * (actually last automation lane of previous track, see below) + * - if first (top-most) lane is at the top -> move to this track + * - else move up one lane + */ + TimeAxisView::Children kids = (*t)->get_child_list(); + TimeAxisView::Children::iterator pkid = kids.end(); + + for (TimeAxisView::Children::iterator ci = kids.begin(); ci != kids.end(); ++ci) { + if ((*ci)->hidden()) { + continue; + } + + std::pair dev; + dev = (*ci)->covers_y_position (top_of_trackviews); + if (dev.first) { + /* some automation lane is currently at the top */ + if (ci == kids.begin()) { + /* first (top-most) autmation lane is at the top. + * jump directly to this track's top + */ + ensure_time_axis_view_is_visible (**t, true); + return true; + } + else if (pkid != kids.end()) { + /* some other automation lane is at the top. + * move up to prev automation lane. + */ + ensure_time_axis_view_is_visible (**pkid, true); + return true; + } + assert(0); // not reached + break; + } + pkid = ci; + } break; } @@ -1469,7 +1549,23 @@ Editor::scroll_up_one_track () } if (prev != track_views.end()) { - ensure_time_axis_view_is_visible (**prev, true); + // move to bottom-most automation-lane of the previous track + TimeAxisView::Children kids = (*prev)->get_child_list(); + TimeAxisView::Children::reverse_iterator pkid = kids.rend(); + if (!skip_child_views) { + // find the last visible lane + for (TimeAxisView::Children::reverse_iterator ci = kids.rbegin(); ci != kids.rend(); ++ci) { + if (!(*ci)->hidden()) { + pkid = ci; + break; + } + } + } + if (pkid != kids.rend()) { + ensure_time_axis_view_is_visible (**pkid, true); + } else { + ensure_time_axis_view_is_visible (**prev, true); + } return true; } diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 42758e156f..a16ae9f05c 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -269,8 +269,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi virtual void override_visible_track_count () = 0; virtual void scroll_tracks_down_line () = 0; virtual void scroll_tracks_up_line () = 0; - virtual bool scroll_down_one_track () = 0; - virtual bool scroll_up_one_track () = 0; + virtual bool scroll_down_one_track (bool skip_child_views = false) = 0; + virtual bool scroll_up_one_track (bool skip_child_views = false) = 0; virtual void prepare_for_cleanup () = 0; virtual void finish_cleanup () = 0; virtual void reset_x_origin (framepos_t frame) = 0; -- cgit v1.2.3