X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Froute_group_menu.cc;h=63577392a779ab5b39dd48c3eca61754d3db04e6;hb=95a61717faa4b427be0e7821ee91f7df81065815;hp=42d09ab9602f631f539996080d276637a5083c1d;hpb=7b2975244165b4ffd1dcf4080c1be4c8dcbc6708;p=ardour.git diff --git a/gtk2_ardour/route_group_menu.cc b/gtk2_ardour/route_group_menu.cc index 42d09ab960..63577392a7 100644 --- a/gtk2_ardour/route_group_menu.cc +++ b/gtk2_ardour/route_group_menu.cc @@ -19,11 +19,17 @@ #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; @@ -31,73 +37,124 @@ using namespace PBD; RouteGroupMenu::RouteGroupMenu (Session* s, PropertyList* plist) : SessionHandlePtr (s) + , _menu (0) , _default_properties (plist) , _inhibit_group_selected (false) - , _selected_route_group (0) { - rebuild (0); + } RouteGroupMenu::~RouteGroupMenu() { - delete _default_properties; + 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; - _selected_route_group = curr; + _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; - items().clear (); + delete _menu; - items().push_back (MenuElem (_("New group..."), sigc::mem_fun (*this, &RouteGroupMenu::new_group))); - items().push_back (SeparatorElem ()); + /* 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; - RadioMenuItem::Group group; - items().push_back (RadioMenuElem (group, _("No group"), sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::set_group), (RouteGroup *) 0))); + MenuList& items = _menu->items (); + + items.push_back (MenuElem (_("New Group..."), sigc::mem_fun (*this, &RouteGroupMenu::new_group))); + items.push_back (SeparatorElem ()); - if (curr == 0) { - static_cast (&items().back())->set_active (); + RadioMenuItem::Group group; + 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), i, (RouteGroup *) 0)); + + if (groups.size() == 1 && *groups.begin() == 0) { + i->set_active (); + } else if (groups.size() > 1) { + i->set_inconsistent (); } if (_session) { - _session->foreach_route_group (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::add_item), curr, &group)); + _session->foreach_route_group (sigc::bind (sigc::mem_fun (*this, &RouteGroupMenu::add_item), groups, &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), i, 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) +RouteGroupMenu::set_group (Gtk::RadioMenuItem* e, RouteGroup* g) { - if (g == _selected_route_group) { - /* cut off the signal_toggled that GTK emits for an option that is being un-selected - when a new option is being selected instead - */ + if (_inhibit_group_selected) { return; } - - if (!_inhibit_group_selected) { - GroupSelected (g); + if (e && !e->get_active()) { + return; } - _selected_route_group = g; + 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 @@ -108,15 +165,39 @@ RouteGroupMenu::new_group () } RouteGroup* g = new RouteGroup (*_session, ""); - g->apply_changes (*_default_properties); + 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 (0, 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); } }