Separate route list code from Editor into its own object, EditorRouteList. Hopefully...
authorCarl Hetherington <carl@carlh.net>
Wed, 1 Jul 2009 23:20:18 +0000 (23:20 +0000)
committerCarl Hetherington <carl@carlh.net>
Wed, 1 Jul 2009 23:20:18 +0000 (23:20 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@5302 d708f5d6-7413-0410-9779-e7cbd77b26cf

14 files changed:
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/editor_canvas.cc
gtk2_ardour/editor_edit_groups.cc
gtk2_ardour/editor_mixer.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_route_list.cc
gtk2_ardour/public_editor.h
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_ui.cc
gtk2_ardour/track_selection.cc
gtk2_ardour/track_selection.h
libs/gtkmm2ext/gtkmm2ext/cell_renderer_pixbuf_toggle.h

index 79895f4067771bf6d97cb723ed7da8a47cbf5933..0d8a58934983fbaa47551653e61bc3879133d0a5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2007 Paul Davis 
+    Copyright (C) 2000-2009 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -36,6 +36,7 @@
 #include "pbd/error.h"
 #include "pbd/enumwriter.h"
 #include "pbd/memento_command.h"
+#include "pbd/unknown_type.h"
 
 #include <glibmm/miscutils.h>
 #include <gtkmm/image.h>
@@ -97,6 +98,9 @@
 #include "editor_drag.h"
 #include "editor_group_tabs.h"
 #include "automation_time_axis.h"
+#include "editor_route_list.h"
+#include "midi_time_axis.h"
+#include "mixer_strip.h"
 
 #include "i18n.h"
 
@@ -298,9 +302,6 @@ Editor::Editor ()
        _show_measures = true;
        _show_waveforms_recording = true;
        show_gain_after_trim = false;
-       route_redisplay_does_not_sync_order_keys = false;
-       route_redisplay_does_not_reset_order_keys = false;
-       no_route_list_redisplay = false;
        verbose_cursor_on = true;
        route_removal = false;
        show_automatic_regions_in_region_list = true;
@@ -314,7 +315,6 @@ Editor::Editor ()
        editor_ruler_menu = 0;
        no_ruler_shown_update = false;
        route_group_menu = 0;
-       route_list_menu = 0;
        region_list_menu = 0;
        marker_menu = 0;
        start_end_marker_menu = 0;
@@ -531,51 +531,6 @@ Editor::Editor ()
        bottom_hbox.set_border_width (2);
        bottom_hbox.set_spacing (3);
 
-
-       CellRendererPixbufToggle* rec_col_renderer = Gtk::manage( new CellRendererPixbufToggle() );
-
-       rec_col_renderer->set_active_pixbuf(::get_icon("record_normal_red"));
-       rec_col_renderer->set_inactive_pixbuf(::get_icon("record_disabled_grey"));
-
-       rec_col_renderer->signal_toggled().connect(mem_fun(*this, &Editor::on_tv_rec_enable_toggled));
-
-       Gtk::TreeViewColumn* rec_state_column = Gtk::manage(new Gtk::TreeViewColumn("Rec", *rec_col_renderer));
-       rec_state_column->add_attribute(rec_col_renderer->property_active(), route_display_columns.rec_enabled);
-       rec_state_column->add_attribute(rec_col_renderer->property_visible(), route_display_columns.is_track);
-
-       route_display_model = ListStore::create(route_display_columns);
-       route_list_display.set_model (route_display_model);
-       
-       route_list_display.append_column (*rec_state_column);
-       route_list_display.append_column (_("Show"), route_display_columns.visible);
-       route_list_display.append_column (_("Name"), route_display_columns.text);
-       
-       route_list_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
-       route_list_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
-       route_list_display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
-       
-       route_list_display.set_headers_visible (true);
-       route_list_display.set_name ("TrackListDisplay");
-       route_list_display.get_selection()->set_mode (SELECTION_NONE);
-       route_list_display.set_reorderable (true);
-       route_list_display.set_rules_hint (true);
-       route_list_display.set_size_request (100,-1);
-       route_list_display.add_object_drag (route_display_columns.route.index(), "routes");
-
-       CellRendererToggle* route_list_visible_cell = dynamic_cast<CellRendererToggle*>(route_list_display.get_column_cell_renderer (1));
-       
-       route_list_visible_cell->property_activatable() = true;
-       route_list_visible_cell->property_radio() = false;
-
-       route_display_model->signal_row_deleted().connect (mem_fun (*this, &Editor::route_list_delete));
-       route_display_model->signal_row_changed().connect (mem_fun (*this, &Editor::route_list_change));
-       route_display_model->signal_rows_reordered().connect (mem_fun (*this, &Editor::route_list_reordered));
-
-       route_list_display.signal_button_press_event().connect (mem_fun (*this, &Editor::route_list_display_button_press), false);
-
-       route_list_scroller.add (route_list_display);
-       route_list_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
-
        group_model = ListStore::create(group_columns);
        route_group_display.set_model (group_model);
 
@@ -648,6 +603,7 @@ Editor::Editor ()
 
        group_model->signal_row_changed().connect (mem_fun (*this, &Editor::route_group_row_change));
 
+       _route_list = new EditorRouteList (this);
 
        route_group_display.set_name ("EditGroupList");
        route_group_display.get_selection()->set_mode (SELECTION_SINGLE);
@@ -792,7 +748,7 @@ Editor::Editor ()
        the_notebook.append_page (region_list_scroller, *nlabel);
        nlabel = manage (new Label (_("Tracks/Busses")));
        nlabel->set_angle (-90);
-       the_notebook.append_page (route_list_scroller, *nlabel);
+       the_notebook.append_page (_route_list->widget (), *nlabel);
        nlabel = manage (new Label (_("Snapshots")));
        nlabel->set_angle (-90);
        the_notebook.append_page (snapshot_display_scroller, *nlabel);
@@ -916,7 +872,6 @@ Editor::Editor ()
        BasicUI::AccessAction.connect (mem_fun (*this, &Editor::access_action));
 
        Config->ParameterChanged.connect (mem_fun (*this, &Editor::parameter_changed));
-       Route::SyncOrderKeys.connect (mem_fun (*this, &Editor::sync_order_keys));
 
        _last_normalization_value = 0;
 
@@ -938,25 +893,11 @@ Editor::~Editor()
        }
 #endif
 
+       delete _route_list;
        delete track_canvas;
        delete _drag;
 }
 
-void 
-Editor::on_tv_rec_enable_toggled(const Glib::ustring& path_string){
-
-       // Get the model row that has been toggled.
-       Gtk::TreeModel::Row row = *route_display_model->get_iter(Gtk::TreeModel::Path(path_string));
-
-       TimeAxisView *tv = row[route_display_columns.tv];
-       AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
-
-       if(atv != 0 && atv->is_audio_track()){
-             atv->get_diskstream()->set_record_enabled(!atv->get_diskstream()->record_enabled());
-       }
-}
-
-
 void
 Editor::add_toplevel_controls (Container& cont)
 {
@@ -1434,7 +1375,7 @@ Editor::connect_to_session (Session *t)
        //tempo_map_changed (Change (0));
        session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
 
-       initial_route_list_display ();
+       _route_list->initial_display ();
 
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
@@ -1442,30 +1383,6 @@ Editor::connect_to_session (Session *t)
 
        start_scrolling ();
 
-       /* don't show master bus in a new session */
-
-       if (ARDOUR_UI::instance()->session_is_new ()) {
-
-               TreeModel::Children rows = route_display_model->children();
-               TreeModel::Children::iterator i;
-       
-               no_route_list_redisplay = true;
-               
-               for (i = rows.begin(); i != rows.end(); ++i) {
-                       TimeAxisView *tv =  (*i)[route_display_columns.tv];
-                       RouteTimeAxisView *rtv;
-                       
-                       if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
-                               if (rtv->route()->is_master()) {
-                                       route_list_display.get_selection()->unselect (i);
-                               }
-                       }
-               }
-               
-               no_route_list_redisplay = false;
-               redisplay_route_list ();
-       }
-       
        switch (snap_type) {
        case SnapToRegionStart:
        case SnapToRegionEnd:
@@ -4697,7 +4614,8 @@ void
 Editor::use_visual_state (VisualState& vs)
 {
        no_save_visual = true;
-       no_route_list_redisplay = true;
+
+       _route_list->suspend_redisplay ();
 
        vertical_adjustment.set_value (vs.y_position);
 
@@ -4717,11 +4635,10 @@ Editor::use_visual_state (VisualState& vs)
 
 
        if (!vs.track_states.empty()) {
-               update_route_visibility ();
+               _route_list->update_visibility ();
        } 
 
-       no_route_list_redisplay = false;
-       redisplay_route_list ();
+       _route_list->resume_redisplay ();
 
        no_save_visual = false;
 }
@@ -5219,7 +5136,7 @@ Editor::first_idle ()
        }
 
        // first idle adds route children (automation tracks), so we need to redisplay here
