Re: UIManager and dynamic menus



On 4/4/07, Paul Davis <paul linuxaudiosystems com> wrote:
On Wed, 2007-04-04 at 11:27 -0500, Paul Davis wrote:
> Hi list,
>
> I've been working with UIManager quite a bit lately and I've come up
> against two issues that are fairly related.
>
> What is the 'UIManager' way of having dynamic menus. I need this when
> adding a list of recent documents to the File menu or when creating a
> list of windows for a View menu.
>
> I've looked at the merge operations presented by UIManager, but they
> appear to be a bit heavier weight than I would expect for something
> like this.
>
> If this merge/unmerge functionality is the way to go, does someone
> have a good example of doing this.  I'm fairly certain I get the
> basics, but having a good example is always nice too.

if one of us hasn't been there already, i'm not sure what we would do :)

personally, i have found it *extremely* hard to use the UIManager for
dynamic menus. the problems have been subtle, and i gave up. my approach
now is to use UIManager for the static menus (including a dangling menu
item where the dynamic one will be "hung"), and then do this:

Gtk::Menu*
SequencerUI::get_trigger_submenu ()
{
        Widget* foo = ActionManager::get_widget ("/Main/Triggers/Edit");
        Gtk::MenuItem* foomi = dynamic_cast<MenuItem*>(foo);
        return foomi->get_submenu ();
}

after that, i use the very nice Menu_Helpers function to rebuild the
item list for the return menu (including a clear):

int
SequencerUI::add_trigger_item (Trigger &trigger)
{
        using namespace Menu_Helpers;
        Gtk::Menu* trigger_menu = get_trigger_submenu();
        MenuList& trigger_list = trigger_menu->items();

        trigger_list.push_back (MenuElem (trigger.name().c_str(), bind (mem_fun
(*this, &SequencerUI::edit_trigger), &trigger)));
        trigger_list.back().set_data ("trigger_ptr", &trigger);

        return 0;
}

void
SequencerUI::rebuild_trigger_submenu ()
{
        using namespace Menu_Helpers;
        Gtk::Menu* trigger_menu = get_trigger_submenu();
        MenuList& items = trigger_menu->items();

        items.clear ();

        _sequencer->foreach_trigger (*this, &SequencerUI::add_trigger_item);

        trigger_menu->show_all ();
}

i just couldn't figure out a way to smoothly accomplish the same thing
with readable and grokkable code.

--p




Both of those ideas are similar to ones I had as well.  Neither of
which is as pretty as I was hoping for.

I'm thinking about making something like a UIManagerMerge that will
accept actions and ui merges and automatically demerge them when it
gets destroyed.

Looking harder at the UIManager API, I'm pretty certain adding bits to
the UIManager will revolve around the UIManager::add_ui() method. But
I'm a bit uncertain how to manage the paths.

For me, I'll be using this from within a plugin context, so each
plugin will get handed a UIManagerMerge object, and add what it needs
to the ui.  Then when the plugin goes away, all of its menu stuff goes
away cleanly as well.  The only thing I can't get around is the path
issue.  As it is, I'd have to make each of my plugins 'know' the path
through the ui stuff.  I did think about making it so that the
UIManagerMerge object could get constructed with a base path, so that
all additions get put below a certain path, but that ixnay's the
ability to add to multiple menus in the UI.

I'll work on fleshing this out a bit more, if anyone else has some
insights, feel free to shout out.  I'll post some code when I get to
that point.

Thanks,
Paul Davis



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]