App commands in menubar disabled?


#1

I’ve tried making my MenuBarModel using app commands, and all of the menu items are disabled!

My main ApplicationCommandTarget is NOT a Component; i have a class called AppBody which is just a normal class to hold the body of the app. The reason for this is that it makes it far easier to make the app transfer to a JuceAudioPlugin. Keeping the app body code and user data in the MainComponent is a problem here obviously because the component may not actually exist.

My JUCEApplication subclass creates the AppBody in its initialise method, and the MainComponent (and MainAppWindow) gets a reference to this. MainComponent is a MenuBarModel, and also is responsible for creating the ApplicationCommandManager like the demo app does.

MainAppWindow constructor does this (takes a reference to the main AppBody)…

   MainComponent* contentComp = new MainComponent (appBody); // gives it reference to AppBody
   setContentComponent (contentComp);
   setMenuBar (contentComp);

And then the MainComponent constructor does this at the beginning…

   commandManager = new ApplicationCommandManager;
   commandManager->registerAllCommandsForTarget (&appBody);
   commandManager->registerAllCommandsForTarget (JUCEApplication::getInstance ());
   addKeyListener (commandManager->getKeyMappings ());

I doubt these bits of code reveal why it’s not working. Perhaps it’s because the AppBody is not a Component and thus not part of the tree? I had a quick look thru some classes to see what might cause a menu item to be disabled but didn’t have much luck. Maybe I need to subclass the ApplicationCommandManager to start looking at the AppBody for target… but surely the Quit command i have registered from the JUCEApplication would still work?

I’m a bit confused, I would expect that the command manager would be able to look at targets that it has registered commands for if it can’t find any targets from component tree analysis…


#2

Yes, it’s probably because it can’t find the target - if you were using a component as a target then it’d find it automatically, but if not, then you’ll probably need to override the ApplicationCommandManager::getFirstCommandTarget() method to make sure your target gets picked up.

(The registration call doesn’t actually keep any reference to the target that you pass in, it just uses the target to get a list of commands)


#3

Is this also an explanation of why the QUIT is also disabled? I would have thought that this command would still be findable?


#4

subclassed it, and it works fine (just instantiating my new ApplicationCommandManager subclass with a pointer to the AppBody to return as the first target). Somehow this allows the quit command to be active too.

Perhaps it would be nice to have a simple ‘setFirstTarget(ApplicationCommandTarget*)’ function to negate the need for subclassing just for a single function?


#5

i had the same problem haydxn… adding a first target make the Quit now be active… strange tho, jules told me that he have done the same things as us but in his version, the Quit is still enable… weirdo


#6

[quote=“haydxn”]subclassed it, and it works fine (just instantiating my new ApplicationCommandManager subclass with a pointer to the AppBody to return as the first target). Somehow this allows the quit command to be active too.

Perhaps it would be nice to have a simple ‘setFirstTarget(ApplicationCommandTarget*)’ function to negate the need for subclassing just for a single function?[/quote]

Yes, I should probably add a setFirstTarget function, that’d make it easier in lots of cases.

And for the quit thing, I think the problem is that if no target is found, it doesn’t add the JUCEApplication object as its last resort target. You can fix it by changing the last line of ApplicationCommandManager::findDefaultComponentTarget() to be

return JUCEApplication::getInstance();

instead of returning 0, and also tweaking this method:

[code]ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const CommandID commandID,
ApplicationCommandInfo& upToDateInfo)
{
ApplicationCommandTarget* target = getFirstCommandTarget();

if (target == 0)
    target = JUCEApplication::getInstance();

if (target != 0)
    target = target->getTargetForCommand (commandID);

if (target != 0)
    target->getCommandInfo (commandID, upToDateInfo);

return target;

}
[/code]


#7