-       redisplay_route_list();
+       _route_list->redisplay ();
        
        delete dialog;
 
@@ -5328,3 +5245,139 @@ Editor::axis_views_from_routes (list<Route*> r) const
        return t;
 }
 
+
+void
+Editor::handle_new_route (RouteList& routes)
+{
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_new_route), routes));
+       
+       RouteTimeAxisView *rtv;
+       list<RouteTimeAxisView*> new_views;
+
+       for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
+               boost::shared_ptr<Route> route = (*x);
+
+               if (route->is_hidden()) {
+                       continue;
+               }
+
+               DataType dt = route->input()->default_type();
+
+               if (dt == ARDOUR::DataType::AUDIO) {
+                       rtv = new AudioTimeAxisView (*this, *session, route, *track_canvas);
+               } else if (dt == ARDOUR::DataType::MIDI) {
+                       rtv = new MidiTimeAxisView (*this, *session, route, *track_canvas);
+               } else {
+                       throw unknown_type();
+               }
+
+               new_views.push_back (rtv);
+               track_views.push_back (rtv);
+               
+               rtv->effective_gain_display ();
+               
+               rtv->view()->RegionViewAdded.connect (mem_fun (*this, &Editor::region_view_added));
+               rtv->view()->HeightChanged.connect (mem_fun (*this, &Editor::streamview_height_changed));
+               
+               rtv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), rtv));
+       }
+
+       _route_list->routes_added (new_views);
+
+       if (show_editor_mixer_when_tracks_arrive) {
+               show_editor_mixer (true);
+       }
+
+       editor_list_button.set_sensitive (true);
+
+       _summary->set_dirty ();
+}
+
+void
+Editor::remove_route (TimeAxisView *tv)
+{
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::remove_route), tv));
+
+       TrackViewList::iterator i;
+       boost::shared_ptr<Route> route;
+       TimeAxisView* next_tv;
+
+       if (tv == entered_track) {
+               entered_track = 0;
+       }
+
+       if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
+
+               i = track_views.erase (i);
+
+               if (track_views.empty()) {
+                       next_tv = 0;
+               } else if (i == track_views.end()) {
+                       next_tv = track_views.front();
+               } else {
+                      next_tv = (*i);
+               }
+       }
+       
+       if (current_mixer_strip && current_mixer_strip->route() == route) {
+
+               if (next_tv) {
+                       set_selected_mixer_strip (*next_tv);
+               } else {
+                       /* make the editor mixer strip go away setting the
+                        * button to inactive (which also unticks the menu option)
+                        */
+
+                       ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
+               }
+       } 
+}
+
+void
+Editor::hide_track_in_display (TimeAxisView& tv, bool temponly)
+{
+       RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&tv);
+
+       if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
+               // this will hide the mixer strip
+               set_selected_mixer_strip (tv);
+       }
+
+       _route_list->hide_track_in_display (tv);
+}
+
+bool
+Editor::sync_track_view_list_and_route_list ()
+{
+       track_views = TrackSelection (_route_list->views ());
+       
+       _summary->set_dirty ();
+       _group_tabs->set_dirty ();
+       
+       return false; // do not call again (until needed)
+}
+
+void
+Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
+{
+       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               theslot (**i);
+       }
+}
+
+RouteTimeAxisView*
+Editor::get_route_view_by_id (PBD::ID& id)
+{
+       RouteTimeAxisView* v;
+
+       for(TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
+                       if(v->route()->id() == id) {
+                               return v;
+                       }
+               }
+       }
+
+       return 0;
+}
+
index a05ff655d3d91e95338f70e336ba6127f7267200..7a62353bca1921fa1189d3d08c081eb969959923 100644 (file)
@@ -116,6 +116,7 @@ class TimeFXDialog;
 class TimeSelection;
 class TrackSelection;
 class EditorGroupTabs;
+class EditorRouteList;
 
 /* <CMT Additions> */
 class ImageFrameView;
@@ -307,7 +308,6 @@ class Editor : public PublicEditor
        /* stuff that AudioTimeAxisView and related classes use */
 
        PlaylistSelector& playlist_selector() const;
-       void route_name_changed (TimeAxisView *);
        void clear_playlist (boost::shared_ptr<ARDOUR::Playlist>);
 
        void new_playlists (TimeAxisView* v);
@@ -324,7 +324,6 @@ class Editor : public PublicEditor
        void show_editor_list (bool yn);
        void set_selected_mixer_strip (TimeAxisView&);
        void hide_track_in_display (TimeAxisView& tv, bool temporary = false);
-       void show_track_in_display (TimeAxisView& tv);
 
        /* nudge is initiated by transport controls owned by ARDOUR_UI */
 
@@ -374,8 +373,6 @@ class Editor : public PublicEditor
        void scroll_tracks_down_line ();
        void scroll_tracks_up_line ();
 
-       void move_selected_tracks (bool up);
-
        bool new_regionviews_display_gain () { return _new_regionviews_show_envelope; }
        void prepare_for_cleanup ();
        void finish_cleanup ();
@@ -402,8 +399,6 @@ class Editor : public PublicEditor
        void goto_visual_state (uint32_t);
        void save_visual_state (uint32_t);
 
-       void update_rec_display ();
-
   protected:
        void map_transport_state ();
        void map_position_change (nframes64_t);
@@ -1394,11 +1389,8 @@ class Editor : public PublicEditor
        /// Snap threshold in pixels
        double snap_threshold;
 
-       void handle_gui_changes (const std::string &, void *);
        bool ignore_gui_changes;
 
-       void    hide_all_tracks (bool with_select);
-
        Drag* _drag;
 
        void break_drag ();
@@ -1768,80 +1760,17 @@ public:
 
        ArdourCanvas::SimpleRect   *zoom_rect;
        void reposition_zoom_rect (nframes64_t start, nframes64_t end);
+
+       EditorRouteList* _route_list;
        
        /* diskstream/route display management */
        Glib::RefPtr<Gdk::Pixbuf> rec_enabled_icon;
        Glib::RefPtr<Gdk::Pixbuf> rec_disabled_icon;
 
-       struct RouteDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
-           RouteDisplayModelColumns() { 
-                   add (text);
-                   add (visible);
-                   add (rec_enabled);
-                   add (temporary_visible);
-                   add (is_track);
-                   add (tv);
-                   add (route);
-           }
-           Gtk::TreeModelColumn<Glib::ustring>  text;
-           Gtk::TreeModelColumn<bool>           visible;
-           Gtk::TreeModelColumn<bool>           rec_enabled;
-           Gtk::TreeModelColumn<bool>           temporary_visible;
-           Gtk::TreeModelColumn<bool>           is_track;
-           Gtk::TreeModelColumn<TimeAxisView*>  tv;
-           Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Route> >  route;
-       };
-
-       void on_tv_rec_enable_toggled(const Glib::ustring& path_string);
-
-       RouteDisplayModelColumns         route_display_columns;
-       Glib::RefPtr<Gtk::ListStore>     route_display_model;
        Glib::RefPtr<Gtk::TreeSelection> route_display_selection;
 
