X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Froute_group_menu.cc;h=5ccafaec398c70467c9313d65c8943ccd4449126;hb=e653da32c06c00e2ff481f2fc9d2d2de34b5aba0;hp=08d2312415f7fd51661f15bc4d6f4b1c9c31e1b1;hpb=64dc5427e4f5339a16a018692dd94f476c53cae9;p=ardour.git diff --git a/gtk2_ardour/route_group_menu.cc b/gtk2_ardour/route_group_menu.cc index 08d2312415..5ccafaec39 100644 --- a/gtk2_ardour/route_group_menu.cc +++ b/gtk2_ardour/route_group_menu.cc @@ -19,72 +19,182 @@ #include #include + +#include "gtkmm2ext/utils.h" +#include "gtkmm2ext/doi.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" + +#include "pbd/i18n.h" using namespace Gtk; using namespace ARDOUR; +using namespace PBD; -RouteGroupMenu::RouteGroupMenu (Session& s, RouteGroup::Property p) - : _session (s), - _default_properties (p) +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 (); + _subject = s; - items().push_back (MenuElem (_("New group..."), sigc::mem_fun (*this, &RouteGroupMenu::new_group))); - items().push_back (SeparatorElem ()); + /* 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"), sigc::bind (sigc::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 (sigc::bind (sigc::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(), sigc::bind (sigc::mem_fun(*this, &RouteGroupMenu::set_group), rg))); + MenuList& items = _menu->items (); - if (rg == curr) { - static_cast (&items().back())->set_active (); + 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, _default_properties); + if (!_session) { + return; + } + + RouteGroup* g = new RouteGroup (*_session, ""); + RouteGroupDialog* d = new RouteGroupDialog (g, true); - RouteGroupDialog d (g, Gtk::Stock::NEW); - int const r = d.do_run (); + d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::new_group_dialog_finished), d)); + d->present (); +} - if (r == Gtk::RESPONSE_OK) { - _session.add_route_group (g); - set_group (g); +void +RouteGroupMenu::new_group_dialog_finished (int r, RouteGroupDialog* d) +{ + if (r == RESPONSE_OK) { + _session->add_route_group (d->group()); + set_group (d->group()); } else { - delete g; + delete d->group (); + } + + delete_when_idle (d); +} + +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); } }