add icons for cut mouse mode button and cut cursor (both need improving)
[ardour.git] / gtk2_ardour / editor_routes.cc
index 10f2c3f5ed924945d2dd35bf4dc15539da30dbf3..025633b0909af55e7cf73aaf7dcc50ec99ae313a 100644 (file)
@@ -53,6 +53,7 @@
 
 using namespace std;
 using namespace ARDOUR;
+using namespace ARDOUR_UI_UTILS;
 using namespace PBD;
 using namespace Gtk;
 using namespace Gtkmm2ext;
@@ -70,6 +71,7 @@ EditorRoutes::EditorRoutes (Editor* e)
         , _ignore_reorder (false)
         , _no_redisplay (false)
         , _adding_routes (false)
+        , _route_deletion_in_progress (false)
         , _menu (0)
         , old_focus (0)
         , selection_countdown (0)
@@ -222,6 +224,7 @@ EditorRoutes::EditorRoutes (Editor* e)
        _display.set_headers_visible (true);
        _display.get_selection()->set_mode (SELECTION_SINGLE);
        _display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter));
+       _display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::selection_changed));
        _display.set_reorderable (true);
        _display.set_name (X_("EditGroupList"));
        _display.set_rules_hint (true);
@@ -270,7 +273,7 @@ EditorRoutes::EditorRoutes (Editor* e)
        active_col->set_fixed_width (30);
        active_col->set_alignment (ALIGN_CENTER);
        
-       _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::route_deleted));
+       _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::row_deleted));
        _model->signal_rows_reordered().connect (sigc::mem_fun (*this, &EditorRoutes::reordered));
 
        _display.signal_button_press_event().connect (sigc::mem_fun (*this, &EditorRoutes::button_press), false);
@@ -284,7 +287,7 @@ EditorRoutes::EditorRoutes (Editor* e)
 
         _display.set_enable_search (false);
 
-       Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_order_keys, this, _1), gui_context());
+       Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_order_keys, this), gui_context());
 }
 
 bool
@@ -518,7 +521,6 @@ EditorRoutes::redisplay ()
                /* show or hide the TimeAxisView */
                if (visible) {
                        position += tv->show_at (position, n, &_editor->edit_controls_vbox);
-                       // SHOWTRACKS
                } else {
                        tv->hide ();
                }
@@ -546,18 +548,31 @@ EditorRoutes::redisplay ()
 }
 
 void
-EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
+EditorRoutes::row_deleted (Gtk::TreeModel::Path const &)
 {
-       /* this happens as the second step of a DnD within the treeview as well
-          as when a row/route is actually deleted.
+       /* this happens as the second step of a DnD within the treeview, and
+          when a route is actually removed. we don't differentiate between
+          the two cases.
+          
+          note that the sync_orders_keys() step may not actually change any
+          RID's (e.g. the last track may be removed, so all other tracks keep
+          the same RID), which means that no redisplay would happen. so we 
+           have to force a redisplay.
        */
+
        DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview row deleted\n");
+
+       DisplaySuspender ds;
        sync_order_keys_from_treeview ();
 }
 
 void
 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
 {
+       /* reordering implies that RID's will change, so sync_order_keys() will
+          cause a redisplay.
+       */
+
        DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview reordered\n");
        sync_order_keys_from_treeview ();
 }
@@ -569,6 +584,7 @@ EditorRoutes::visible_changed (std::string const & path)
                return;
        }
 