-       Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Route> > route_list_display; 
-       Gtk::ScrolledWindow                   route_list_scroller;
-       Gtk::Menu*                            route_list_menu;
-
-       void update_route_visibility ();
-
-       void sync_order_keys (const char*);
-       bool route_redisplay_does_not_sync_order_keys;
-       bool route_redisplay_does_not_reset_order_keys;
-
-       bool route_list_display_button_press (GdkEventButton*);
-       void route_list_display_drag_data_received  (const Glib::RefPtr<Gdk::DragContext>& context,
-                                                    gint                x,
-                                                    gint                y,
-                                                    const Gtk::SelectionData& data,
-                                                    guint               info,
-                                                    guint               time);
-
-       bool route_list_selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
-
-       void route_list_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&);
-       void route_list_delete (const Gtk::TreeModel::Path&);
-       void track_list_reorder (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order);
-
-       void initial_route_list_display ();
-       void redisplay_route_list();
-       void route_list_reordered (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* what);
-       bool ignore_route_list_reorder;
-       bool no_route_list_redisplay;
        bool sync_track_view_list_and_route_list ();
 
-       void build_route_list_menu ();
-       void show_route_list_menu ();
-
-       void show_all_routes ();
-       void hide_all_routes ();
-       void show_all_audiotracks ();
-       void hide_all_audiotracks ();
-       void show_all_audiobus ();
-       void hide_all_audiobus ();
-
-       void set_all_tracks_visibility (bool yn);
-       void set_all_audio_visibility (int type, bool yn);
-
        /* edit group management */
 
         struct GroupListModelColumns : public Gtk::TreeModel::ColumnRecord {
@@ -2297,6 +2226,8 @@ public:
 
        friend class EditorSummary;
        friend class EditorGroupTabs;
+
+       friend class EditorRouteList;
 };
 
 #endif /* __ardour_editor_h__ */
index 1799938dabc08320afe1f4d2018c7a8f7636bc52..22db438a62bb398f3a4645af5ef048618aeed598 100644 (file)
@@ -30,6 +30,7 @@
 #include "i18n.h"
 #include "audio_time_axis.h"
 #include "editor_group_tabs.h"
+#include "editor_route_list.h"
 
 using namespace Gtk;
 using namespace Glib;
@@ -312,9 +313,9 @@ Editor::register_actions ()
        act = ActionManager::register_action (editor_actions, "toggle-zoom", _("Toggle Zoom State"), mem_fun(*this, &Editor::swap_visual_state));
        ActionManager::session_sensitive_actions.push_back (act);
 
-       act = ActionManager::register_action (editor_actions, "move-selected-tracks-up", _("Move Selected Tracks Up"), bind (mem_fun(*this, &Editor::move_selected_tracks), true));
+       act = ActionManager::register_action (editor_actions, "move-selected-tracks-up", _("Move Selected Tracks Up"), bind (mem_fun(*_route_list, &EditorRouteList::move_selected_tracks), true));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (editor_actions, "move-selected-tracks-down", _("Move Selected Tracks Down"), bind (mem_fun(*this, &Editor::move_selected_tracks), false));
+       act = ActionManager::register_action (editor_actions, "move-selected-tracks-down", _("Move Selected Tracks Down"), bind (mem_fun(*_route_list, &EditorRouteList::move_selected_tracks), false));
        ActionManager::session_sensitive_actions.push_back (act);
 
        act = ActionManager::register_action (editor_actions, "scroll-tracks-up", _("Scroll Tracks Up"), mem_fun(*this, &Editor::scroll_tracks_up));
index c753ab50ac9807014462a2c2ed6756f6571f7233..d85390383fe65f0c51da3be6f0871cd8bf6cdb2d 100644 (file)
@@ -42,6 +42,7 @@
 #include "editor_drag.h"
 #include "region_view.h"
 #include "editor_group_tabs.h"
+#include "editor_route_list.h"
 
 #include "i18n.h"
 
@@ -373,20 +374,15 @@ Editor::track_canvas_size_allocated ()
 void
 Editor::controls_layout_size_request (Requisition* req)
 {
-       TreeModel::Children rows = route_display_model->children();
-       TreeModel::Children::iterator i;
-       double pos;
-       bool changed = false;
-
-       for (pos = 0, i = rows.begin(); i != rows.end(); ++i) {
-               TimeAxisView *tv = (*i)[route_display_columns.tv];
-               if (tv != 0) {
-                       pos += tv->effective_height ();
-                       tv->clip_to_viewport ();
-               }
+       double pos = 0;
+       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               pos += (*i)->effective_height ();
+               (*i)->clip_to_viewport ();
        }
 
        gint height = min ((gint) pos, (gint) (physical_screen_height - 600));
+       
+       bool changed = false;
 
        gint w = edit_controls_vbox.get_width();
        if (_group_tabs->is_mapped()) {
index 6eac473c7e68082988141d15ba169ab662968fb6..50d6eb57339354e779d07b17b184f38d73969cd6 100644 (file)
@@ -33,6 +33,7 @@
 #include "editor_group_tabs.h"
 #include "route_group_dialog.h"
 #include "route_time_axis.h"
+#include "editor_route_list.h"
 
 #include "ardour/route.h"
 
@@ -371,7 +372,7 @@ Editor::route_group_row_change (const Gtk::TreeModel::Path& path,const Gtk::Tree
        if ((*iter)[group_columns.is_visible]) {
                for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
                        if ((*j)->route_group() == group) {
-                               show_track_in_display (**j);
+                               _route_list->show_track_in_display (**j);
                        }
                }
        } else {
index 7fd31c468b81548ec7c45a8b3f910baaedae5df9..61b5e2f143d86ac48fab0ae105b9ddb63e7f84d4 100644 (file)
@@ -31,6 +31,7 @@
 #include "selection.h"
 #include "audio_time_axis.h"
 #include "actions.h"
+#include "editor_route_list.h"
 
 #include "i18n.h"
 
@@ -363,22 +364,20 @@ Editor::session_going_away ()
 
        /* hide all tracks */
 
-       hide_all_tracks (false);
+       _route_list->hide_all_tracks (false);
 
        /* rip everything out of the list displays */
 
        region_list_display.set_model (Glib::RefPtr<Gtk::TreeStore>(0));
-       route_list_display.set_model (Glib::RefPtr<Gtk::TreeStore>(0));
+       _route_list->clear ();
        named_selection_display.set_model (Glib::RefPtr<Gtk::TreeStore>(0));
        route_group_display.set_model (Glib::RefPtr<Gtk::TreeStore>(0));
 
        region_list_model->clear ();
-       route_display_model->clear ();
        named_selection_model->clear ();
        group_model->clear ();
 
        region_list_display.set_model (region_list_model);
-       route_list_display.set_model (route_display_model);
        named_selection_display.set_model (named_selection_model);
        route_group_display.set_model (group_model);
 
index 325ac0792283bb17334752cc9bc04d9a37f40367..47ef27dc28c667a2c28715162670db3800ae7418 100644 (file)
@@ -77,6 +77,7 @@
 #include "utils.h"
 #include "editor_drag.h"
 #include "strip_silence_dialog.h"
+#include "editor_route_list.h"
 
 #include "i18n.h"
 
@@ -1743,8 +1744,8 @@ Editor::temporal_zoom_region (bool both_axes)
                }
                
                /* hide irrelevant tracks */
-               
-               no_route_list_redisplay = true;
+
+               _route_list->suspend_redisplay ();
 
                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                        if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) {
@@ -1752,8 +1753,7 @@ Editor::temporal_zoom_region (bool both_axes)
                        }
                }
 
