summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-07-19 21:47:07 +0000
committerCarl Hetherington <carl@carlh.net>2010-07-19 21:47:07 +0000
commit536384ea4ea7d468363ff5f284a817c42083c3b5 (patch)
treefb5c5762e962c827e047a71945d591b9e5526ba4
parent0cf3e493f98c133359facd7c30a48be19f139e82 (diff)
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
-rw-r--r--gtk2_ardour/editor_component.h6
-rw-r--r--gtk2_ardour/editor_group_tabs.cc55
-rw-r--r--gtk2_ardour/editor_group_tabs.h9
-rw-r--r--gtk2_ardour/editor_locations.cc2
-rw-r--r--gtk2_ardour/editor_locations.h3
-rw-r--r--gtk2_ardour/editor_regions.cc2
-rw-r--r--gtk2_ardour/editor_regions.h2
-rw-r--r--gtk2_ardour/editor_route_groups.cc255
-rw-r--r--gtk2_ardour/editor_route_groups.h22
-rw-r--r--gtk2_ardour/editor_routes.cc2
-rw-r--r--gtk2_ardour/editor_routes.h2
-rw-r--r--gtk2_ardour/editor_snapshots.cc2
-rw-r--r--gtk2_ardour/editor_snapshots.h2
-rw-r--r--gtk2_ardour/editor_summary.cc2
-rw-r--r--gtk2_ardour/editor_summary.h2
-rw-r--r--gtk2_ardour/group_tabs.cc237
-rw-r--r--gtk2_ardour/group_tabs.h37
-rw-r--r--gtk2_ardour/mixer_group_tabs.cc78
-rw-r--r--gtk2_ardour/mixer_group_tabs.h11
-rw-r--r--gtk2_ardour/mixer_ui.cc2
20 files changed, 360 insertions, 373 deletions
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 <list>
-
-#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<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 ("");
}
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<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);
}
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<Gtk::ListStore> _model;
Glib::RefPtr<Gtk::TreeSelection> _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 <gtkmm/treeview.h>
#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<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);
+}
+
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<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
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;
}