Tweak group tabs class hierarchy and offer the same menu in both editor and mixer...
authorCarl Hetherington <carl@carlh.net>
Mon, 19 Jul 2010 21:47:07 +0000 (21:47 +0000)
committerCarl Hetherington <carl@carlh.net>
Mon, 19 Jul 2010 21:47:07 +0000 (21:47 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@7441 d708f5d6-7413-0410-9779-e7cbd77b26cf

20 files changed:
gtk2_ardour/editor_component.h
gtk2_ardour/editor_group_tabs.cc
gtk2_ardour/editor_group_tabs.h
gtk2_ardour/editor_locations.cc
gtk2_ardour/editor_locations.h
gtk2_ardour/editor_regions.cc
gtk2_ardour/editor_regions.h
gtk2_ardour/editor_route_groups.cc
gtk2_ardour/editor_route_groups.h
gtk2_ardour/editor_routes.cc
gtk2_ardour/editor_routes.h
gtk2_ardour/editor_snapshots.cc
gtk2_ardour/editor_snapshots.h
gtk2_ardour/editor_summary.cc
gtk2_ardour/editor_summary.h
gtk2_ardour/group_tabs.cc
gtk2_ardour/group_tabs.h
gtk2_ardour/mixer_group_tabs.cc
gtk2_ardour/mixer_group_tabs.h
gtk2_ardour/mixer_ui.cc

index 5b4f7e15d8ebe2a663b9305abb77cc83ebe2e411..f6816c56080776d3e5472cf41700005a26712281 100644 (file)
 #ifndef __ardour_gtk_editor_component_h__
 #define __ardour_gtk_editor_component_h__
 
-#include <list>
-
-#include "ardour/session_handle.h"
-
 class Editor;
 
-class EditorComponent : public ARDOUR::SessionHandlePtr
+class EditorComponent
 {
 public:
        EditorComponent (Editor *);
index 04f61aaeef42d6447dd8ec922d26883c335bf47a..ccf95b797f65f21a96e58f35bdb7654bd7df66a2 100644 (file)
 #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<RouteTimeAxisView*> (*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 ("");
 }
index 4dc447da1796f7621d49f323db8fd6cc0051f593..6d2b5417476a6c64eff4c750392513e41b67ecdb 100644 (file)
@@ -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 ();
 };
index d4117b86b03a39c1633c2d879e9c16016f0573fb..c74a97fc994fb1cc624f5e9cf701fd3ef4082760 100644 (file)
@@ -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);
 }
 
index 6d4d3128e45531212aa9b94a1d13ee2b7222282c..414a57ee7dc382ba20812832ae117c952040b428 100644 (file)
@@ -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 *);
index 1b8e07a28bcb092cf6d8756b747fb7dcbc44fd19..1acb5805833fb21526e30c6fd53ec500f49b50d1 100644 (file)
@@ -157,7 +157,7 @@ EditorRegions::EditorRegions (Editor* e)
 void
 EditorRegions::set_session (ARDOUR::Session* s)
 {
-       EditorComponent::set_session (s);
+       SessionHandlePtr::set_session (s);
        redisplay ();
 }
 
index b17699e9e6482d8cf0112e2deb951ce01fb6521a..4ccb91588bffc5ddfbd2b806cd65f08ba7867d39 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "editor_component.h"
 