-               no_route_list_redisplay = false;
-               redisplay_route_list ();
+               _route_list->resume_redisplay ();
 
                vertical_adjustment.set_value (0.0);
                no_save_visual = false;
index 1cce9fb517445fc86b917dca9d56c989db80c84e..c597adf86f964be55663d99a08408bad6a45c9d8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-2009 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include <cmath>
 #include <cassert>
 
+#include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
+
+#include "ardour/diskstream.h"
+
 #include "editor.h"
 #include "keyboard.h"
 #include "ardour_ui.h"
@@ -34,6 +38,7 @@
 #include "actions.h"
 #include "utils.h"
 #include "editor_group_tabs.h"
+#include "editor_route_list.h"
 
 #include "pbd/unknown_type.h"
 
@@ -46,273 +51,366 @@ using namespace sigc;
 using namespace ARDOUR;
 using namespace PBD;
 using namespace Gtk;
+using namespace Gtkmm2ext;
 using namespace Glib;
 
-const char* _order_key = N_("editor");
+EditorRouteList::EditorRouteList (Editor* e)
+       : _editor (e),
+         _ignore_reorder (false),
+         _no_redisplay (false),
+         _redisplay_does_not_sync_order_keys (false),
+         _redisplay_does_not_reset_order_keys (false),
+         _menu (0)
+{
+       _scroller.add (_display);
+       _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
+
+       _model = ListStore::create (_columns);
+       _display.set_model (_model);
+
+       CellRendererPixbufToggle* rec_col_renderer = manage (new CellRendererPixbufToggle());
+
+       rec_col_renderer->set_active_pixbuf (::get_icon("record_normal_red"));
+       rec_col_renderer->set_inactive_pixbuf (::get_icon("record_disabled_grey"));
+
+       rec_col_renderer->signal_toggled().connect (mem_fun (*this, &EditorRouteList::on_tv_rec_enable_toggled));
+
+       Gtk::TreeViewColumn* rec_state_column = manage (new TreeViewColumn("Rec", *rec_col_renderer));
+       rec_state_column->add_attribute(rec_col_renderer->property_active(), _columns.rec_enabled);
+       rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track);
+
+       _display.append_column (*rec_state_column);
+       _display.append_column (_("Show"), _columns.visible);
+       _display.append_column (_("Name"), _columns.text);
+       
+       _display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
+       _display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
+       _display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
+       
+       _display.set_headers_visible (true);
+       _display.set_name ("TrackListDisplay");
+       _display.get_selection()->set_mode (SELECTION_NONE);
+       _display.set_reorderable (true);
+       _display.set_rules_hint (true);
+       _display.set_size_request (100, -1);
+       _display.add_object_drag (_columns.route.index(), "routes");
+
+       CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (1));
+       
+       visible_cell->property_activatable() = true;
+       visible_cell->property_radio() = false;
+
+       _model->signal_row_deleted().connect (mem_fun (*this, &EditorRouteList::route_deleted));
+       _model->signal_row_changed().connect (mem_fun (*this, &EditorRouteList::changed));
+       _model->signal_rows_reordered().connect (mem_fun (*this, &EditorRouteList::reordered));
+       _display.signal_button_press_event().connect (mem_fun (*this, &EditorRouteList::button_press), false);
+
+       Route::SyncOrderKeys.connect (mem_fun (*this, &EditorRouteList::sync_order_keys));
+}
+
+void 
+EditorRouteList::on_tv_rec_enable_toggled (Glib::ustring const & path_string)
+{
+       // Get the model row that has been toggled.
+       Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
+
+       TimeAxisView *tv = row[_columns.tv];
+       AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
+
+       if (atv != 0 && atv->is_audio_track()){
+             atv->get_diskstream()->set_record_enabled(!atv->get_diskstream()->record_enabled());
+       }
+}
 
 void
-Editor::handle_new_route (RouteList& routes)
+EditorRouteList::build_menu ()
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), routes));
+       using namespace Menu_Helpers;
+       using namespace Gtk;
+
+       _menu = new Menu;
        
-       TimeAxisView *tv;
-       RouteTimeAxisView *rtv;
-       TreeModel::Row parent;
-       TreeModel::Row row;
+       MenuList& items = _menu->items();
+       _menu->set_name ("ArdourContextMenu");
 
-       route_redisplay_does_not_sync_order_keys = true;
-       no_route_list_redisplay = true;
+       items.push_back (MenuElem (_("Show All"), mem_fun (*this, &EditorRouteList::show_all_routes)));
+       items.push_back (MenuElem (_("Hide All"), mem_fun (*this, &EditorRouteList::hide_all_routes)));
+       items.push_back (MenuElem (_("Show All Audio Tracks"), mem_fun (*this, &EditorRouteList::show_all_audiotracks)));
+       items.push_back (MenuElem (_("Hide All Audio Tracks"), mem_fun (*this, &EditorRouteList::hide_all_audiotracks)));
+       items.push_back (MenuElem (_("Show All Audio Busses"), mem_fun (*this, &EditorRouteList::show_all_audiobus)));
+       items.push_back (MenuElem (_("Hide All Audio Busses"), mem_fun (*this, &EditorRouteList::hide_all_audiobus)));
 
-       for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
-               boost::shared_ptr<Route> route = (*x);
+}
 
-               if (route->is_hidden()) {
-                       continue;
-               }
+void
+EditorRouteList::show_menu ()
+{
+       if (_menu == 0) {
+               build_menu ();
+       }
 
-               DataType dt = route->input()->default_type();
+       _menu->popup (1, gtk_get_current_event_time());
+}
 
-               if (dt == ARDOUR::DataType::AUDIO)
-                       tv = new AudioTimeAxisView (*this, *session, route, *track_canvas);
-               else if (dt == ARDOUR::DataType::MIDI)
-                       tv = new MidiTimeAxisView (*this, *session, route, *track_canvas);
-               else
-                       throw unknown_type();
+const char* _order_key = N_("editor");
 
