ardour
route_group_menu.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include <gtkmm/menu.h>
21 #include <gtkmm/stock.h>
22 #include "gtkmm2ext/utils.h"
23 #include "ardour/session.h"
24 #include "ardour/route_group.h"
25 #include "ardour/route.h"
26 #include "route_group_menu.h"
27 #include "route_group_dialog.h"
28 #include "i18n.h"
29 
30 using namespace Gtk;
31 using namespace ARDOUR;
32 using namespace PBD;
33 
35  : SessionHandlePtr (s)
36  , _menu (0)
37  , _default_properties (plist)
38  , _inhibit_group_selected (false)
39 {
40 
41 }
42 
44 {
45  delete _menu;
46  delete _default_properties;
47 }
48 
50 void
52 {
53  assert (!s.empty ());
54 
55  using namespace Menu_Helpers;
56 
57  _subject = s;
58 
59  /* FInd all the route groups that our subjects are members of */
60  std::set<RouteGroup*> groups;
61  for (WeakRouteList::const_iterator i = _subject.begin (); i != _subject.end(); ++i) {
62  boost::shared_ptr<Route> r = i->lock ();
63  if (r) {
64  groups.insert (r->route_group ());
65  }
66  }
67 
69 
70  delete _menu;
71 
72  /* Note: don't use manage() here, otherwise if our _menu object is attached as a submenu
73  and its parent is then destroyed, our _menu object will be deleted and we'll have no
74  way of knowing about it. Without manage(), when the above happens our _menu's gobject
75  will be destroyed and its value set to 0, so we know.
76  */
77  _menu = new Menu;
78 
79  MenuList& items = _menu->items ();
80 
81  items.push_back (MenuElem (_("New Group..."), sigc::mem_fun (*this, &RouteGroupMenu::new_group)));
82  items.push_back (SeparatorElem ());
83 
84  RadioMenuItem::Group group;
85  items.push_back (RadioMenuElem (group, _("No Group")));
86  RadioMenuItem* i = static_cast<RadioMenuItem *> (&items.back ());
87  i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), (RouteGroup *) 0));
88 
89  if (groups.size() == 1 && *groups.begin() == 0) {
90  i->set_active ();
91  } else if (groups.size() > 1) {
92  i->set_inconsistent ();
93  }
94 
95  if (_session) {
96  _session->foreach_route_group (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::add_item), groups, &group));
97  }
98 
100 }
101 
106 void
107 RouteGroupMenu::add_item (RouteGroup* rg, std::set<RouteGroup*> const & groups, RadioMenuItem::Group* group)
108 {
109  using namespace Menu_Helpers;
110 
111  MenuList& items = _menu->items ();
112 
113  items.push_back (RadioMenuElem (*group, rg->name()));
114  RadioMenuItem* i = static_cast<RadioMenuItem*> (&items.back ());
115  i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), rg));
116 
117  if (groups.size() == 1 && *groups.begin() == rg) {
118  /* there's only one active group, and it's this one */
119  i->set_active ();
120  } else if (groups.size() > 1) {
121  /* there are >1 active groups */
122  i->set_inconsistent ();
123  }
124 }
125 
129 void
131 {
133  return;
134  }
135 
136  for (WeakRouteList::const_iterator i = _subject.begin(); i != _subject.end(); ++i) {
137  boost::shared_ptr<Route> r = i->lock ();
138  if (!r || r->route_group () == g) {
139  /* lock of weak_ptr failed, or the group for this route is already right */
140  continue;
141  }
142 
143  if (g) {
144  g->add (r);
145  } else {
146  if (r->route_group ()) {
147  r->route_group()->remove (r);
148  }
149  }
150  }
151 }
152 
153 void
155 {
156  if (!_session) {
157  return;
158  }
159 
160  RouteGroup* g = new RouteGroup (*_session, "");
162 
163  RouteGroupDialog d (g, true);
164 
165  if (d.do_run ()) {
166  delete g;
167  } else {
169  set_group (g);
170  }
171 }
172 
173 Gtk::Menu *
175 {
176  /* Our menu's gobject can be 0 if it was attached as a submenu whose
177  parent was subsequently deleted.
178  */
179  assert (_menu && _menu->gobj());
180  return _menu;
181 }
182 
183 void
185 {
186  if (_menu && _menu->gobj ()) {
188  }
189 }
void add_route_group(RouteGroup *)
Definition: ardour_ui.h:130
void add_item(ARDOUR::RouteGroup *, std::set< ARDOUR::RouteGroup * > const &, Gtk::RadioMenuItem::Group *)
void build(ARDOUR::WeakRouteList const &)
#define _(Text)
Definition: i18n.h:11
bool _inhibit_group_selected
virtual bool apply_changes(PropertyBase const &)
Definition: stateful.cc:337
void foreach_route_group(boost::function< void(RouteGroup *)> f)
Definition: session.h:510
PBD::PropertyList * _default_properties
int remove(boost::shared_ptr< Route >)
Definition: route_group.cc:161
Definition: amp.h:29
Gtk::Menu * _menu
Gtk::Menu * menu()
RouteGroup * route_group() const
std::string name() const
ARDOUR::WeakRouteList _subject
std::list< boost::weak_ptr< Route > > WeakRouteList
Definition: types.h:533
Definition: debug.h:30
int add(boost::shared_ptr< Route >)
Definition: route_group.cc:130
RouteGroupMenu(ARDOUR::Session *, PBD::PropertyList *)
LIBGTKMM2EXT_API void detach_menu(Gtk::Menu &)
Definition: utils.cc:361
void set_group(ARDOUR::RouteGroup *)
ARDOUR::Session * _session