-class EditorRegions : public EditorComponent
+class EditorRegions : public EditorComponent, public ARDOUR::SessionHandlePtr
 {
 public:
        EditorRegions (Editor *);
index c30132a3b883ab4d4537be7e9080b696c7f0d5c7..b66fa753da642f63847e12af4d78e2b8a920e5a1 100644 (file)
@@ -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<RouteTimeAxisView*> (*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<RouteTimeAxisView*> (*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<RouteTimeAxisView*> (*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<Route> a, boost::shared_ptr<Route> 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<RouteList> 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<RouteTimeAxisView*> (*j);
-               if (rtv) {
-
-                       boost::shared_ptr<Route> 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);
 }
index bbc238e3af2c778c36d468392244cfb8031b2f59..402f8e2aed5f9644837179456fdb0af75dbdc3ce 100644 (file)
@@ -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<Gtk::ListStore> _model;
        Glib::RefPtr<Gtk::TreeSelection> _selection;
        Gtk::TreeView _display;
index b351c8a51dd518d51d5e761de5c8cdf52c40b2b2..308f0c50b81d6266b4dd328c3984466e66d29a1b 100644 (file)
@@ -201,7 +201,7 @@ EditorRoutes::EditorRoutes (Editor* e)
 void
 EditorRoutes::set_session (Session* s)
 {
-       EditorComponent::set_session (s);
+       SessionHandlePtr::set_session (s);
 
        initial_display ();
 
index fbbfafe54d319b80c9a8711a09189f28868648c7..07ee8c262975b734b60b939188f3852d2f6e6b30 100644 (file)
@@ -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 *);
index e7bd89f6043235eecfbbc2651cd4bb814e8dc325..3c841774af2888bbe10ad21fb50c55e6f20e3e14 100644 (file)
@@ -54,7 +54,7 @@ EditorSnapshots::EditorSnapshots (Editor* e)
 void
 EditorSnapshots::set_session (Session* s)
 {
-       EditorComponent::set_session (s);
+       SessionHandlePtr::set_session (s);
 
        redisplay ();
 }
index 5563778aa5f3af69596b9cc72a1aeaeafb6c78f4..00427ef3ec8058d448cdf78e9af2998b80b04917 100644 (file)
@@ -23,7 +23,7 @@
 #include <gtkmm/treeview.h>
 #include "editor_component.h"
 
-class EditorSnapshots : public EditorComponent
+class EditorSnapshots : public EditorComponent, public ARDOUR::SessionHandlePtr
 {
 public:
        EditorSnapshots (Editor *);
index b5abe68c3d9393aca7377eac259d5e73fd979e69..c87d91431733326446c6f7e0c6c33425264fad8a 100644 (file)
@@ -60,7 +60,7 @@ EditorSummary::EditorSummary (Editor* e)
 void
 EditorSummary::set_session (Session* s)
 {
-       EditorComponent::set_session (s);
+       SessionHandlePtr::set_session (s);
 
        set_dirty ();
 
index 2080692a858a62db7f7993e094992f9e035fb224..cd01bbd9464360a11509eccd9ac8c1bae38f5887 100644 (file)
@@ -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 *);
index 1e537176cc399a2245607aeb8f509bfb7eb08d22..d69bc7a039ef8a93279f046448f59a60c1187e74 100644 (file)
@@ -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<Tab>::iterator* prev, list<Tab>::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<RouteList> 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<RouteList> 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<Route> a, boost::shared_ptr<Route> 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<RouteList> 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<RouteList> 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);
+}
+       
index dbe3174f1b2129551299bda49705f9a12a06eb13..d5d1fa5afcf5471bf246321fe075102e5de24755 100644 (file)
@@ -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<Tab>::iterator *, std::list<Tab>::iterator *);
 
+       Gtk::Menu* _menu;
        std::list<Tab> _tabs; ///< current list of tabs
        Tab* _dragging; ///< tab being dragged, or 0
        bool _dragging_new_tab; ///< true if we're dragging a new tab
index a52271d0de9543b7956ef38aaa0262fbc0ad6257..a948fe1b61c31dbd1e26c2cbaa8a3821ab31c81e 100644 (file)
@@ -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 ("");
 }
index 272fb9234aa8bc04a1eb8d7a3f5db7976f60025c..8a2e06bc45f609dba5534dfb6b5b60a31515b2f4 100644 (file)
@@ -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;
 };
index 4d6f7119cc72b9ac5528a7ed7a1de675165aee5c..69e14e2f8f1e6eada7f655aa2b8f2b8a26841611 100644 (file)
@@ -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;
 }