-               //cerr << "Editor::handle_new_route() called on " << route->name() << endl;//DEBUG
-#if 0
-               if (route_display_model->children().size() == 0) {
-                       
-                       /* set up basic entries */
-                       
-                       TreeModel::Row row;
+void
+EditorRouteList::redisplay ()
+{
+       TreeModel::Children rows = _model->children();
+       TreeModel::Children::iterator i;
+       uint32_t position;
+       int n;
+
+       if (_no_redisplay) {
+               return;
+       }
+
+       for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
+               TimeAxisView *tv = (*i)[_columns.tv];
+               boost::shared_ptr<Route> route = (*i)[_columns.route];
+
+               if (tv == 0) {
+                       // just a "title" row
+                       continue;
+               }
+
+               if (!_redisplay_does_not_reset_order_keys) {
                        
-                       row = *(route_display_model->append());  // path = "0"
-                       row[route_display_columns.text] = _("Busses");
-                       row[route_display_columns.tv] = 0;
-                       row = *(route_display_model->append());  // path = "1"
-                       row[route_display_columns.text] = _("Tracks");
-                       row[route_display_columns.tv] = 0;
+                       /* this reorder is caused by user action, so reassign sort order keys
+                          to tracks.
+                       */
                        
+                       route->set_order_key (_order_key, n);
                }
-               
-               if (dynamic_cast<AudioTrack*>(route.get()) != 0) {
-                       TreeModel::iterator iter = route_display_model->get_iter ("1");  // audio tracks 
-                       parent = *iter;
+
+               bool visible = (*i)[_columns.visible];
+
+               /* show or hide the TimeAxisView */
+               if (visible) {
+                       tv->set_marked_for_display (true);
+                       position += tv->show_at (position, n, &_editor->edit_controls_vbox);
+                       tv->clip_to_viewport ();
                } else {
-                       TreeModel::iterator iter = route_display_model->get_iter ("0");  // busses
-                       parent = *iter;
+                       tv->set_marked_for_display (false);
+                       tv->hide ();
                }
                
-               
-               row = *(route_display_model->append (parent.children()));
-#else 
-               row = *(route_display_model->append ());
-#endif
+               n++;
+       }
 
-               // cerr << route->name() << " marked for display ? " << tv->marked_for_display() << endl;
-               
-               row[route_display_columns.text] = route->name();
-               row[route_display_columns.visible] = tv->marked_for_display();
-               row[route_display_columns.tv] = tv;
-               row[route_display_columns.route] = route;
-               row[route_display_columns.is_track] = (boost::dynamic_pointer_cast<Track>(route) != 0);
+       /* whenever we go idle, update the track view list to reflect the new order.
+          we can't do this here, because we could mess up something that is traversing
+          the track order and has caused a redisplay of the list.
+       */
 
-               track_views.push_back (tv);
-               
-               ignore_route_list_reorder = true;
-               
-               if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv)) != 0) {
-                       /* added a new fresh one at the end */
-                       if (rtv->route()->order_key(_order_key) == -1) {
-                               rtv->route()->set_order_key (_order_key, route_display_model->children().size()-1);
-                       }
-                       rtv->effective_gain_display ();
-               }
-               
-               ignore_route_list_reorder = false;
+       Glib::signal_idle().connect (mem_fun (*_editor, &Editor::sync_track_view_list_and_route_list));
+       
+       _editor->full_canvas_height = position + _editor->canvas_timebars_vsize;
+       _editor->vertical_adjustment.set_upper (_editor->full_canvas_height);
 
-               route->gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes));
-               tv->view()->RegionViewAdded.connect (mem_fun (*this, &Editor::region_view_added));
-               tv->view()->HeightChanged.connect (mem_fun (*this, &Editor::streamview_height_changed));
-               
-               tv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), tv));
+       if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) {
+               /* 
+                  We're increasing the size of the canvas while the bottom is visible.
+                  We scroll down to keep in step with the controls layout.
+               */
+               _editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
        }
 
-       no_route_list_redisplay = false;
+       if (!_redisplay_does_not_reset_order_keys && !_redisplay_does_not_sync_order_keys) {
+               _editor->current_session()->sync_order_keys (_order_key);
+       }
+}
 
-       redisplay_route_list ();
+void
+EditorRouteList::route_deleted (Gtk::TreeModel::Path const & path)
+{
+       /* this could require an order reset & sync */
+       _editor->current_session()->set_remote_control_ids();
+       _ignore_reorder = true;
+       redisplay ();
+       _ignore_reorder = false;
+}
 
-       if (show_editor_mixer_when_tracks_arrive) {
-               show_editor_mixer (true);
-       }
 
-       editor_list_button.set_sensitive(true);
-       route_redisplay_does_not_sync_order_keys = false;
+void
+EditorRouteList::changed (Gtk::TreeModel::Path const & path, Gtk::TreeModel::iterator const & iter)
+{
+       /* never reset order keys because of a property change */
+       _redisplay_does_not_reset_order_keys = true;
+       _editor->current_session()->set_remote_control_ids();
+       redisplay ();
+       _redisplay_does_not_reset_order_keys = false;
+}
+
+void
+EditorRouteList::routes_added (list<RouteTimeAxisView*> routes)
+{
+       TreeModel::Row row;
+
+       _redisplay_does_not_sync_order_keys = true;
+       suspend_redisplay ();
+
+       for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
+
+               row = *(_model->append ());
+
+               row[_columns.text] = (*x)->route()->name();
+               row[_columns.visible] = (*x)->marked_for_display();
+               row[_columns.tv] = *x;
+               row[_columns.route] = (*x)->route ();
+               row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
+
+               _ignore_reorder = true;
+               
+               /* added a new fresh one at the end */
+               if ((*x)->route()->order_key(_order_key) == -1) {
+                       (*x)->route()->set_order_key (_order_key, _model->children().size()-1);
+               }
+               
+               _ignore_reorder = false;
+
+               boost::weak_ptr<Route> wr ((*x)->route());
+               (*x)->route()->gui_changed.connect (mem_fun (*this, &EditorRouteList::handle_gui_changes));
+               (*x)->route()->NameChanged.connect (bind (mem_fun (*this, &EditorRouteList::route_name_changed), wr));
+               (*x)->GoingAway.connect (bind (mem_fun (*this, &EditorRouteList::route_removed), *x));
 
-       _summary->set_dirty ();
+               if ((*x)->is_track()) {
+                       boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
+                       t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &EditorRouteList::update_rec_display));
+               }
+       }
+
+       resume_redisplay ();
+       _redisplay_does_not_sync_order_keys = false;
 }
 
 void
-Editor::handle_gui_changes (const string & what, void *src)
+EditorRouteList::handle_gui_changes (string const & what, void *src)
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_gui_changes), what, src));
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRouteList::handle_gui_changes), what, src));
 
        if (what == "track_height") {
                /* Optional :make tracks change height while it happens, instead 
                   of on first-idle
                */
                //update_canvas_now ();
-               redisplay_route_list ();
+               redisplay ();
        }
 
        if (what == "visible_tracks") {
-               redisplay_route_list ();
+               redisplay ();
        }
 }
 
 void
-Editor::remove_route (TimeAxisView *tv)
+EditorRouteList::route_removed (TimeAxisView *tv)
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::remove_route), tv));
+       ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRouteList::route_removed), tv));
 
-       TrackViewList::iterator i;
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator ri;
-       boost::shared_ptr<Route> route;
-       TimeAxisView* next_tv;
-
-       if (tv == entered_track) {
-               entered_track = 0;
-       }
 
        /* the core model has changed, there is no need to sync 
           view orders.
        */
 
-       route_redisplay_does_not_sync_order_keys = true;
+       _redisplay_does_not_sync_order_keys = true;
 
        for (ri = rows.begin(); ri != rows.end(); ++ri) {
-               if ((*ri)[route_display_columns.tv] == tv) {
-                       route = (*ri)[route_display_columns.route];
-                       route_display_model->erase (ri);
+               if ((*ri)[_columns.tv] == tv) {
+                       _model->erase (ri);
                        break;
                }
        }
 
-       route_redisplay_does_not_sync_order_keys = false;
-
-       if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
-
-               i = track_views.erase (i);
-
-               if (track_views.empty()) {
-                       next_tv = 0;
-               } else if (i == track_views.end()) {
-                       next_tv = track_views.front();
-               } else {
-                      next_tv = (*i);
-               }
-       }
-       
-       if (current_mixer_strip && current_mixer_strip->route() == route) {
-
-               if (next_tv) {
-                       set_selected_mixer_strip (*next_tv);
-               } else {
-                       /* make the editor mixer strip go away setting the
-                        * button to inactive (which also unticks the menu option)
-                        */
-
-                       ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
-               }
-       } 
+       _redisplay_does_not_sync_order_keys = false;
 }
 
 void
-Editor::route_name_changed (TimeAxisView *tv)
+EditorRouteList::route_name_changed (boost::weak_ptr<Route> r)
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::route_name_changed), tv));
+       ENSURE_GUI_THREAD (bind (mem_fun (*this, &EditorRouteList::route_name_changed), r));
+
+       boost::shared_ptr<Route> route = r.lock ();
+       if (!route) {
+               return;
+       }
        
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
        
        for (i = rows.begin(); i != rows.end(); ++i) {
-               if ((*i)[route_display_columns.tv] == tv) {
-                       (*i)[route_display_columns.text] = tv->name();
+               boost::shared_ptr<Route> t = (*i)[_columns.route];
+               if (t == route) {
+                       (*i)[_columns.text] = route->name();
                        break;
                }
        } 
 }
 
 void
