I’ve been working on a new application, and I created a menu bar for it today based on the code in the Juce demo application. The only significant difference between my application and the Juce demo application was that I separated the menu bar code from the content component code so that both are two independent classes. Well, after I added the menu bar, all the menu items showed up correctly, but they’re all inactive.
I’ve been experimenting for a couple of hours trying to solve this problem, but nothing I’ve tried seems to work. I tried all the obvious solutions. For instance in the method getCommandInfo() I set setActive() to true for every ApplicationCommandInfo object. I called commandStatusChanged() on the ApplicationCommandManager in this method. I tried calling this same method again after all the menus and user interface stuff was built to make it reload the ApplicationCommandInfo objects. But none of this has helped.
Does anyone have any idea what might be causing this behavior? I’m thinking about dumping the ApplicationCommandManager altogether so that I can manually set the active status when adding the items to the menu.
The items will only get enabled if the command manager can find an event target that they could be sent to. So if e.g. none of your UI components have the focus, and if the command manager’s fallback target doesn’t support those commands, then they’ll be deselected. Have a read of the command manager’s help for more info about how it tries to find a suitable target, and then make sure you’ve got one for it.
Thanks for your response. That explained why I was having problems. I had my main content component inherit from the menu bar class, and now, the menus are all active.
My main content component, however, shows a pop-up window sometimes that allows the user to do some configuration tasks, and whenever this popup is showing, the menus become inactivate again. I’m developing on a Mac, and it’s a bit odd to have the menus at the top of the screen deactivated just because you have a popup in front of the main window. So, I’ve tried to work around this by listening for when a user clicks on a menu to open it so that I can close the popup whenever this happens. But I couldn’t figure out how to do this. I tried overriding the PopupMenu’s show() methods, but it seems that those methods aren’t being called (this might be because I’m working with a Mac menu). I also tried listening for when the other windows lost the focus, but these methods aren’t being called when someone clicks on a menu. Do you have any suggestions concerning how I might detect that a user has opened a menu?
I am wondering more generally whether it makes sense to link whether the menus are active to whether a particular component has the focus. On a Mac, the menus aren’t attached to any particular window but rather are at the top of the screen, and an application might have multiple windows. If the menus are linked to one particular window, then they’ll become inactive when a user starts working in a different window, but this is clearly not desirable behavior, no?
Not sure I follow you… every app I’ve ever used changes/disables the menu items according to what the app is doing at any particular moment - that makes perfect sense.
If you want your commands to always be enabled regardless of what the user is doing, then you need to put them inside a command target object that is always accessible to the command manager (i.e. with setFirstCommandTarget()). If you put them inside a window, then it makes perfect sense that they’ll only be available when the window is focused.
Alternatively, you could make your other windows implement getNextCommandTarget() to defer to your main window for commands they don’t understand. But trying to hack around with the menus to make it do what you want is really missing the point.
Okay. I misunderstood your first mail. I thought you were implying that application command targets had to be visual components, and this didn’t make sense to me. But the tip you gave me in your second response to use setFirstCommandTarget() solved the problem I was having, and now that I understand better how the application command manager and targets work I like this structure quite a lot actually. Thanks for your help!