make Selection::set (TrackViewList*) more efficient and emit less PI::Change signals
[ardour.git] / gtk2_ardour / selection.cc
index 27a062e87dd57facf79912d42e79cab3c5241232..ab26bfd48ab484a99e2c1f6cc63ab8aaa90e3a07 100644 (file)
@@ -40,6 +40,7 @@
 #include "automation_time_axis.h"
 #include "public_editor.h"
 #include "control_point.h"
+#include "vca_time_axis.h"
 
 #include "pbd/i18n.h"
 
@@ -274,6 +275,9 @@ Selection::toggle (const TrackViewList& track_list)
        PresentationInfo::ChangeSuspender cs;
 
        for (TrackViewList::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
+               if (dynamic_cast<VCATimeAxisView*> (*i)) {
+                       continue;
+               }
                toggle ((*i));
        }
 }
@@ -281,6 +285,10 @@ Selection::toggle (const TrackViewList& track_list)
 void
 Selection::toggle (TimeAxisView* track)
 {
+       if (dynamic_cast<VCATimeAxisView*> (track)) {
+               return;
+       }
+
        TrackSelection::iterator i;
 
        if ((i = find (tracks.begin(), tracks.end(), track)) == tracks.end()) {
@@ -437,6 +445,9 @@ Selection::add (TrackViewList const & track_list)
 
        if (!added.empty()) {
                for (TrackViewList::iterator x = added.begin(); x != added.end(); ++x) {
+                       if (dynamic_cast<VCATimeAxisView*> (*x)) {
+                               continue;
+                       }
                        (*x)->set_selected (true);
                }
        }
@@ -445,10 +456,11 @@ Selection::add (TrackViewList const & track_list)
 void
 Selection::add (TimeAxisView* track)
 {
-       clear_objects();  //enforce object/range exclusivity
+       if (dynamic_cast<VCATimeAxisView*> (track)) {
+               return;
+       }
 
        TrackViewList tr;
-       track->set_selected (true);
        tr.push_back (track);
        add (tr);
 }
@@ -634,20 +646,29 @@ Selection::remove (TimeAxisView* track)
 {
        list<TimeAxisView*>::iterator i;
        if ((i = find (tracks.begin(), tracks.end(), track)) != tracks.end()) {
-               track->set_selected (false);
+               /* erase first, because set_selected() will remove the track
+                  from the selection, invalidating the iterator.
+
+                  In fact, we don't really even need to do the erase, but this is
+                  a hangover of axis view selection being in the GUI.
+               */
                tracks.erase (i);
+               track->set_selected (false);
        }
 }
 
 void
 Selection::remove (const TrackViewList& track_list)
 {
+       PresentationInfo::ChangeSuspender cs;
+
        for (TrackViewList::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
 
                TrackViewList::iterator x = find (tracks.begin(), tracks.end(), *i);
+
                if (x != tracks.end()) {
-                       (*i)->set_selected (false);
                        tracks.erase (x);
+                       (*i)->set_selected (false);
                }
        }
 }
@@ -780,6 +801,9 @@ Selection::remove (boost::shared_ptr<ARDOUR::AutomationList> ac)
 void
 Selection::set (TimeAxisView* track)
 {
+       if (dynamic_cast<VCATimeAxisView*> (track)) {
+               return;
+       }
        clear_objects ();  //enforce object/range exclusivity
 
        PresentationInfo::ChangeSuspender cs;
@@ -806,40 +830,29 @@ Selection::set (const TrackViewList& track_list)
 {
        clear_objects();  //enforce object/range exclusivity
 
-       PresentationInfo::ChangeSuspender cs;
-
-       if (!tracks.empty()) {
 
-               /* cannot use set<T>::operator== (set<T> const &) here, because
-                * apparently the ordering used within 2 sets is not
-                * necessarily the same.
-                */
+       TrackViewList to_be_added;
+       TrackViewList to_be_removed;
 
-               if (tracks.size() == track_list.size()) {
-                       bool missing = false;
-
-                       for (TrackViewList::const_iterator x = track_list.begin(); x != track_list.end(); ++x) {
-                               if (find (tracks.begin(), tracks.end(), *x) == tracks.end()) {
-                                       missing = true;
-                               }
-                       }
-
-                       if (!missing) {
-                               /* already same selection: nothing to do */
-                               return;
-                       }
+       for (TrackViewList::const_iterator x = tracks.begin(); x != tracks.end(); ++x) {
+               if (find (track_list.begin(), track_list.end(), *x) == track_list.end()) {
+                       to_be_removed.push_back (*x);
                }
+       }
 
-               /* argument is different from existing selection */
-
-               for (TrackViewList::iterator x = tracks.begin(); x != tracks.end(); ++x) {
-                       (*x)->set_selected (false);
+       for (TrackViewList::const_iterator x = track_list.begin(); x != track_list.end(); ++x) {
+               if (dynamic_cast<VCATimeAxisView*> (*x)) {
+                       continue;
+               }
+               if (find (tracks.begin(), tracks.end(), *x) == tracks.end()) {
+                       to_be_added.push_back (*x);
                }
-
-               tracks.clear ();
        }
 
-       add (track_list);
+       PresentationInfo::ChangeSuspender cs;
+       remove (to_be_removed);
+       add (to_be_added);
+
 }
 
 void
@@ -979,25 +992,25 @@ Selection::set (boost::shared_ptr<Evoral::ControlList> ac)
 }
 
 bool
-Selection::selected (ArdourMarker* m)
+Selection::selected (ArdourMarker* m) const
 {
        return find (markers.begin(), markers.end(), m) != markers.end();
 }
 
 bool
-Selection::selected (TimeAxisView* tv)
+Selection::selected (TimeAxisView* tv) const
 {
        return tv->selected ();
 }
 
 bool
-Selection::selected (RegionView* rv)
+Selection::selected (RegionView* rv) const
 {
        return find (regions.begin(), regions.end(), rv) != regions.end();
 }
 
 bool
-Selection::selected (ControlPoint* cp)
+Selection::selected (ControlPoint* cp) const
 {
        return find (points.begin(), points.end(), cp) != points.end();
 }