-Editor::update_route_visibility ()
+EditorRouteList::update_visibility ()
 {
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
-       
-       no_route_list_redisplay = true;
+
+       suspend_redisplay ();
 
        for (i = rows.begin(); i != rows.end(); ++i) {
-               TimeAxisView *tv = (*i)[route_display_columns.tv];
-               (*i)[route_display_columns.visible] = tv->marked_for_display ();
+               TimeAxisView *tv = (*i)[_columns.tv];
+               (*i)[_columns.visible] = tv->marked_for_display ();
                cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl;
        }
 
-       no_route_list_redisplay = false;
-       redisplay_route_list ();
+       resume_redisplay ();
 }
 
 void
-Editor::hide_track_in_display (TimeAxisView& tv, bool temponly)
+EditorRouteList::hide_track_in_display (TimeAxisView& tv)
 {
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
 
        for (i = rows.begin(); i != rows.end(); ++i) {
-               if ((*i)[route_display_columns.tv] == &tv) { 
-                       (*i)[route_display_columns.visible] = false;
+               if ((*i)[_columns.tv] == &tv) { 
+                       (*i)[_columns.visible] = false;
                        break;
                }
        }
-
-       RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&tv);
-
-       if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
-               // this will hide the mixer strip
-               set_selected_mixer_strip (tv);
-       }
 }
 
 void
-Editor::show_track_in_display (TimeAxisView& tv)
+EditorRouteList::show_track_in_display (TimeAxisView& tv)
 {
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
        
        for (i = rows.begin(); i != rows.end(); ++i) {
-               if ((*i)[route_display_columns.tv] == &tv) { 
-                       (*i)[route_display_columns.visible] = true;
+               if ((*i)[_columns.tv] == &tv) { 
+                       (*i)[_columns.visible] = true;
                        break;
                }
        }
 }
 
 void
-Editor::route_list_reordered (const TreeModel::Path& path,const TreeModel::iterator& iter,int* what)
+EditorRouteList::reordered (TreeModel::Path const & path, TreeModel::iterator const & iter, int* what)
 {
-       redisplay_route_list ();
+       redisplay ();
 }
 
 
 void
-Editor::sync_order_keys (const char *src)
+EditorRouteList::sync_order_keys (char const * src)
 {
        vector<int> neworder;
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator ri;
 
-       if ((strcmp (src, _order_key) == 0) || !session || (session->state_of_the_state() & Session::Loading) || rows.empty()) {
+       ARDOUR::Session* s = _editor->current_session ();
+
+       if ((strcmp (src, _order_key) == 0) || !s || (s->state_of_the_state() & Session::Loading) || rows.empty()) {
                return;
        }
 
@@ -324,7 +422,7 @@ Editor::sync_order_keys (const char *src)
        int order;
 
        for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
-               boost::shared_ptr<Route> route = (*ri)[route_display_columns.route];
+               boost::shared_ptr<Route> route = (*ri)[_columns.route];
 
                int old_key = order;
                int new_key = route->order_key (_order_key);
@@ -337,121 +435,34 @@ Editor::sync_order_keys (const char *src)
        }
 
        if (changed) {
-               route_redisplay_does_not_reset_order_keys = true;
-               route_display_model->reorder (neworder);
-               route_redisplay_does_not_reset_order_keys = false;
-       }
-}
-
-void
-Editor::redisplay_route_list ()
-{
-       TreeModel::Children rows = route_display_model->children();
-       TreeModel::Children::iterator i;
-       uint32_t position;
-       int n;
-
-       if (no_route_list_redisplay) {
-               return;
-       }
-
-       for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
-               TimeAxisView *tv = (*i)[route_display_columns.tv];
-               boost::shared_ptr<Route> route = (*i)[route_display_columns.route];
-
-               if (tv == 0) {
-                       // just a "title" row
-                       continue;
-               }
-
-               if (!route_redisplay_does_not_reset_order_keys) {
-                       
-                       /* this reorder is caused by user action, so reassign sort order keys
-                          to tracks.
-                       */
-                       
-                       route->set_order_key (_order_key, n);
-               }
-
-               bool visible = (*i)[route_display_columns.visible];
-
-               /* show or hide the TimeAxisView */
-               if (visible) {
-                       tv->set_marked_for_display (true);
-                       position += tv->show_at (position, n, &edit_controls_vbox);
-                       tv->clip_to_viewport ();
-               } else {
-                       tv->set_marked_for_display (false);
-                       tv->hide ();
-               }
-               
-               n++;
-       }
-
-       /* whenever we go idle, update the track view list to reflect the new order.
-          we can't do this here, because we could mess up something that is traversing
-          the track order and has caused a redisplay of the list.
-       */
-
-       Glib::signal_idle().connect (mem_fun (*this, &Editor::sync_track_view_list_and_route_list));
-       
-       full_canvas_height = position + canvas_timebars_vsize;
-       vertical_adjustment.set_upper (full_canvas_height);
-
-       if ((vertical_adjustment.get_value() + _canvas_height) > vertical_adjustment.get_upper()) {
-               /* 
-                  We're increasing the size of the canvas while the bottom is visible.
-                  We scroll down to keep in step with the controls layout.
-               */
-               vertical_adjustment.set_value (full_canvas_height - _canvas_height);
-       }
-
-       if (!route_redisplay_does_not_reset_order_keys && !route_redisplay_does_not_sync_order_keys) {
-               session->sync_order_keys (_order_key);
+               _redisplay_does_not_reset_order_keys = true;
+               _model->reorder (neworder);
+               _redisplay_does_not_reset_order_keys = false;
        }
 }
 
-bool
-Editor::sync_track_view_list_and_route_list ()
-{
-       TreeModel::Children rows = route_display_model->children();
-       TreeModel::Children::iterator i;
-
-       track_views.clear ();
-
-       for (i = rows.begin(); i != rows.end(); ++i) {
-               TimeAxisView *tv = (*i)[route_display_columns.tv];
-               track_views.push_back (tv);
-       }
-
-       _summary->set_dirty ();
-       _group_tabs->set_dirty ();
-
-       return false; // do not call again (until needed)
-}
 
 void
