ApplicationCommandManager


#1

Hi All,

I am tying to use ApplicationCommandManager to dispatch commands to other components on the application window. But I observed that if the target component is not selected the ApplicationCommandManager does not call perform on the component. Is there any way that I can send commands to all the components in application which are ApplicationCommandTarget rather than to the ones that are selected.

-Sarbjit


#2

What do you mean by ‘selected’?

If you registered the target with the manager, you can check that it will get the command using
getFirstCommandTarget() and setFirstCommandTarget() to the specific command.

You should also check that you did returned the command id in the getAllCommands() in the target.


#3

I am sure that I did register the command with the manager. By selected I mean that if the component has focus only then the perform method is invoked on target else it does not invoke the perform method.


#4

I once had an issue like this, it’s because I my manager and target used to be on a separate TopLevelComponents, so when the target was not in focus
it was not active and did not receive commands, the solution was to register the manager as a key listener in the target’s TopLevelComponent like this:

getTopLevelComponent()->addKeyListener(commandManager.getKeyMappings());

#5

Thanks for the reply but still it is not working. Actually I have a document window which is sending command and my target is another document widnow. IS it because of separate windows that I am not getting commands when not in focus?


#6

The ApplicationCommandManager needs to know where to start looking for a suitable target when a command is invoked. By default, it will check for one that has been set via setFirstCommandTarget(), and if one has not been specified, it will call findDefaultComponentTarget(), which starts with what currently has focus.

When it looks at the focused component, it will try to find the first component which implements ApplicationCommandTarget (checking that one before each of its ancestors). If it belongs to a TopLevelWindow, that is obviously where the search will stop (as it’s the top level - there are no components above it). If the target you expect to receive the command lives inside a different TopLevelWindow to the currently focused component, it will never be found by this default behaviour; the search will be taking place in an entirely separate tree of objects.

So, you need to customise this behaviour according to your needs. The first thing to do is decide on how you’d want this search to be started; if you just want to have a fixed starting point (or one which you can change manually when necessary), you can call setFirstCommandTarget(). If you want it to use some kind of logic to decide on where to start for each case, you can override getFirstCommandTarget(), so you can leave it to sort itself out as needed. One simple approach would be to give your manager an array of CommandIDs which should always go to one particular target; if that array contains the current CommandID you’d return that target, otherwise return findDefaultComponentTarget().

Remember that you also must implement getNextCommandTarget() for each target. The stuff above covers the start of the search for a target, whereas this controls how the search progresses from one target to the next. This is therefore another place where you can influence a command’s journey to its target. The ‘default’ thing you’d normally do (as suggested by the docs) is return findFirstTargetParentComponent(). You might want to provide a means of jumping from a target in one window to a suitable one in another. You’d have to be careful that all commands are handled somewhere though if there’s a chance the targets might direct themselves into an infinite loop! I guess you could create some kind of TargetTraverser object which (after getting reset in getFirstCommandTarget()) keeps track of which targets have been visited; each target could then be written to use that traverser to return the next target. That’s probably only worth bothering with if you have an extremely complicated setup though, and if it’s that complex, you’d probably be better off redesigning your program! :wink:

TBH, I think just choosing between a specific target and the default focus search based on command ID is probably the easiest approach to take (going from the information you have given).