From: Carl Hetherington Date: Mon, 19 Jul 2010 21:47:07 +0000 (+0000) Subject: Tweak group tabs class hierarchy and offer the same menu in both editor and mixer... X-Git-Tag: 3.0-alpha5~1806 X-Git-Url: https://git.carlh.net/gitweb/?a=commitdiff_plain;h=536384ea4ea7d468363ff5f284a817c42083c3b5;p=ardour.git Tweak group tabs class hierarchy and offer the same menu in both editor and mixer. Fixes #3336. git-svn-id: svn://localhost/ardour2/branches/3.0@7441 d708f5d6-7413-0410-9779-e7cbd77b26cf --- diff --git a/gtk2_ardour/editor_component.h b/gtk2_ardour/editor_component.h index 5b4f7e15d8..f6816c5608 100644 --- a/gtk2_ardour/editor_component.h +++ b/gtk2_ardour/editor_component.h @@ -20,13 +20,9 @@ #ifndef __ardour_gtk_editor_component_h__ #define __ardour_gtk_editor_component_h__ -#include - -#include "ardour/session_handle.h" - class Editor; -class EditorComponent : public ARDOUR::SessionHandlePtr +class EditorComponent { public: EditorComponent (Editor *); diff --git a/gtk2_ardour/editor_group_tabs.cc b/gtk2_ardour/editor_group_tabs.cc index 04f61aaeef..ccf95b797f 100644 --- a/gtk2_ardour/editor_group_tabs.cc +++ b/gtk2_ardour/editor_group_tabs.cc @@ -23,12 +23,13 @@ #include "route_time_axis.h" #include "utils.h" #include "editor_route_groups.h" +#include "editor_routes.h" using namespace std; using namespace ARDOUR; EditorGroupTabs::EditorGroupTabs (Editor* e) - : GroupTabs (e) + : EditorComponent (e) { } @@ -146,14 +147,54 @@ EditorGroupTabs::routes_for_tab (Tab const * t) const } -Gtk::Menu* -EditorGroupTabs::get_menu (RouteGroup *g) +void +EditorGroupTabs::add_menu_items (Gtk::Menu* m, RouteGroup* g) +{ + using namespace Gtk::Menu_Helpers; + + if (g) { + MenuList& items = m->items (); + items.push_back (MenuElem (_("Fit to Window"), sigc::bind (sigc::mem_fun (*_editor, &Editor::fit_route_group), g))); + } +} + +PBD::PropertyList +EditorGroupTabs::default_properties () const +{ + PBD::PropertyList plist; + + plist.add (Properties::active, true); + plist.add (Properties::mute, true); + plist.add (Properties::solo, true); + plist.add (Properties::recenable, true); + plist.add (Properties::edit, true); + + return plist; +} + +string +EditorGroupTabs::order_key () const { - return _editor->_route_groups->menu (g); + return X_("editor"); } -RouteGroup * -EditorGroupTabs::new_route_group () const +RouteList +EditorGroupTabs::selected_routes () const +{ + RouteList rl; + + for (TrackSelection::iterator i = _editor->get_selection().tracks.begin(); i != _editor->get_selection().tracks.end(); ++i) { + RouteTimeAxisView* rtv = dynamic_cast (*i); + if (rtv) { + rl.push_back (rtv->route()); + } + } + + return rl; +} + +void +EditorGroupTabs::sync_order_keys () { - return _editor->_route_groups->new_route_group (); + _editor->_routes->sync_order_keys (""); } diff --git a/gtk2_ardour/editor_group_tabs.h b/gtk2_ardour/editor_group_tabs.h index 4dc447da17..6d2b541747 100644 --- a/gtk2_ardour/editor_group_tabs.h +++ b/gtk2_ardour/editor_group_tabs.h @@ -22,7 +22,7 @@ class Editor; -class EditorGroupTabs : public GroupTabs +class EditorGroupTabs : public GroupTabs, public EditorComponent { public: EditorGroupTabs (Editor *); @@ -35,6 +35,9 @@ private: double extent () const { return _height; } - Gtk::Menu* get_menu (ARDOUR::RouteGroup* g); - ARDOUR::RouteGroup* new_route_group () const; + void add_menu_items (Gtk::Menu *, ARDOUR::RouteGroup *); + PBD::PropertyList default_properties () const; + std::string order_key () const; + ARDOUR::RouteList selected_routes () const; + void sync_order_keys (); }; diff --git a/gtk2_ardour/editor_locations.cc b/gtk2_ardour/editor_locations.cc index d4117b86b0..c74a97fc99 100644 --- a/gtk2_ardour/editor_locations.cc +++ b/gtk2_ardour/editor_locations.cc @@ -34,7 +34,7 @@ EditorLocations::EditorLocations (Editor* e) void EditorLocations::set_session (ARDOUR::Session* s) { - EditorComponent::set_session (s); + SessionHandlePtr::set_session (s); locations->set_session (s); } diff --git a/gtk2_ardour/editor_locations.h b/gtk2_ardour/editor_locations.h index 6d4d3128e4..414a57ee7d 100644 --- a/gtk2_ardour/editor_locations.h +++ b/gtk2_ardour/editor_locations.h @@ -20,6 +20,7 @@ #ifndef __gtk_ardour_editor_locations_h__ #define __gtk_ardour_editor_locations_h__ +#include "ardour/session_handle.h" #include "editor_component.h" class LocationUI; @@ -28,7 +29,7 @@ namespace Gtk { class Widget; } -class EditorLocations : public EditorComponent +class EditorLocations : public EditorComponent, public ARDOUR::SessionHandlePtr { public: EditorLocations (Editor *); diff --git a/gtk2_ardour/editor_regions.cc b/gtk2_ardour/editor_regions.cc index 1b8e07a28b..1acb580583 100644 --- a/gtk2_ardour/editor_regions.cc +++ b/gtk2_ardour/editor_regions.cc @@ -157,7 +157,7 @@ EditorRegions::EditorRegions (Editor* e) void EditorRegions::set_session (ARDOUR::Session* s) { - EditorComponent::set_session (s); + SessionHandlePtr::set_session (s); redisplay (); } diff --git a/gtk2_ardour/editor_regions.h b/gtk2_ardour/editor_regions.h index b17699e9e6..4ccb91588b 100644 --- a/gtk2_ardour/editor_regions.h +++ b/gtk2_ardour/editor_regions.h @@ -21,7 +21,7 @@ #include "editor_component.h" -class EditorRegions : public EditorComponent +class EditorRegions : public EditorComponent, public ARDOUR::SessionHandlePtr { public: EditorRegions (Editor *); diff --git a/gtk2_ardour/editor_route_groups.cc b/gtk2_ardour/editor_route_groups.cc index c30132a3b8..b66fa753da 100644 --- a/gtk2_ardour/editor_route_groups.cc +++ b/gtk2_ardour/editor_route_groups.cc @@ -48,7 +48,6 @@ using Gtkmm2ext::Keyboard; EditorRouteGroups::EditorRouteGroups (Editor* e) : EditorComponent (e), - _menu (0), _in_row_change (false) { @@ -153,7 +152,7 @@ EditorRouteGroups::EditorRouteGroups (Editor* e) w->show(); remove_button->add (*w); - add_button->signal_clicked().connect (hide_return (sigc::mem_fun (*this, &EditorRouteGroups::new_route_group))); + add_button->signal_clicked().connect (sigc::hide_return (sigc::mem_fun (*this, &EditorRouteGroups::run_new_group_dialog))); remove_button->signal_clicked().connect (sigc::mem_fun (*this, &EditorRouteGroups::remove_selected)); button_box->pack_start (*add_button); @@ -163,196 +162,6 @@ EditorRouteGroups::EditorRouteGroups (Editor* e) _display_packer->pack_start (*button_box, false, false); } - -Gtk::Menu* -EditorRouteGroups::menu (RouteGroup* g) -{ - using namespace Gtk::Menu_Helpers; - - delete _menu; - - Menu* new_from = new Menu; - MenuList& f = new_from->items (); - f.push_back (MenuElem (_("Selection..."), sigc::mem_fun (*this, &EditorRouteGroups::new_from_selection))); - f.push_back (MenuElem (_("Record Enabled..."), sigc::mem_fun (*this, &EditorRouteGroups::new_from_rec_enabled))); - f.push_back (MenuElem (_("Soloed..."), sigc::mem_fun (*this, &EditorRouteGroups::new_from_soloed))); - - _menu = new Menu; - _menu->set_name ("ArdourContextMenu"); - MenuList& items = _menu->items(); - - items.push_back (MenuElem (_("New..."), hide_return (sigc::mem_fun(*this, &EditorRouteGroups::new_route_group)))); - items.push_back (MenuElem (_("New From"), *new_from)); - if (g) { - items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::edit), g))); - items.push_back (MenuElem (_("Fit to Window"), sigc::bind (sigc::mem_fun (*_editor, &Editor::fit_route_group), g))); - items.push_back (MenuElem (_("Subgroup"), sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::subgroup), g))); - items.push_back (MenuElem (_("Collect"), sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::collect), g))); - } - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Activate All"), sigc::mem_fun(*this, &EditorRouteGroups::activate_all))); - items.push_back (MenuElem (_("Disable All"), sigc::mem_fun(*this, &EditorRouteGroups::disable_all))); - - return _menu; -} - -void -EditorRouteGroups::subgroup (RouteGroup* g) -{ - g->make_subgroup (); -} - -void -EditorRouteGroups::unsubgroup (RouteGroup* g) -{ - g->destroy_subgroup (); -} - -void -EditorRouteGroups::activate_all () -{ - _session->foreach_route_group ( - sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::set_activation), true) - ); -} - -void -EditorRouteGroups::disable_all () -{ - _session->foreach_route_group ( - sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::set_activation), false) - ); -} - -void -EditorRouteGroups::set_activation (RouteGroup* g, bool a) -{ - g->set_active (a, this); -} - -ARDOUR::RouteGroup * -EditorRouteGroups::new_route_group () const -{ - PropertyList plist; - - plist.add (Properties::active, true); - plist.add (Properties::mute, true); - plist.add (Properties::solo, true); - plist.add (Properties::edit, true); - - RouteGroup* g = new RouteGroup (*_session, ""); - - g->set_properties (plist); - - RouteGroupDialog d (g, Gtk::Stock::NEW); - int const r = d.do_run (); - - if (r != Gtk::RESPONSE_OK) { - delete g; - return 0; - } - - _session->add_route_group (g); - return g; -} -void -EditorRouteGroups::run_new_group_dialog (const RouteList& rl) -{ - PropertyList plist; - - plist.add (Properties::active, true); - plist.add (Properties::mute, true); - plist.add (Properties::solo, true); - plist.add (Properties::recenable, true); - plist.add (Properties::edit, true); - - RouteGroup* g = new RouteGroup (*_session, ""); - g->set_properties (plist); - - RouteGroupDialog d (g, Gtk::Stock::NEW); - int const r = d.do_run (); - - switch (r) { - case Gtk::RESPONSE_OK: - case Gtk::RESPONSE_ACCEPT: - _session->add_route_group (g); - for (RouteList::const_iterator i = rl.begin(); i != rl.end(); ++i) { - g->add (*i); - } - break; - default: - delete g; - } -} - -void -EditorRouteGroups::new_from_selection () -{ - if (_editor->get_selection().tracks.empty()) { - return; - } - - RouteList rl; - - for (TrackSelection::iterator i = _editor->get_selection().tracks.begin(); i != _editor->get_selection().tracks.end(); ++i) { - RouteTimeAxisView* rtv = dynamic_cast (*i); - if (rtv) { - rl.push_back (rtv->route()); - } - } - - if (rl.empty()) { - return; - } - - run_new_group_dialog (rl); -} - -void -EditorRouteGroups::new_from_rec_enabled () -{ - RouteList rl; - - for (TrackViewList::const_iterator i = _editor->get_track_views().begin(); i != _editor->get_track_views().end(); ++i) { - RouteTimeAxisView* rtv = dynamic_cast (*i); - if (rtv && rtv->route()->record_enabled()) { - rl.push_back (rtv->route()); - } - } - - if (rl.empty()) { - return; - } - - run_new_group_dialog (rl); -} - -void -EditorRouteGroups::new_from_soloed () -{ - RouteList rl; - - for (TrackViewList::const_iterator i = _editor->get_track_views().begin(); i != _editor->get_track_views().end(); ++i) { - RouteTimeAxisView* rtv = dynamic_cast (*i); - if (rtv && !rtv->route()->is_master() && rtv->route()->soloed()) { - rl.push_back (rtv->route()); - } - } - - if (rl.empty()) { - return; - } - - run_new_group_dialog (rl); -} - -void -EditorRouteGroups::edit (RouteGroup* g) -{ - RouteGroupDialog d (g, Gtk::Stock::APPLY); - d.do_run (); -} - void EditorRouteGroups::remove_selected () { @@ -381,7 +190,7 @@ EditorRouteGroups::remove_selected () void EditorRouteGroups::button_clicked () { - new_route_group (); + run_new_group_dialog (); } gint @@ -405,7 +214,7 @@ EditorRouteGroups::button_press_event (GdkEventButton* ev) } if (Keyboard::is_context_menu_event (ev)) { - menu(group)->popup (1, ev->time); + _editor->_group_tabs->get_menu(group)->popup (1, ev->time); return true; } @@ -678,7 +487,7 @@ EditorRouteGroups::clear () void EditorRouteGroups::set_session (Session* s) { - EditorComponent::set_session (s); + SessionHandlePtr::set_session (s); if (_session) { _session->route_group_added.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&EditorRouteGroups::add, this, _1), gui_context()); @@ -688,58 +497,10 @@ EditorRouteGroups::set_session (Session* s) groups_changed (); } -struct CollectSorter { - bool operator () (boost::shared_ptr a, boost::shared_ptr b) { - return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor")); - } -}; - -/** Collect all members of a RouteGroup so that they are together in the Editor. - * @param g Group to collect. - */ void -EditorRouteGroups::collect (RouteGroup* g) +EditorRouteGroups::run_new_group_dialog () { - boost::shared_ptr routes = g->route_list (); - routes->sort (CollectSorter ()); - int const N = routes->size (); - - RouteList::iterator i = routes->begin (); - TrackViewList::const_iterator j = _editor->get_track_views().begin(); - - int diff = 0; - int coll = -1; - while (i != routes->end() && j != _editor->get_track_views().end()) { - - RouteTimeAxisView* rtv = dynamic_cast (*j); - if (rtv) { - - boost::shared_ptr r = rtv->route (); - int const k = r->order_key (N_ ("editor")); - - if (*i == r) { - - if (coll == -1) { - coll = k; - diff = N - 1; - } else { - --diff; - } - - r->set_order_key (N_ ("editor"), coll); - - ++coll; - ++i; - - } else { - - r->set_order_key (N_ ("editor"), k + diff); - - } - } - - ++j; - } - - _editor->_routes->sync_order_keys (""); + RouteList rl; + + return _editor->_group_tabs->run_new_group_dialog (rl); } diff --git a/gtk2_ardour/editor_route_groups.h b/gtk2_ardour/editor_route_groups.h index bbc238e3af..402f8e2aed 100644 --- a/gtk2_ardour/editor_route_groups.h +++ b/gtk2_ardour/editor_route_groups.h @@ -19,7 +19,7 @@ #include "editor_component.h" -class EditorRouteGroups : public EditorComponent +class EditorRouteGroups : public EditorComponent, public ARDOUR::SessionHandlePtr { public: EditorRouteGroups (Editor *); @@ -30,10 +30,7 @@ public: return *_display_packer; } - Gtk::Menu* menu (ARDOUR::RouteGroup *); - void clear (); - ARDOUR::RouteGroup* new_route_group () const; private: @@ -64,29 +61,16 @@ private: Columns _columns; - void activate_all (); - void disable_all (); - void subgroup (ARDOUR::RouteGroup *); - void unsubgroup (ARDOUR::RouteGroup *); - void collect (ARDOUR::RouteGroup *); - + void add (ARDOUR::RouteGroup *); void row_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&); void name_edit (const Glib::ustring&, const Glib::ustring&); - void new_from_selection (); - void new_from_rec_enabled (); - void new_from_soloed (); - void edit (ARDOUR::RouteGroup *); void button_clicked (); gint button_press_event (GdkEventButton* ev); - void add (ARDOUR::RouteGroup* group); - void remove_route_group (); void groups_changed (); void property_changed (ARDOUR::RouteGroup*, const PBD::PropertyChange &); - void set_activation (ARDOUR::RouteGroup *, bool); void remove_selected (); - void run_new_group_dialog (const ARDOUR::RouteList&); + void run_new_group_dialog (); - Gtk::Menu* _menu; Glib::RefPtr _model; Glib::RefPtr _selection; Gtk::TreeView _display; diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc index b351c8a51d..308f0c50b8 100644 --- a/gtk2_ardour/editor_routes.cc +++ b/gtk2_ardour/editor_routes.cc @@ -201,7 +201,7 @@ EditorRoutes::EditorRoutes (Editor* e) void EditorRoutes::set_session (Session* s) { - EditorComponent::set_session (s); + SessionHandlePtr::set_session (s); initial_display (); diff --git a/gtk2_ardour/editor_routes.h b/gtk2_ardour/editor_routes.h index fbbfafe54d..07ee8c2629 100644 --- a/gtk2_ardour/editor_routes.h +++ b/gtk2_ardour/editor_routes.h @@ -23,7 +23,7 @@ #include "pbd/signals.h" #include "editor_component.h" -class EditorRoutes : public EditorComponent, public PBD::ScopedConnectionList +class EditorRoutes : public EditorComponent, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr { public: EditorRoutes (Editor *); diff --git a/gtk2_ardour/editor_snapshots.cc b/gtk2_ardour/editor_snapshots.cc index e7bd89f604..3c841774af 100644 --- a/gtk2_ardour/editor_snapshots.cc +++ b/gtk2_ardour/editor_snapshots.cc @@ -54,7 +54,7 @@ EditorSnapshots::EditorSnapshots (Editor* e) void EditorSnapshots::set_session (Session* s) { - EditorComponent::set_session (s); + SessionHandlePtr::set_session (s); redisplay (); } diff --git a/gtk2_ardour/editor_snapshots.h b/gtk2_ardour/editor_snapshots.h index 5563778aa5..00427ef3ec 100644 --- a/gtk2_ardour/editor_snapshots.h +++ b/gtk2_ardour/editor_snapshots.h @@ -23,7 +23,7 @@ #include #include "editor_component.h" -class EditorSnapshots : public EditorComponent +class EditorSnapshots : public EditorComponent, public ARDOUR::SessionHandlePtr { public: EditorSnapshots (Editor *); diff --git a/gtk2_ardour/editor_summary.cc b/gtk2_ardour/editor_summary.cc index b5abe68c3d..c87d914317 100644 --- a/gtk2_ardour/editor_summary.cc +++ b/gtk2_ardour/editor_summary.cc @@ -60,7 +60,7 @@ EditorSummary::EditorSummary (Editor* e) void EditorSummary::set_session (Session* s) { - EditorComponent::set_session (s); + SessionHandlePtr::set_session (s); set_dirty (); diff --git a/gtk2_ardour/editor_summary.h b/gtk2_ardour/editor_summary.h index 2080692a85..cd01bbd946 100644 --- a/gtk2_ardour/editor_summary.h +++ b/gtk2_ardour/editor_summary.h @@ -33,7 +33,7 @@ class Editor; /** Class to provide a visual summary of the contents of an editor window; represents * the whole session as a set of lines, one per region view. */ -class EditorSummary : public CairoWidget, public EditorComponent +class EditorSummary : public CairoWidget, public EditorComponent, public ARDOUR::SessionHandlePtr { public: EditorSummary (Editor *); diff --git a/gtk2_ardour/group_tabs.cc b/gtk2_ardour/group_tabs.cc index 1e537176cc..d69bc7a039 100644 --- a/gtk2_ardour/group_tabs.cc +++ b/gtk2_ardour/group_tabs.cc @@ -33,18 +33,23 @@ using namespace Gtk; using namespace ARDOUR; using Gtkmm2ext::Keyboard; -GroupTabs::GroupTabs (Editor* e) - : EditorComponent (e), - _dragging (0), - _dragging_new_tab (0) +GroupTabs::GroupTabs () + : _menu (0) + , _dragging (0) + , _dragging_new_tab (0) { } +GroupTabs::~GroupTabs () +{ + delete _menu; +} + void GroupTabs::set_session (Session* s) { - EditorComponent::set_session (s); + SessionHandlePtr::set_session (s); if (_session) { _session->RouteGroupChanged.connect (_session_connections, invalidator (*this), boost::bind (&GroupTabs::set_dirty, this), gui_context()); @@ -184,7 +189,7 @@ GroupTabs::on_button_release_event (GdkEventButton* ev) if (!routes.empty()) { if (_dragging_new_tab) { - RouteGroup* g = new_route_group (); + RouteGroup* g = create_and_add_group (); if (g) { for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) { g->add (*i); @@ -280,3 +285,223 @@ GroupTabs::click_to_tab (double c, list::iterator* prev, list::iterato return under; } +Gtk::Menu* +GroupTabs::get_menu (RouteGroup* g) +{ + using namespace Menu_Helpers; + + delete _menu; + + Menu* new_from = new Menu; + MenuList& f = new_from->items (); + f.push_back (MenuElem (_("Selection..."), sigc::mem_fun (*this, &GroupTabs::new_from_selection))); + f.push_back (MenuElem (_("Record Enabled..."), sigc::mem_fun (*this, &GroupTabs::new_from_rec_enabled))); + f.push_back (MenuElem (_("Soloed..."), sigc::mem_fun (*this, &GroupTabs::new_from_soloed))); + + _menu = new Menu; + _menu->set_name ("ArdourContextMenu"); + MenuList& items = _menu->items(); + + items.push_back (MenuElem (_("New..."), hide_return (sigc::mem_fun(*this, &GroupTabs::create_and_add_group)))); + items.push_back (MenuElem (_("New From"), *new_from)); + + if (g) { + items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &GroupTabs::edit_group), g))); + items.push_back (MenuElem (_("Subgroup"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::subgroup), g))); + items.push_back (MenuElem (_("Collect"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::collect), g))); + } + + add_menu_items (_menu, g); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Activate All"), sigc::mem_fun(*this, &GroupTabs::activate_all))); + items.push_back (MenuElem (_("Disable All"), sigc::mem_fun(*this, &GroupTabs::disable_all))); + + return _menu; + +} + +void +GroupTabs::new_from_selection () +{ + RouteList rl = selected_routes (); + if (rl.empty()) { + return; + } + + run_new_group_dialog (rl); +} + +void +GroupTabs::new_from_rec_enabled () +{ + boost::shared_ptr rl = _session->get_routes (); + + RouteList rec_enabled; + + for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { + if ((*i)->record_enabled()) { + rec_enabled.push_back (*i); + } + } + + if (rec_enabled.empty()) { + return; + } + + run_new_group_dialog (rec_enabled); +} + +void +GroupTabs::new_from_soloed () +{ + boost::shared_ptr rl = _session->get_routes (); + + RouteList soloed; + + for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { + if (!(*i)->is_master() && (*i)->soloed()) { + soloed.push_back (*i); + } + } + + if (soloed.empty()) { + return; + } + + run_new_group_dialog (soloed); + +} + +void +GroupTabs::run_new_group_dialog (RouteList const & rl) +{ + RouteGroup* g = new RouteGroup (*_session, ""); + g->set_properties (default_properties ()); + + RouteGroupDialog d (g, Gtk::Stock::NEW); + int const r = d.do_run (); + + switch (r) { + case Gtk::RESPONSE_OK: + case Gtk::RESPONSE_ACCEPT: + _session->add_route_group (g); + for (RouteList::const_iterator i = rl.begin(); i != rl.end(); ++i) { + g->add (*i); + } + break; + default: + delete g; + } +} + +RouteGroup * +GroupTabs::create_and_add_group () const +{ + RouteGroup* g = new RouteGroup (*_session, ""); + + g->set_properties (default_properties ()); + + RouteGroupDialog d (g, Gtk::Stock::NEW); + int const r = d.do_run (); + + if (r != Gtk::RESPONSE_OK) { + delete g; + return 0; + } + + _session->add_route_group (g); + return g; +} + +void +GroupTabs::edit_group (RouteGroup* g) +{ + RouteGroupDialog d (g, Gtk::Stock::APPLY); + d.do_run (); +} + +void +GroupTabs::subgroup (RouteGroup* g) +{ + g->make_subgroup (); +} + +struct CollectSorter { + CollectSorter (std::string const & key) : _key (key) {} + + bool operator () (boost::shared_ptr a, boost::shared_ptr b) { + return a->order_key (_key) < b->order_key (_key); + } + + std::string _key; +}; + +/** Collect all members of a RouteGroup so that they are together in the Editor or Mixer. + * @param g Group to collect. + */ +void +GroupTabs::collect (RouteGroup* g) +{ + boost::shared_ptr group_routes = g->route_list (); + group_routes->sort (CollectSorter (order_key ())); + int const N = group_routes->size (); + + RouteList::iterator i = group_routes->begin (); + boost::shared_ptr routes = _session->get_routes (); + RouteList::const_iterator j = routes->begin (); + + int diff = 0; + int coll = -1; + while (i != group_routes->end() && j != routes->end()) { + + int const k = (*j)->order_key (order_key ()); + + if (*i == *j) { + + if (coll == -1) { + coll = k; + diff = N - 1; + } else { + --diff; + } + + (*j)->set_order_key (order_key (), coll); + + ++coll; + ++i; + + } else { + + (*j)->set_order_key (order_key (), k + diff); + + } + + ++j; + } + + sync_order_keys (); +} + +void +GroupTabs::activate_all () +{ + _session->foreach_route_group ( + sigc::bind (sigc::mem_fun (*this, &GroupTabs::set_activation), true) + ); +} + +void +GroupTabs::disable_all () +{ + _session->foreach_route_group ( + sigc::bind (sigc::mem_fun (*this, &GroupTabs::set_activation), false) + ); +} + +void +GroupTabs::set_activation (RouteGroup* g, bool a) +{ + g->set_active (a, this); +} + diff --git a/gtk2_ardour/group_tabs.h b/gtk2_ardour/group_tabs.h index dbe3174f1b..d5d1fa5afc 100644 --- a/gtk2_ardour/group_tabs.h +++ b/gtk2_ardour/group_tabs.h @@ -31,13 +31,21 @@ class Editor; /** Parent class for tabs which represent route groups as coloured tabs; * Currently used on the left-hand side of the editor and at the top of the mixer. */ -class GroupTabs : public CairoWidget, public EditorComponent +class GroupTabs : public CairoWidget, public ARDOUR::SessionHandlePtr { public: - GroupTabs (Editor *); + GroupTabs (); + virtual ~GroupTabs (); void set_session (ARDOUR::Session *); + /** @param g Route group, or 0. + * @return Menu to be popped up on right-click over the given route group. + */ + Gtk::Menu* get_menu (ARDOUR::RouteGroup* g); + + void run_new_group_dialog (ARDOUR::RouteList const &); + protected: struct Tab { @@ -72,13 +80,23 @@ private: /** @return Size of the widget along the primary axis */ virtual double extent () const = 0; - /** @param g Route group, or 0. - * @return Menu to be popped up on right-click over the given route group. - */ - virtual Gtk::Menu* get_menu (ARDOUR::RouteGroup* g) = 0; - - virtual ARDOUR::RouteGroup* new_route_group () const = 0; - + virtual void add_menu_items (Gtk::Menu *, ARDOUR::RouteGroup *) {} + virtual PBD::PropertyList default_properties () const = 0; + virtual std::string order_key () const = 0; + virtual ARDOUR::RouteList selected_routes () const = 0; + virtual void sync_order_keys () = 0; + + void new_from_selection (); + void new_from_rec_enabled (); + void new_from_soloed (); + ARDOUR::RouteGroup* create_and_add_group () const; + void collect (ARDOUR::RouteGroup *); + void set_activation (ARDOUR::RouteGroup *, bool); + void edit_group (ARDOUR::RouteGroup *); + void subgroup (ARDOUR::RouteGroup *); + void activate_all (); + void disable_all (); + void render (cairo_t *); void on_size_request (Gtk::Requisition *); bool on_button_press_event (GdkEventButton *); @@ -87,6 +105,7 @@ private: Tab * click_to_tab (double, std::list::iterator *, std::list::iterator *); + Gtk::Menu* _menu; std::list _tabs; ///< current list of tabs Tab* _dragging; ///< tab being dragged, or 0 bool _dragging_new_tab; ///< true if we're dragging a new tab diff --git a/gtk2_ardour/mixer_group_tabs.cc b/gtk2_ardour/mixer_group_tabs.cc index a52271d0de..a948fe1b61 100644 --- a/gtk2_ardour/mixer_group_tabs.cc +++ b/gtk2_ardour/mixer_group_tabs.cc @@ -32,9 +32,7 @@ using namespace ARDOUR; using namespace PBD; MixerGroupTabs::MixerGroupTabs (Mixer_UI* m) - : GroupTabs (0), - _mixer (m), - _menu (0) + : _mixer (m) { } @@ -152,74 +150,34 @@ MixerGroupTabs::routes_for_tab (Tab const * t) const return routes; } -Gtk::Menu* -MixerGroupTabs::get_menu (RouteGroup* g) +PropertyList +MixerGroupTabs::default_properties () const { - if (g == 0) { - return 0; - } - - using namespace Menu_Helpers; - - delete _menu; - _menu = new Menu; - - MenuList& items = _menu->items (); - items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &MixerGroupTabs::edit_group), g))); - items.push_back (MenuElem (_("Subgroup"), sigc::bind (sigc::mem_fun (*this, &MixerGroupTabs::make_subgroup), g))); - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Remove"), sigc::bind (sigc::mem_fun (*this, &MixerGroupTabs::remove_group), g))); + PropertyList plist; - return _menu; -} + plist.add (Properties::active, true); + plist.add (Properties::mute, true); + plist.add (Properties::solo, true); + plist.add (Properties::gain, true); + plist.add (Properties::recenable, true); -void -MixerGroupTabs::edit_group (RouteGroup* g) -{ - RouteGroupDialog d (g, Gtk::Stock::APPLY); - d.do_run (); + return plist; } -void -MixerGroupTabs::remove_group (RouteGroup *g) +string +MixerGroupTabs::order_key () const { - _session->remove_route_group (*g); + return X_("signal"); } -void -MixerGroupTabs::make_subgroup (RouteGroup* g) +RouteList +MixerGroupTabs::selected_routes () const { - g->make_subgroup (); + return _mixer->selection().routes; } void -MixerGroupTabs::destroy_subgroup (RouteGroup* g) -{ - g->destroy_subgroup (); -} - -ARDOUR::RouteGroup * -MixerGroupTabs::new_route_group () const +MixerGroupTabs::sync_order_keys () { - PropertyList plist; - - plist.add (Properties::active, true); - plist.add (Properties::mute, true); - plist.add (Properties::solo, true); - plist.add (Properties::gain, true); - plist.add (Properties::recenable, true); - - RouteGroup* g = new RouteGroup (*_session, ""); - g->set_properties (plist); - - RouteGroupDialog d (g, Gtk::Stock::NEW); - int const r = d.do_run (); - - if (r != Gtk::RESPONSE_OK) { - delete g; - return 0; - } - - _session->add_route_group (g); - return g; + _mixer->sync_order_keys (""); } diff --git a/gtk2_ardour/mixer_group_tabs.h b/gtk2_ardour/mixer_group_tabs.h index 272fb9234a..8a2e06bc45 100644 --- a/gtk2_ardour/mixer_group_tabs.h +++ b/gtk2_ardour/mixer_group_tabs.h @@ -34,14 +34,11 @@ private: double extent () const { return _width; } - Gtk::Menu* get_menu (ARDOUR::RouteGroup* g); - ARDOUR::RouteGroup* new_route_group () const; - void edit_group (ARDOUR::RouteGroup *); - void remove_group (ARDOUR::RouteGroup *); - void make_subgroup (ARDOUR::RouteGroup *); - void destroy_subgroup (ARDOUR::RouteGroup *); + PBD::PropertyList default_properties () const; + std::string order_key () const; + ARDOUR::RouteList selected_routes () const; + void sync_order_keys (); Mixer_UI* _mixer; - Gtk::Menu* _menu; }; diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 4d6f7119cc..69e14e2f8f 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -1320,6 +1320,8 @@ Mixer_UI::add_route_group (RouteGroup* group) group_display.set_cursor (group_model->get_path (row), *col, *name_cell, true); } + _group_tabs->set_dirty (); + in_group_row_change = false; }