-Editor::hide_all_tracks (bool with_select)
+EditorRouteList::hide_all_tracks (bool with_select)
 {
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
 
-       no_route_list_redisplay = true;
+       suspend_redisplay ();
 
        for (i = rows.begin(); i != rows.end(); ++i) {
                
                TreeModel::Row row = (*i);
-               TimeAxisView *tv = row[route_display_columns.tv];
+               TimeAxisView *tv = row[_columns.tv];
 
                if (tv == 0) {
                        continue;
                }
                
-               row[route_display_columns.visible] = false;
+               row[_columns.visible] = false;
        }
 
-       no_route_list_redisplay = false;
-       redisplay_route_list ();
+       resume_redisplay ();
 
        /* XXX this seems like a hack and half, but its not clear where to put this
           otherwise.
@@ -461,60 +472,39 @@ Editor::hide_all_tracks (bool with_select)
 }
 
 void
-Editor::build_route_list_menu ()
-{
-       using namespace Menu_Helpers;
-       using namespace Gtk;
-
-       route_list_menu = new Menu;
-       
-       MenuList& items = route_list_menu->items();
-       route_list_menu->set_name ("ArdourContextMenu");
-
-       items.push_back (MenuElem (_("Show All"), mem_fun(*this, &Editor::show_all_routes)));
-       items.push_back (MenuElem (_("Hide All"), mem_fun(*this, &Editor::hide_all_routes)));
-       items.push_back (MenuElem (_("Show All Audio Tracks"), mem_fun(*this, &Editor::show_all_audiotracks)));
-       items.push_back (MenuElem (_("Hide All Audio Tracks"), mem_fun(*this, &Editor::hide_all_audiotracks)));
-       items.push_back (MenuElem (_("Show All Audio Busses"), mem_fun(*this, &Editor::show_all_audiobus)));
-       items.push_back (MenuElem (_("Hide All Audio Busses"), mem_fun(*this, &Editor::hide_all_audiobus)));
-
-}
-
-void
-Editor::set_all_tracks_visibility (bool yn)
+EditorRouteList::set_all_tracks_visibility (bool yn)
 {
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
 
-       no_route_list_redisplay = true;
+       suspend_redisplay ();
 
        for (i = rows.begin(); i != rows.end(); ++i) {
 
                TreeModel::Row row = (*i);
-               TimeAxisView* tv = row[route_display_columns.tv];
+               TimeAxisView* tv = row[_columns.tv];
 
                if (tv == 0) {
                        continue;
                }
                
-               (*i)[route_display_columns.visible] = yn;
+               (*i)[_columns.visible] = yn;
        }
 
-       no_route_list_redisplay = false;
-       redisplay_route_list ();
+       resume_redisplay ();
 }
 
 void
-Editor::set_all_audio_visibility (int tracks, bool yn) 
+EditorRouteList::set_all_audio_visibility (int tracks, bool yn) 
 {
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
 
-       no_route_list_redisplay = true;
+       suspend_redisplay ();
 
        for (i = rows.begin(); i != rows.end(); ++i) {
                TreeModel::Row row = (*i);
-               TimeAxisView* tv = row[route_display_columns.tv];
+               TimeAxisView* tv = row[_columns.tv];
                AudioTimeAxisView* atv;
 
                if (tv == 0) {
@@ -524,67 +514,66 @@ Editor::set_all_audio_visibility (int tracks, bool yn)
                if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
                        switch (tracks) {
                        case 0:
-                               (*i)[route_display_columns.visible] = yn;
+                               (*i)[_columns.visible] = yn;
                                break;
 
                        case 1:
                                if (atv->is_audio_track()) {
-                                       (*i)[route_display_columns.visible] = yn;
+                                       (*i)[_columns.visible] = yn;
                                }
                                break;
                                
                        case 2:
                                if (!atv->is_audio_track()) {
-                                       (*i)[route_display_columns.visible] = yn;
+                                       (*i)[_columns.visible] = yn;
                                }
                                break;
                        }
                }
        }
 
-       no_route_list_redisplay = false;
-       redisplay_route_list ();
+       resume_redisplay ();
 }
 
 void
-Editor::hide_all_routes ()
+EditorRouteList::hide_all_routes ()
 {
        set_all_tracks_visibility (false);
 }
 
 void
-Editor::show_all_routes ()
+EditorRouteList::show_all_routes ()
 {
        set_all_tracks_visibility (true);
 }
 
 void
-Editor::show_all_audiobus ()
+EditorRouteList::show_all_audiobus ()
 {
        set_all_audio_visibility (2, true);
 }
 void
-Editor::hide_all_audiobus ()
+EditorRouteList::hide_all_audiobus ()
 {
        set_all_audio_visibility (2, false);
 }
 
 void
-Editor::show_all_audiotracks()
+EditorRouteList::show_all_audiotracks()
 {
        set_all_audio_visibility (1, true);
 }
 void
-Editor::hide_all_audiotracks ()
+EditorRouteList::hide_all_audiotracks ()
 {
        set_all_audio_visibility (1, false);
 }
 
 bool
-Editor::route_list_display_button_press (GdkEventButton* ev)
+EditorRouteList::button_press (GdkEventButton* ev)
 {
        if (Keyboard::is_context_menu_event (ev)) {
-               show_route_list_menu ();
+               show_menu ();
                return true;
        }
 
@@ -594,7 +583,7 @@ Editor::route_list_display_button_press (GdkEventButton* ev)
        int cellx;
        int celly;
        
-       if (!route_list_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) {
+       if (!_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) {
                return false;
        }
 
@@ -604,11 +593,11 @@ Editor::route_list_display_button_press (GdkEventButton* ev)
                /* allow normal processing to occur */
                return false;
        case 1:
-               if ((iter = route_display_model->get_iter (path))) {
-                       TimeAxisView* tv = (*iter)[route_display_columns.tv];
+               if ((iter = _model->get_iter (path))) {
+                       TimeAxisView* tv = (*iter)[_columns.tv];
                        if (tv) {
-                               bool visible = (*iter)[route_display_columns.visible];
-                               (*iter)[route_display_columns.visible] = !visible;
+                               bool visible = (*iter)[_columns.visible];
+                               (*iter)[_columns.visible] = !visible;
                        }
                }
                return true;
@@ -624,18 +613,8 @@ Editor::route_list_display_button_press (GdkEventButton* ev)
        return false;
 }
 
-void
-Editor::show_route_list_menu()
-{
-       if (route_list_menu == 0) {
-               build_route_list_menu ();
-       }
-
-       route_list_menu->popup (1, gtk_get_current_event_time());
-}
-
 bool
-Editor::route_list_selection_filter (const Glib::RefPtr<TreeModel>& model, const TreeModel::Path& path, bool yn)
+EditorRouteList::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const &, bool)
 {
        return true;
 }
@@ -648,108 +627,85 @@ struct EditorOrderRouteSorter {
 };
 
 void
-Editor::initial_route_list_display ()
+EditorRouteList::initial_display ()
 {
-       boost::shared_ptr<RouteList> routes = session->get_routes();
+       boost::shared_ptr<RouteList> routes = _editor->current_session()->get_routes();
        RouteList r (*routes);
        EditorOrderRouteSorter sorter;
 
        r.sort (sorter);
-       
-       no_route_list_redisplay = true;
 
-       route_display_model->clear ();
+       suspend_redisplay ();
 
-       handle_new_route (r);
+       _model->clear ();
+       _editor->handle_new_route (r);
 
-       no_route_list_redisplay = false;
+       /* don't show master bus in a new session */
 
-       redisplay_route_list ();
-}
+       if (ARDOUR_UI::instance()->session_is_new ()) {
 
-void
-Editor::track_list_reorder (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter, int* new_order)
-{
-       route_redisplay_does_not_sync_order_keys = true;
-       session->set_remote_control_ids();
-       redisplay_route_list ();
-       route_redisplay_does_not_sync_order_keys = false;
-}
+               TreeModel::Children rows = _model->children();
+               TreeModel::Children::iterator i;
+       
+               _no_redisplay = true;
+               
+               for (i = rows.begin(); i != rows.end(); ++i) {
+                       TimeAxisView *tv =  (*i)[_columns.tv];
+                       RouteTimeAxisView *rtv;
+                       
+                       if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
+                               if (rtv->route()->is_master()) {
+                                       _display.get_selection()->unselect (i);
+                               }
+                       }
+               }
+               
+               _no_redisplay = false;
+               redisplay ();
+       }       
 
-void
-Editor::route_list_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter)
-{
-       /* never reset order keys because of a property change */
-       route_redisplay_does_not_reset_order_keys = true;
-       session->set_remote_control_ids();
-       redisplay_route_list ();
-       route_redisplay_does_not_reset_order_keys = false;
+       resume_redisplay ();
 }
 
 void
-Editor::route_list_delete (const Gtk::TreeModel::Path& path)
+EditorRouteList::track_list_reorder (Gtk::TreeModel::Path const & path, Gtk::TreeModel::iterator const & iter, int* new_order)
 {
-       /* this could require an order reset & sync */
-       session->set_remote_control_ids();
-       ignore_route_list_reorder = true;
-       redisplay_route_list ();
-       ignore_route_list_reorder = false;
+       _redisplay_does_not_sync_order_keys = true;
+       _editor->current_session()->set_remote_control_ids();
+       redisplay ();
+       _redisplay_does_not_sync_order_keys = false;
 }
 
