Add test for #3356.
[ardour.git] / gtk2_ardour / location_ui.cc
index eebec3556eff01f2cd347d3b23303ae571a72ab2..fda29be193a336d4ecd87b44b589c32d12765313 100644 (file)
@@ -21,7 +21,6 @@
 #include <cstdlib>
 
 #include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/stop_signal.h>
 
 #include "ardour/utils.h"
 #include "ardour/configuration.h"
@@ -226,7 +225,7 @@ LocationEditRow::set_location (Location *loc)
                        item_table.attach (remove_button, 6, 7, 0, 1, FILL, FILL, 4, 0);
                }
 
-               if (location->is_end() || location->is_start()) {
+               if (location->is_session_range()) {
                        remove_button.set_sensitive (false);
                }
 
@@ -453,9 +452,11 @@ LocationEditRow::hide_toggled ()
 void
 LocationEditRow::remove_button_pressed ()
 {
-       if (!location) return;
+       if (!location) {
+               return;
+       }
 
-       remove_requested(location); /*  EMIT_SIGNAL */
+       remove_requested (location); /* EMIT_SIGNAL */
 }
 
 
@@ -671,7 +672,7 @@ LocationUI::do_location_remove (ARDOUR::Location *loc)
           cannot be removed.
        */
 
-       if (loc->is_end()) {
+       if (loc->is_session_range()) {
                return FALSE;
        }
 
@@ -702,6 +703,12 @@ LocationUI::location_redraw_ranges ()
        range_rows.show();
 }
 
+struct LocationSortByStart {
+    bool operator() (Location *a, Location *b) {
+           return a->start() < b->start();
+    }
+};
+
 void
 LocationUI::location_added (Location* location)
 {
@@ -709,12 +716,41 @@ LocationUI::location_added (Location* location)
 
        if (location->is_auto_punch()) {
                punch_edit_row.set_location(location);
-       }
-       else if (location->is_auto_loop()) {
+       } else if (location->is_auto_loop()) {
                loop_edit_row.set_location(location);
-       }
-       else {
-               refresh_location_list ();
+       } else if (location->is_range_marker() || location->is_mark()) {
+               Locations::LocationList loc = _session->locations()->list ();
+               loc.sort (LocationSortByStart ());
+
+               LocationEditRow* erow = manage (new LocationEditRow (_session, location));
+               erow->remove_requested.connect (sigc::mem_fun (*this, &LocationUI::location_remove_requested));
+               Box_Helpers::BoxList & children = location->is_range_marker() ? range_rows.children () : location_rows.children ();
+
+               /* Step through the location list and the GUI list to find the place to insert */
+               Locations::LocationList::iterator i = loc.begin ();
+               Box_Helpers::BoxList::iterator j = children.begin ();
+               while (i != loc.end()) {
+
+                       if (location->flags() != (*i)->flags()) {
+                               /* Skip locations in the session list that aren't of the right type */
+                               ++i;
+                               continue;
+                       }
+
+                       if (*i == location) {
+                               children.insert (j, Box_Helpers::Element (*erow, PACK_SHRINK, 1, PACK_START));
+                               break;
+                       }
+
+                       ++i;
+                       
+                       if (j != children.end()) {
+                               ++j;
+                       }
+               }
+
+               range_rows.show_all ();
+               location_rows.show_all ();
        }
 }
 
@@ -725,26 +761,24 @@ LocationUI::location_removed (Location* location)
 
        if (location->is_auto_punch()) {
                punch_edit_row.set_location(0);
-       }
-       else if (location->is_auto_loop()) {
+       } else if (location->is_auto_loop()) {
                loop_edit_row.set_location(0);
-       }
-       else {
-               refresh_location_list ();
+       } else if (location->is_range_marker() || location->is_mark()) {
+               Box_Helpers::BoxList& children = location->is_range_marker() ? range_rows.children () : location_rows.children ();
+               for (Box_Helpers::BoxList::iterator i = children.begin(); i != children.end(); ++i) {
+                       LocationEditRow* r = dynamic_cast<LocationEditRow*> (i->get_widget());
+                       if (r && r->get_location() == location) {
+                               children.erase (i);
+                               break;
+                       }
+               }
        }
 }
 
