internal bool DispatchCommandFromAccel (object commandId, object dataItem, object initialTarget)
{
// Dispatches a command that has been fired by an accelerator.
// The difference from a normal dispatch is that there may
// be several commands bound to the same accelerator, and in
// this case it will execute the one that is enabled.
// If the original key has been modified
// by a CommandUpdate handler, it won't work. That's a limitation,
// but checking all possible commands would be too slow.
Command cmd = GetCommand (commandId);
if (cmd == null)
return false;
string accel = cmd.AccelKey;
KeyBinding binding;
if (accel == null || !KeyBinding.TryParse (accel, out binding))
return DispatchCommand (commandId, dataItem, initialTarget, CommandSource.Keybinding);
List<Command> list = bindings.Commands (binding);
if (list == null || list.Count == 1) {
// The command is not overloaded, so it can be handled normally.
return DispatchCommand (commandId, dataItem, initialTarget, CommandSource.Keybinding);
}
CommandTargetRoute targetChain = new CommandTargetRoute (initialTarget);
// Get the accelerator used to fire the command and make sure it has not changed.
CommandInfo accelInfo = GetCommandInfo (commandId, targetChain);
bool res = DispatchCommand (commandId, accelInfo.DataItem, initialTarget, CommandSource.Keybinding);
// If the accelerator has changed, we can't handle overloading.
if (res || accel != accelInfo.AccelKey)
return res;
// Execution failed. Now try to execute alternate commands
// bound to the same key.
for (int i = 0; i < list.Count; i++) {
if (list[i].Id == commandId) // already handled above.
continue;
CommandInfo cinfo = GetCommandInfo (list[i].Id, targetChain);
if (cinfo.AccelKey != accel) // Key changed by a handler, just ignore the command.
continue;
if (DispatchCommand (list[i].Id, cinfo.DataItem, initialTarget, CommandSource.Keybinding))
return true;
}
return false;
}