-
 void  
-Editor::route_list_display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
-                                               int x, int y, 
-                                               const SelectionData& data,
-                                               guint info, guint time)
+EditorRouteList::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
+                                            int x, int y, 
+                                            const SelectionData& data,
+                                            guint info, guint time)
 {
        if (data.get_target() == "GTK_TREE_MODEL_ROW") {
-               route_list_display.on_drag_data_received (context, x, y, data, info, time);
+               _display.on_drag_data_received (context, x, y, data, info, time);
                return;
        }
+       
        context->drag_finish (true, false, time);
 }
 
-RouteTimeAxisView*
-Editor::get_route_view_by_id (PBD::ID& id)
-{
-       RouteTimeAxisView* v;
-
-       for(TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-               if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
-                       if(v->route()->id() == id) {
-                               return v;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-void
-Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
-{
-       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-               theslot (**i);
-       }
-}
-
 void
-Editor::move_selected_tracks (bool up)
+EditorRouteList::move_selected_tracks (bool up)
 {
-       if (selection->tracks.empty()) {
+       if (_editor->selection->tracks.empty()) {
                return;
        }
 
        typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
        std::list<ViewRoute> view_routes;
        std::vector<int> neworder;
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator ri;
 
        for (ri = rows.begin(); ri != rows.end(); ++ri) {
-               TimeAxisView* tv = (*ri)[route_display_columns.tv];
-               boost::shared_ptr<Route> route = (*ri)[route_display_columns.route];
+               TimeAxisView* tv = (*ri)[_columns.tv];
+               boost::shared_ptr<Route> route = (*ri)[_columns.route];
 
                view_routes.push_back (ViewRoute (tv, route));
        }
@@ -765,7 +721,7 @@ Editor::move_selected_tracks (bool up)
                ++leading;
                
                while (leading != view_routes.end()) {
-                       if (selection->selected (leading->first)) {
+                       if (_editor->selection->selected (leading->first)) {
                                view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
                                leading = view_routes.erase (leading);
                        } else {
@@ -790,7 +746,7 @@ Editor::move_selected_tracks (bool up)
 
                while (1) {
 
-                       if (selection->selected (leading->first)) {
+                       if (_editor->selection->selected (leading->first)) {
                                list<ViewRoute>::iterator tmp;
 
                                /* need to insert *after* trailing, not *before* it,
@@ -841,27 +797,46 @@ Editor::move_selected_tracks (bool up)
                neworder.push_back (leading->second->order_key (_order_key));
        }
 
-       route_display_model->reorder (neworder);
+       _model->reorder (neworder);
 
-       session->sync_order_keys (_order_key);
+       _editor->current_session()->sync_order_keys (_order_key);
 }
 
 void
-Editor::update_rec_display ()
+EditorRouteList::update_rec_display ()
 {
-       TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = _model->children();
        TreeModel::Children::iterator i;
        
        for (i = rows.begin(); i != rows.end(); ++i) {
-               boost::shared_ptr<Route> route = (*i)[route_display_columns.route];
+               boost::shared_ptr<Route> route = (*i)[_columns.route];
 
                if (boost::dynamic_pointer_cast<Track>(route)) {
 
                        if (route->record_enabled()){
-                               (*i)[route_display_columns.rec_enabled] = true;
+                               (*i)[_columns.rec_enabled] = true;
                        } else {
-                               (*i)[route_display_columns.rec_enabled] = false;
+                               (*i)[_columns.rec_enabled] = false;
                        }
                } 
        }
 }
+
+list<TimeAxisView*>
+EditorRouteList::views () const
+{
+       list<TimeAxisView*> v;
+       for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
+               v.push_back ((*i)[_columns.tv]);
+       }
+
+       return v;
+}
+
+void
+EditorRouteList::clear ()
+{
+       _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
+       _model->clear ();
+       _display.set_model (_model);
+}
index 6e020beb7797e355c2de38ca7c60af2169ea36f8..83aa91e1ae7ba66dca3fb8ef2bcf88b657072a05 100644 (file)
@@ -218,7 +218,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
        virtual Editing::ZoomFocus get_zoom_focus () const = 0;
        virtual gdouble   get_current_zoom () const = 0;
        virtual PlaylistSelector& playlist_selector() const = 0;
-       virtual void route_name_changed (TimeAxisView *) = 0;
        virtual void clear_playlist (boost::shared_ptr<ARDOUR::Playlist>) = 0;
        virtual void new_playlists (TimeAxisView*) = 0;
        virtual void copy_playlists (TimeAxisView*) = 0;
@@ -227,7 +226,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
        virtual void set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove = false) = 0;
        virtual void set_selected_mixer_strip (TimeAxisView&) = 0;
        virtual void hide_track_in_display (TimeAxisView& tv, bool temporary = false) = 0;
-       virtual void show_track_in_display (TimeAxisView& tv) = 0;
 
        /** Set whether the editor should follow the playhead.
         * @param yn true to follow playhead, otherwise false.
@@ -324,8 +322,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
        virtual bool canvas_markerview_end_handle_event(GdkEvent* event, ArdourCanvas::Item*,MarkerView*) = 0;
 #endif
 
-       virtual void update_rec_display () = 0;
-
        static const int window_border_width;
        static const int container_border_width;
        static const int vertical_spacing;
index df79aca78ee6ebc4695b94a7d93d1b508bc7233e..ebc4a350e69739de2707421c1b1e65b0c8593e33 100644 (file)
@@ -363,7 +363,6 @@ RouteTimeAxisView::label_view ()
 void
 RouteTimeAxisView::route_name_changed ()
 {
-       _editor.route_name_changed (this);
        label_view ();
 }
 
index 2662ba96643cc4c54ff4511c8c257c045f996c01..c32929e35b83905019f23b30546904494f00d491 100644 (file)
@@ -195,7 +195,6 @@ RouteUI::set_route (boost::shared_ptr<Route> rp)
                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
                connections.push_back (t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed)));
-               connections.push_back (t->diskstream()->RecordEnableChanged.connect (mem_fun (PublicEditor::instance(), &PublicEditor::update_rec_display)));
                connections.push_back (_session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed)));
 
                rec_enable_button->show();
index 5e2922449144487193fb5fe39d278365fec0a995..d9c7f02e19b00ceabff2539a0666113ce24a0fac 100755 (executable)
@@ -3,6 +3,12 @@
 
 using namespace std;
 
+TrackSelection::TrackSelection (list<TimeAxisView*> const &t)
+       : list<TimeAxisView*> (t)
+{
+
+}
+
 list<TimeAxisView*>
 TrackSelection::add (list<TimeAxisView*> const & t)
 {
index 8d46a59828ac18d79eb53b97143080d5efd2d50a..2a4cc1b2887124848da1e40b5edb13bf3917c7a9 100644 (file)
@@ -27,6 +27,9 @@ class TimeAxisView;
 class TrackSelection : public std::list<TimeAxisView*>
 {
 public:
+       TrackSelection () {}
+               
+       TrackSelection (std::list<TimeAxisView*> const &);
        std::list<TimeAxisView*> add (std::list<TimeAxisView*> const &);
        bool contains (TimeAxisView const *) const;
 };
index 74f5e59a526280c036d538f007775a7851b40815..18c1e5cac0d502da2814c9868fd971d78a80e2e2 100644 (file)
@@ -23,6 +23,7 @@
 #include <gtkmm/drawingarea.h>
 #include <gtkmm/adjustment.h>
 #include <gtkmm/widget.h>
+#include <gtkmm/cellrenderer.h>
 #include <gdkmm.h>
 
 using namespace Gtk;