-struct LocationSortByStart {
-    bool operator() (Location *a, Location *b) {
-           return a->start() < b->start();
-    }
-};
-
 void
 LocationUI::map_locations (Locations::LocationList& locations)
 {
        Locations::LocationList::iterator i;
-       Location* location;
        gint n;
        int mark_n = 0;
        Locations::LocationList temp = locations;
@@ -753,38 +787,32 @@ LocationUI::map_locations (Locations::LocationList& locations)
        temp.sort (cmp);
        locations = temp;
 
-       Box_Helpers::BoxList & loc_children = location_rows.children();
-       Box_Helpers::BoxList & range_children = range_rows.children();
-       LocationEditRow * erow;
-
        for (n = 0, i = locations.begin(); i != locations.end(); ++n, ++i) {
 
-               location = *i;
+               Location* location = *i;
 
                if (location->is_mark()) {
-                       mark_n++;
-                       erow = manage (new LocationEditRow(_session, location, mark_n));
+                       LocationEditRow* erow = manage (new LocationEditRow (_session, location, mark_n));
                        erow->remove_requested.connect (sigc::mem_fun(*this, &LocationUI::location_remove_requested));
-                       erow->redraw_ranges.connect (sigc::mem_fun(*this, &LocationUI::location_redraw_ranges));
+                       erow->redraw_ranges.connect (sigc::mem_fun(*this, &LocationUI::location_redraw_ranges));
+                       Box_Helpers::BoxList & loc_children = location_rows.children();
                        loc_children.push_back(Box_Helpers::Element(*erow, PACK_SHRINK, 1, PACK_START));
                        if (location == newest_location) {
                                newest_location = 0;
                                erow->focus_name();
                        }
-               }
-               else if (location->is_auto_punch()) {
+               } else if (location->is_auto_punch()) {
                        punch_edit_row.set_session (_session);
                        punch_edit_row.set_location (location);
                        punch_edit_row.show_all();
-               }
-               else if (location->is_auto_loop()) {
+               } else if (location->is_auto_loop()) {
                        loop_edit_row.set_session (_session);
                        loop_edit_row.set_location (location);
                        loop_edit_row.show_all();
-               }
-               else {
-                       erow = manage (new LocationEditRow(_session, location));
+               } else {
+                       LocationEditRow* erow = manage (new LocationEditRow(_session, location));
                        erow->remove_requested.connect (sigc::mem_fun(*this, &LocationUI::location_remove_requested));
+                       Box_Helpers::BoxList & range_children = range_rows.children();
                        range_children.push_back(Box_Helpers::Element(*erow,  PACK_SHRINK, 1, PACK_START));
                }
        }
@@ -860,7 +888,7 @@ LocationUI::set_session(ARDOUR::Session* s)
        SessionHandlePtr::set_session (s);
 
        if (_session) {
-               _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&LocationUI::refresh_location_list, this), gui_context());
+               _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&LocationUI::locations_changed, this, _1), gui_context());
                _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&LocationUI::refresh_location_list, this), gui_context());
                _session->locations()->added.connect (_session_connections, invalidator (*this), ui_bind (&LocationUI::location_added, this, _1), gui_context());
                _session->locations()->removed.connect (_session_connections, invalidator (*this), ui_bind (&LocationUI::location_removed, this, _1), gui_context());
@@ -872,6 +900,17 @@ LocationUI::set_session(ARDOUR::Session* s)
        refresh_location_list ();
 }
 
+void
+LocationUI::locations_changed (Locations::Change c)
+{
+       /* removal is signalled by both a removed and a changed signal emission from Locations,
+          so we don't need to refresh the list on a removal
+       */
+       if (c != Locations::REMOVAL) {
+               refresh_location_list ();
+       }
+}
+
 void
 LocationUI::session_going_away()
 {
@@ -896,9 +935,8 @@ LocationUI::session_going_away()
 /*------------------------*/
 
 LocationUIWindow::LocationUIWindow ()
-       : ArdourDialog ("locations dialog")
+       : ArdourDialog (_("Locations"))
 {
-       set_title (_("Locations"));
        set_wmclass(X_("ardour_locations"), "Ardour");
        set_name ("LocationWindow");