X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Froute_group_menu.cc;h=c50a18e3cf11619aeb78af0c77331a1262dd4d87;hb=92e5a13fd41eba37a2634caf921606b7d915c557;hp=e42cdedfac1d51b9c489e5322b5698aa5210140c;hpb=7a4f1b9cf685aa5b6288b87c02d0f25397f6cd3a;p=ardour.git diff --git a/gtk2_ardour/route_group_menu.cc b/gtk2_ardour/route_group_menu.cc index e42cdedfac..c50a18e3cf 100644 --- a/gtk2_ardour/route_group_menu.cc +++ b/gtk2_ardour/route_group_menu.cc @@ -1,71 +1,189 @@ +/* + Copyright (C) 2009 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + #include #include +#include "gtkmm2ext/utils.h" #include "ardour/session.h" #include "ardour/route_group.h" +#include "ardour/route.h" #include "route_group_menu.h" #include "route_group_dialog.h" #include "i18n.h" using namespace Gtk; using namespace ARDOUR; +using namespace PBD; -RouteGroupMenu::RouteGroupMenu (Session& s) - : _session (s) +RouteGroupMenu::RouteGroupMenu (Session* s, PropertyList* plist) + : SessionHandlePtr (s) + , _menu (0) + , _default_properties (plist) + , _inhibit_group_selected (false) { - rebuild (0); + } +RouteGroupMenu::~RouteGroupMenu() +{ + delete _menu; + delete _default_properties; +} + +/** @param s Routes to operate on */ void -RouteGroupMenu::rebuild (RouteGroup* curr) +RouteGroupMenu::build (WeakRouteList const & s) { + assert (!s.empty ()); + using namespace Menu_Helpers; - - items().clear (); - items().push_back (MenuElem (_("New group..."), mem_fun (*this, &RouteGroupMenu::new_group))); - items().push_back (SeparatorElem ()); + _subject = s; + + /* FInd all the route groups that our subjects are members of */ + std::set groups; + for (WeakRouteList::const_iterator i = _subject.begin (); i != _subject.end(); ++i) { + boost::shared_ptr r = i->lock (); + if (r) { + groups.insert (r->route_group ()); + } + } + + _inhibit_group_selected = true; + + delete _menu; + + /* Note: don't use manage() here, otherwise if our _menu object is attached as a submenu + and its parent is then destroyed, our _menu object will be deleted and we'll have no + way of knowing about it. Without manage(), when the above happens our _menu's gobject + will be destroyed and its value set to 0, so we know. + */ + _menu = new Menu; + + MenuList& items = _menu->items (); + + items.push_back (MenuElem (_("New Group..."), sigc::mem_fun (*this, &RouteGroupMenu::new_group))); + items.push_back (SeparatorElem ()); RadioMenuItem::Group group; - items().push_back (RadioMenuElem (group, _("No group"), bind (mem_fun (*this, &RouteGroupMenu::set_group), (RouteGroup *) 0))); + items.push_back (RadioMenuElem (group, _("No Group"))); + RadioMenuItem* i = static_cast (&items.back ()); + i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), (RouteGroup *) 0)); + + if (groups.size() == 1 && *groups.begin() == 0) { + i->set_active (); + } else if (groups.size() > 1) { + i->set_inconsistent (); + } - if (curr == 0) { - static_cast (&items().back())->set_active (); + if (_session) { + _session->foreach_route_group (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::add_item), groups, &group)); } - - _session.foreach_route_group (bind (mem_fun (*this, &RouteGroupMenu::add_item), curr, &group)); + + _inhibit_group_selected = false; } +/** @param rg Route group to add. + * @param groups Active route groups (may included 0 for `no group') + * @param group Radio item group to add radio items to. + */ void -RouteGroupMenu::add_item (RouteGroup* rg, RouteGroup* curr, RadioMenuItem::Group* group) +RouteGroupMenu::add_item (RouteGroup* rg, std::set const & groups, RadioMenuItem::Group* group) { using namespace Menu_Helpers; - items().push_back (RadioMenuElem (*group, rg->name(), bind (mem_fun(*this, &RouteGroupMenu::set_group), rg))); - - if (rg == curr) { - static_cast (&items().back())->set_active (); - } + MenuList& items = _menu->items (); + + items.push_back (RadioMenuElem (*group, rg->name())); + RadioMenuItem* i = static_cast (&items.back ()); + i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), rg)); + + if (groups.size() == 1 && *groups.begin() == rg) { + /* there's only one active group, and it's this one */ + i->set_active (); + } else if (groups.size() > 1) { + /* there are >1 active groups */ + i->set_inconsistent (); + } } +/** Called when a group is selected from the menu. + * @param Group, or 0 for none. + */ void RouteGroupMenu::set_group (RouteGroup* g) { - GroupSelected (g); -} + if (_inhibit_group_selected) { + return; + } + for (WeakRouteList::const_iterator i = _subject.begin(); i != _subject.end(); ++i) { + boost::shared_ptr r = i->lock (); + if (!r || r->route_group () == g) { + /* lock of weak_ptr failed, or the group for this route is already right */ + continue; + } + + if (g) { + g->add (r); + } else { + if (r->route_group ()) { + r->route_group()->remove (r); + } + } + } +} void RouteGroupMenu::new_group () { - RouteGroup* g = new RouteGroup (_session, "", RouteGroup::Active); + if (!_session) { + return; + } - RouteGroupDialog d (g, Gtk::Stock::NEW); - int const r = d.do_run (); + RouteGroup* g = new RouteGroup (*_session, ""); + g->apply_changes (*_default_properties); - if (r == Gtk::RESPONSE_OK) { - _session.add_route_group (g); - set_group (g); - } else { + RouteGroupDialog d (g, true); + + if (d.do_run ()) { delete g; + } else { + _session->add_route_group (g); + set_group (g); + } +} + +Gtk::Menu * +RouteGroupMenu::menu () +{ + /* Our menu's gobject can be 0 if it was attached as a submenu whose + parent was subsequently deleted. + */ + assert (_menu && _menu->gobj()); + return _menu; +} + +void +RouteGroupMenu::detach () +{ + if (_menu && _menu->gobj ()) { + Gtkmm2ext::detach_menu (*_menu); } }