+       DisplaySuspender ds;
        TreeIter iter;
 
        if ((iter = _model->get_iter (path))) {
@@ -599,10 +615,25 @@ EditorRoutes::active_changed (std::string const & path)
 void
 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
 {
-       TreeModel::Row row;
        PBD::Unwinder<bool> at (_adding_routes, true);
 
-       suspend_redisplay ();
+       bool from_scratch = (_model->children().size() == 0);
+       Gtk::TreeModel::Children::iterator insert_iter = _model->children().end();
+
+       for (Gtk::TreeModel::Children::iterator it = _model->children().begin(); it != _model->children().end(); ++it) {
+               boost::shared_ptr<Route> r = (*it)[_columns.route];
+
+               if (r->order_key() == (routes.front()->route()->order_key() + routes.size())) {
+                       insert_iter = it;
+                       break;
+               }
+       }
+
+       if(!from_scratch) {
+               _editor->selection->tracks.clear();
+       } 
+
+       DisplaySuspender ds;
 
        _display.set_model (Glib::RefPtr<ListStore>());
 
@@ -610,7 +641,7 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
 
                boost::shared_ptr<MidiTrack> midi_trk = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
 
-               row = *(_model->append ());
+               TreeModel::Row row = *(_model->insert (insert_iter));
 
                row[_columns.text] = (*x)->route()->name();
                row[_columns.visible] = (*x)->marked_for_display();
@@ -634,6 +665,10 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
                row[_columns.solo_safe_state] = (*x)->route()->solo_safe();
                row[_columns.name_editable] = true;
 
+               if (!from_scratch) {
+                       _editor->selection->add(*x);
+               }
+
                boost::weak_ptr<Route> wr ((*x)->route());
 
                (*x)->route()->gui_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context());
@@ -667,7 +702,6 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
        update_input_active_display ();
        update_active_display ();
 
-       resume_redisplay ();
        _display.set_model (_model);
 
        /* now update route order keys from the treeview/track display order */
@@ -701,10 +735,13 @@ EditorRoutes::route_removed (TimeAxisView *tv)
 
        TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator ri;
+       bool found = false;
 
        for (ri = rows.begin(); ri != rows.end(); ++ri) {
                if ((*ri)[_columns.tv] == tv) {
+                        PBD::Unwinder<bool> uw (_route_deletion_in_progress, true);
                        _model->erase (ri);
+                       found = true;
                        break;
                }
        }
@@ -759,7 +796,7 @@ EditorRoutes::update_visibility ()
        TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
 
-       suspend_redisplay ();
+       DisplaySuspender ds ();
 
        for (i = rows.begin(); i != rows.end(); ++i) {
                TimeAxisView *tv = (*i)[_columns.tv];
@@ -770,8 +807,6 @@ EditorRoutes::update_visibility ()
         */
 
        sync_order_keys_from_treeview ();
-
-       resume_redisplay ();
 }
 
 void
@@ -810,7 +845,7 @@ EditorRoutes::show_track_in_display (TimeAxisView& tv)
 void
 EditorRoutes::reset_remote_control_ids ()
 {
-       if (Config->get_remote_model() != EditorOrdered || !_session || _session->deletion_in_progress()) {
+       if (Config->get_remote_model() == UserOrdered || !_session || _session->deletion_in_progress()) {
                return;
        }
 
@@ -839,7 +874,7 @@ EditorRoutes::reset_remote_control_ids ()
                        uint32_t new_rid = (visible ? rid : invisible_key--);
 
                        if (new_rid != route->remote_control_id()) {
-                               route->set_remote_control_id_from_order_key (EditorSort, new_rid);      
+                               route->set_remote_control_id_explicit (new_rid);        
                                rid_change = true;
                        }
                        
@@ -885,20 +920,20 @@ EditorRoutes::sync_order_keys_from_treeview ()
                boost::shared_ptr<Route> route = (*ri)[_columns.route];
                bool visible = (*ri)[_columns.visible];
 
-               uint32_t old_key = route->order_key (EditorSort);
+               uint32_t old_key = route->order_key ();
 
                if (order != old_key) {
-                       route->set_order_key (EditorSort, order);
+                       route->set_order_key (order);
 
                        changed = true;
                }
 
-               if ((Config->get_remote_model() == EditorOrdered) && !route->is_master() && !route->is_monitor()) {
+               if ((Config->get_remote_model() == MixerOrdered) && !route->is_master() && !route->is_monitor()) {
 
                        uint32_t new_rid = (visible ? rid : invisible_key--);
 
                        if (new_rid != route->remote_control_id()) {
-                               route->set_remote_control_id_from_order_key (EditorSort, new_rid);      
+                               route->set_remote_control_id_explicit (new_rid);        
                                rid_change = true;
                        }
                        
@@ -913,7 +948,7 @@ EditorRoutes::sync_order_keys_from_treeview ()
        
        if (changed) {
                /* tell the world that we changed the editor sort keys */
-               _session->sync_order_keys (EditorSort);
+               _session->sync_order_keys ();
        }
 
        if (rid_change) {
@@ -923,37 +958,17 @@ EditorRoutes::sync_order_keys_from_treeview ()
 }
 
 void
-EditorRoutes::sync_treeview_from_order_keys (RouteSortOrderKey src)
+EditorRoutes::sync_treeview_from_order_keys ()
 {
-       /* Some route order key(s) for `src' has been changed, make sure that 
+       /* Some route order key(s) have been changed, make sure that 
           we update out tree/list model and GUI to reflect the change.
        */
 
-       if (!_session || _session->deletion_in_progress()) {
+       if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
                return;
        }
 
-       DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("editor sync model from order keys, src = %1\n", enum_2_string (src)));
-
-       if (src == MixerSort) {
-
-               if (!Config->get_sync_all_route_ordering()) {
-                       /* mixer sort keys changed - we don't care */
-                       return;
-               }
-
-               DEBUG_TRACE (DEBUG::OrderKeys, "reset editor order key to match mixer\n");
-
-               /* mixer sort keys were changed, update the editor sort
-                * keys since "sync mixer+editor order" is enabled.
-                */
-
-               boost::shared_ptr<RouteList> r = _session->get_routes ();
-               
-               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                       (*i)->sync_order_keys (src);
-               }
-       }
+       DEBUG_TRACE (DEBUG::OrderKeys, "editor sync model from order keys.\n");
 
        /* we could get here after either a change in the Mixer or Editor sort
         * order, but either way, the mixer order keys reflect the intended
@@ -973,7 +988,7 @@ EditorRoutes::sync_treeview_from_order_keys (RouteSortOrderKey src)
 
        for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
                boost::shared_ptr<Route> route = (*ri)[_columns.route];
-               sorted_routes.push_back (RoutePlusOrderKey (route, old_order, route->order_key (EditorSort)));
+               sorted_routes.push_back (RoutePlusOrderKey (route, old_order, route->order_key ()));
        }
 
        SortByNewDisplayOrder cmp;
@@ -1009,7 +1024,7 @@ EditorRoutes::hide_all_tracks (bool /*with_select*/)
        TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
 
-       suspend_redisplay ();
+       DisplaySuspender ds;
 
        for (i = rows.begin(); i != rows.end(); ++i) {
 
@@ -1022,14 +1037,6 @@ EditorRoutes::hide_all_tracks (bool /*with_select*/)
 
                row[_columns.visible] = false;
        }
-
-       resume_redisplay ();
-
-       /* XXX this seems like a hack and half, but its not clear where to put this
-          otherwise.
-       */
-
-       //reset_scrolling_region ();
 }
 
 void
@@ -1038,7 +1045,7 @@ EditorRoutes::set_all_tracks_visibility (bool yn)
        TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
 
-       suspend_redisplay ();
+       DisplaySuspender ds;
 
        for (i = rows.begin(); i != rows.end(); ++i) {
 
@@ -1057,8 +1064,6 @@ EditorRoutes::set_all_tracks_visibility (bool yn)
         */
 
        sync_order_keys_from_treeview ();
-
-       resume_redisplay ();
 }
 
 void
@@ -1067,7 +1072,7 @@ EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn)
        TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
 
-       suspend_redisplay ();
+       DisplaySuspender ds;
 
        for (i = rows.begin(); i != rows.end(); ++i) {
 
@@ -1119,8 +1124,6 @@ EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn)
         */
 
        sync_order_keys_from_treeview ();
-
-       resume_redisplay ();
 }
 
 void
