Add API allowing plugin preset load to affect automation
[ardour.git] / gtk2_ardour / editor_routes.cc
index cec0969863107a9ed36c3e8c481500a1e2a78f9e..b1618bde49b12892daad4d100434d04bfc7f3c4b 100644 (file)
@@ -1167,8 +1167,10 @@ EditorRoutes::sync_treeview_from_presentation_info (PropertyChange const & what_
                         * The rows (stripables) are not actually removed from the model,
                         * but only from the display in the DnDTreeView.
                         * ->reorder() will fail to find the row_path.
-                        * (re-order drag -> remove row -> rync PI from TV -> notify -> sync TV from PI -> crash)
+                        * (re-order drag -> remove row -> sync PI from TV -> notify -> sync TV from PI -> crash)
                         */
+                       Unwinder<bool> uw2 (_ignore_selection_change, true);
+
                        _display.unset_model();
                        _model->reorder (neworder);
                        _display.set_model (_model);
@@ -1195,7 +1197,6 @@ EditorRoutes::sync_treeview_from_presentation_info (PropertyChange const & what_
                }
 
                /* step two: set the Selection (for stripables/routes) */
-
                _editor->get_selection().set (tvl);
        }
 
@@ -1581,13 +1582,15 @@ struct PresentationInfoVCASorter
 void
 EditorRoutes::initial_display ()
 {
-       DisplaySuspender ds;
-       _model->clear ();
 
        if (!_session) {
+               _model->clear ();
                return;
        }
 
+       DisplaySuspender ds;
+       _model->clear ();
+
        StripableList s;
 
        RouteList r (*_session->get_routes());
@@ -1622,146 +1625,116 @@ EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& contex
 struct ViewStripable {
        TimeAxisView* tav;
        boost::shared_ptr<Stripable> stripable;
-       uint32_t old_order;
 
-       ViewStripable (TimeAxisView* t, boost::shared_ptr<Stripable> s, uint32_t n)
-               : tav (t), stripable (s), old_order (n) {}
+       ViewStripable (TimeAxisView* t, boost::shared_ptr<Stripable> s)
+               : tav (t), stripable (s) {}
 };
 
 void
 EditorRoutes::move_selected_tracks (bool up)
 {
-       if (_editor->selection->tracks.empty()) {
+       TimeAxisView* scroll_to = 0;
+       StripableList sl;
+       _session->get_stripables (sl);
+
+       if (sl.size() < 2) {
+               /* nope */
                return;
        }
 
+       sl.sort (Stripable::PresentationOrderSorter());
+
        std::list<ViewStripable> view_stripables;
-       std::vector<int> neworder;
-       TreeModel::Children rows = _model->children();
-       TreeModel::Children::iterator ri;
-       TreeModel::Children::size_type n;
 
-       for (n = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++n) {
-               TimeAxisView* tv = (*ri)[_columns.tv];
-               boost::shared_ptr<Stripable> stripable = (*ri)[_columns.stripable];
-               view_stripables.push_back (ViewStripable (tv, stripable, n));
+       /* build a list that includes time axis view information */
+
+       for (StripableList::const_iterator sli = sl.begin(); sli != sl.end(); ++sli) {
+               TimeAxisView* tv = _editor->axis_view_from_stripable (*sli);
+               view_stripables.push_back (ViewStripable (tv, *sli));
        }
 
-       list<ViewStripable>::iterator trailing;
-       list<ViewStripable>::iterator leading;
+       /* for each selected stripable, move it above or below the adjacent
+        * stripable that has a time-axis view representation here. If there's
+        * no such representation, then
+        */
 
-       TimeAxisView* scroll_to = NULL;
+       list<ViewStripable>::iterator unselected_neighbour;
+       list<ViewStripable>::iterator vsi;
 
-       if (up) {
+       {
+               PresentationInfo::ChangeSuspender cs;
 
-               trailing = view_stripables.begin();
-               leading = view_stripables.begin();
+               if (up) {
+                       unselected_neighbour = view_stripables.end ();
+                       vsi = view_stripables.begin();
 
-               ++leading;
+                       while (vsi != view_stripables.end()) {
 
-               while (leading != view_stripables.end()) {
-                       if (_editor->selection->selected (leading->tav)) {
-                               view_stripables.insert (trailing, ViewStripable (*leading));
-                               if (!scroll_to) {
-                                       scroll_to = leading->tav;
-                               }
-                               leading = view_stripables.erase (leading);
-                       } else {
-                               ++leading;
-                               ++trailing;
-                       }
-               }
+                               if (vsi->stripable->presentation_info().selected()) {
 
-       } else {
+                                       if (unselected_neighbour != view_stripables.end()) {
 
-               /* if we could use reverse_iterator in list::insert, this code
-                  would be a beautiful reflection of the code above. but we can't
-                  and so it looks like a bit of a mess.
-               */
+                                               PresentationInfo::order_t unselected_neighbour_order = unselected_neighbour->stripable->presentation_info().order();
+                                               PresentationInfo::order_t my_order = vsi->stripable->presentation_info().order();
 
-               trailing = view_stripables.end();
-               leading = view_stripables.end();
+                                               unselected_neighbour->stripable->set_presentation_order (my_order);
+                                               vsi->stripable->set_presentation_order (unselected_neighbour_order);
 
-               --leading; if (leading == view_stripables.begin()) { return; }
-               --leading;
-               --trailing;
+                                               if (!scroll_to) {
+                                                       scroll_to = vsi->tav;
+                                               }
+                                       }
 
-               while (1) {
+                               } else {
+
+                                       if (vsi->tav) {
+                                               unselected_neighbour = vsi;
+                                       }
 
-                       if (_editor->selection->selected (leading->tav)) {
-                               if (!scroll_to) {
-                                       scroll_to = leading->tav;
                                }
-                               list<ViewStripable>::iterator tmp;
 
-                               /* need to insert *after* trailing, not *before* it,
-                                  which is what insert (iter, val) normally does.
-                               */
+                               ++vsi;
+                       }
 
-                               tmp = trailing;
-                               tmp++;
+               } else {
 
-                               view_stripables.insert (tmp, ViewStripable (*leading));
+                       unselected_neighbour = view_stripables.end();
+                       vsi = unselected_neighbour;
 
-                               /* can't use iter = cont.erase (iter); form here, because
-                                  we need iter to move backwards.
-                               */
+                       do {
 
-                               tmp = leading;
-                               --tmp;
+                               --vsi;
 
-                               bool done = false;
+                               if (vsi->stripable->presentation_info().selected()) {
 
-                               if (leading == view_stripables.begin()) {
-                                       /* the one we've just inserted somewhere else
-                                          was the first in the list. erase this copy,
-                                          and then break, because we're done.
-                                       */
-                                       done = true;
-                               }
+                                       if (unselected_neighbour != view_stripables.end()) {
 
-                               view_stripables.erase (leading);
+                                               PresentationInfo::order_t unselected_neighbour_order = unselected_neighbour->stripable->presentation_info().order();
+                                               PresentationInfo::order_t my_order = vsi->stripable->presentation_info().order();
 
-                               if (done) {
-                                       break;
-                               }
+                                               unselected_neighbour->stripable->set_presentation_order (my_order);
+                                               vsi->stripable->set_presentation_order (unselected_neighbour_order);
 
-                               leading = tmp;
+                                               if (!scroll_to) {
+                                                       scroll_to = vsi->tav;
+                                               }
+                                       }
+
+                               } else {
+
+                                       if (vsi->tav) {
+                                               unselected_neighbour = vsi;
+                                       }
 
-                       } else {
-                               if (leading == view_stripables.begin()) {
-                                       break;
                                }
-                               --leading;
-                               --trailing;
-                       }
-               };
-       }
 
-       for (leading = view_stripables.begin(); leading != view_stripables.end(); ++leading) {
-               neworder.push_back (leading->old_order);
-#ifndef NDEBUG
-               if (leading->old_order != neworder.size() - 1) {
-                       DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("move %1 to %2\n", leading->old_order, neworder.size() - 1));
+                       } while (vsi != view_stripables.begin());
                }
-#endif
        }
 
-#ifndef NDEBUG
-       DEBUG_TRACE (DEBUG::OrderKeys, "New order after moving tracks:\n");
-       for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
-               DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("\t%1\n", *i));
-       }
-       DEBUG_TRACE (DEBUG::OrderKeys, "-------\n");
-#endif
-
-
-       _model->reorder (neworder);
-
        if (scroll_to) {
                _editor->ensure_time_axis_view_is_visible (*scroll_to, false);
        }
-
 }
 
 void