@@ -1295,27 +1298,46 @@ EditorRoutes::button_press (GdkEventButton* ev)
        //Scroll editor canvas to selected track
        if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
-               // Get the model row.
                Gtk::TreeModel::Row row = *_model->get_iter (path);
-
                TimeAxisView *tv = row[_columns.tv];
 
-               int y_pos = tv->y_position();
-
-               //Clamp the y pos so that we do not extend beyond the canvas full height.
-               if (_editor->_full_canvas_height - y_pos < _editor->_visible_canvas_height){
-                   y_pos = _editor->_full_canvas_height - _editor->_visible_canvas_height;
-               }
-
-               //Only scroll to if the track is visible
-               if(y_pos != -1){
-                   _editor->reset_y_origin (y_pos);
+               if (tv) {
+                       _editor->ensure_time_axis_view_is_visible (*tv, true);
                }
        }
 
        return false;
 }
 
+void
+EditorRoutes::selection_changed ()
+{
+       if (_display.get_selection()->count_selected_rows() > 0) {
+
+               TreeIter iter;
+               TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows ();
+               TrackViewList selected;
+
+               _editor->get_selection().clear_regions ();
+
+               for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
+
+                       if ((iter = _model->get_iter (*i))) {
+
+                               TimeAxisView* tv = (*iter)[_columns.tv];
+                               selected.push_back (tv);
+                       }
+                       
+               }
+
+               _editor->get_selection().set (selected);
+               _editor->ensure_time_axis_view_is_visible (*(selected.front()), true);
+
+       } else {
+               _editor->get_selection().clear_tracks ();
+       }
+}
+
 bool
 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/)
 {
@@ -1339,18 +1361,17 @@ struct EditorOrderRouteSorter {
                    /* everything else before master */
                    return false;
            }
-           return a->order_key (EditorSort) < b->order_key (EditorSort);
+           return a->order_key () < b->order_key ();
     }
 };
 
 void
 EditorRoutes::initial_display ()
 {
-       suspend_redisplay ();
+       DisplaySuspender ds;
        _model->clear ();
 
        if (!_session) {
-               resume_redisplay ();
                return;
        }
 
@@ -1377,8 +1398,6 @@ EditorRoutes::initial_display ()
                _editor->add_routes (r);
                
        }
-
-       resume_redisplay ();
 }
 
 void
@@ -1499,7 +1518,7 @@ EditorRoutes::move_selected_tracks (bool up)
        }
 
        for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
-               uint32_t order = leading->second->order_key (EditorSort);
+               uint32_t order = leading->second->order_key ();
                neworder.push_back (order);
        }
 
@@ -1687,14 +1706,11 @@ EditorRoutes::show_tracks_with_regions_at_playhead ()
                }
        }
 
-       suspend_redisplay ();
+       DisplaySuspender ds;
 
        TreeModel::Children rows = _model->children ();
        for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
                TimeAxisView* tv = (*i)[_columns.tv];
                (*i)[_columns.visible] = (show.find (tv) != show.end());
        }
-
-       resume_redisplay ();
 }
-