| /******************************************************************************* |
| * Copyright (c) 2004, 2015 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.commands; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import org.eclipse.core.commands.Command; |
| import org.eclipse.core.commands.CommandManager; |
| import org.eclipse.core.commands.IHandler; |
| import org.eclipse.core.commands.contexts.ContextManager; |
| import org.eclipse.core.commands.contexts.ContextManagerEvent; |
| import org.eclipse.core.commands.contexts.IContextManagerListener; |
| import org.eclipse.e4.core.commands.internal.HandlerServiceImpl; |
| import org.eclipse.jface.bindings.Binding; |
| import org.eclipse.jface.bindings.BindingManager; |
| import org.eclipse.jface.bindings.BindingManagerEvent; |
| import org.eclipse.jface.bindings.IBindingManagerListener; |
| import org.eclipse.jface.bindings.Scheme; |
| import org.eclipse.jface.bindings.TriggerSequence; |
| import org.eclipse.jface.bindings.keys.ParseException; |
| import org.eclipse.ui.commands.CommandManagerEvent; |
| import org.eclipse.ui.commands.ICategory; |
| import org.eclipse.ui.commands.ICommand; |
| import org.eclipse.ui.commands.ICommandManager; |
| import org.eclipse.ui.commands.ICommandManagerListener; |
| import org.eclipse.ui.commands.IKeyConfiguration; |
| import org.eclipse.ui.internal.handlers.LegacyHandlerWrapper; |
| import org.eclipse.ui.internal.keys.SchemeLegacyWrapper; |
| import org.eclipse.ui.internal.util.Util; |
| import org.eclipse.ui.keys.KeySequence; |
| import org.eclipse.ui.keys.KeyStroke; |
| |
| /** |
| * Provides support for the old <code>ICommandManager</code> interface. |
| * |
| * @since 3.1 |
| */ |
| public final class CommandManagerLegacyWrapper implements ICommandManager, |
| org.eclipse.core.commands.ICommandManagerListener, IBindingManagerListener, IContextManagerListener { |
| |
| /** |
| * Whether commands should print out information about which handlers are being |
| * executed. Change this value if you want console output on command execution. |
| */ |
| public static boolean DEBUG_COMMAND_EXECUTION = false; |
| |
| /** |
| * Whether commands should print out information about handler changes. Change |
| * this value if you want console output when commands change handlers. |
| */ |
| public static boolean DEBUG_HANDLERS = false; |
| |
| /** |
| * Which command should print out debugging information. Change this value if |
| * you want to only here when a command with a particular identifier changes its |
| * handler. |
| */ |
| public static String DEBUG_HANDLERS_COMMAND_ID = null; |
| |
| static boolean validateKeySequence(KeySequence keySequence) { |
| if (keySequence == null) { |
| return false; |
| } |
| List<KeyStroke> keyStrokes = keySequence.getKeyStrokes(); |
| int size = keyStrokes.size(); |
| if (size == 0 || size > 4 || !keySequence.isComplete()) { |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * The JFace binding machine that provides binding support for this workbench |
| * mutable command manager. This value will never be <code>null</code>. |
| * |
| * @since 3.1 |
| */ |
| private final BindingManager bindingManager; |
| |
| /** |
| * The command manager that provides functionality for this workbench command |
| * manager. This value will never be <code>null</code>. |
| * |
| * @since 3.1 |
| */ |
| private final CommandManager commandManager; |
| |
| private List<ICommandManagerListener> commandManagerListeners; |
| |
| /** |
| * The context manager that provides functionality for this workbench command |
| * manager. This value will never be <code>null</code>. |
| * |
| * @since 3.1 |
| */ |
| private final ContextManager contextManager; |
| |
| /** |
| * Constructs a new instance of <code>MutableCommandManager</code>. The binding |
| * manager and command manager providing support for this manager are |
| * constructed at this time. |
| * |
| * @param bindingManager The binding manager providing support for the command |
| * manager; must not be <code>null</code>. |
| * @param commandManager The command manager providing support for this command |
| * manager; must not be <code>null</code>. |
| * @param contextManager The context manager to provide context support to this |
| * manager. This value must not be <code>null</code>. |
| * |
| */ |
| public CommandManagerLegacyWrapper(final BindingManager bindingManager, final CommandManager commandManager, |
| final ContextManager contextManager) { |
| if (contextManager == null) { |
| throw new NullPointerException("The context manager cannot be null."); //$NON-NLS-1$ |
| } |
| this.bindingManager = bindingManager; |
| this.commandManager = commandManager; |
| this.contextManager = contextManager; |
| } |
| |
| @Override |
| public void addCommandManagerListener(final ICommandManagerListener commandManagerListener) { |
| if (commandManagerListener == null) { |
| throw new NullPointerException("Cannot add a null listener."); //$NON-NLS-1$ |
| } |
| |
| if (commandManagerListeners == null) { |
| commandManagerListeners = new ArrayList<>(); |
| this.commandManager.addCommandManagerListener(this); |
| this.bindingManager.addBindingManagerListener(this); |
| this.contextManager.addContextManagerListener(this); |
| } |
| |
| if (!commandManagerListeners.contains(commandManagerListener)) { |
| commandManagerListeners.add(commandManagerListener); |
| } |
| } |
| |
| @Override |
| public void bindingManagerChanged(final BindingManagerEvent event) { |
| final boolean schemeDefinitionsChanged = event.getScheme() != null; |
| final Set<String> previousSchemes; |
| if (schemeDefinitionsChanged) { |
| previousSchemes = new HashSet<>(); |
| final Scheme scheme = event.getScheme(); |
| final Scheme[] definedSchemes = event.getManager().getDefinedSchemes(); |
| final int definedSchemesCount = definedSchemes.length; |
| for (int i = 0; i < definedSchemesCount; i++) { |
| final Scheme definedScheme = definedSchemes[0]; |
| if ((definedScheme == scheme) && (event.isSchemeDefined())) { |
| continue; // skip this one, it was just defined. |
| } |
| previousSchemes.add(definedSchemes[0].getId()); |
| } |
| if (!event.isSchemeDefined()) { |
| previousSchemes.add(scheme.getId()); |
| } |
| } else { |
| previousSchemes = null; |
| } |
| |
| fireCommandManagerChanged(new CommandManagerEvent(this, false, event.isActiveSchemeChanged(), |
| event.isLocaleChanged(), event.isPlatformChanged(), false, false, schemeDefinitionsChanged, null, null, |
| previousSchemes)); |
| } |
| |
| @Override |
| public void commandManagerChanged(final org.eclipse.core.commands.CommandManagerEvent event) { |
| // Figure out the set of previous category identifiers. |
| final boolean categoryIdsChanged = event.isCategoryChanged(); |
| final Set<String> previousCategoryIds; |
| if (categoryIdsChanged) { |
| previousCategoryIds = new HashSet<String>(commandManager.getDefinedCategoryIds()); |
| final String categoryId = event.getCategoryId(); |
| if (event.isCategoryDefined()) { |
| previousCategoryIds.remove(categoryId); |
| } else { |
| previousCategoryIds.add(categoryId); |
| } |
| } else { |
| previousCategoryIds = null; |
| } |
| |
| // Figure out the set of previous command identifiers. |
| final boolean commandIdsChanged = event.isCommandChanged(); |
| final Set<String> previousCommandIds; |
| if (commandIdsChanged) { |
| previousCommandIds = new HashSet<String>(commandManager.getDefinedCommandIds()); |
| final String commandId = event.getCommandId(); |
| if (event.isCommandDefined()) { |
| previousCommandIds.remove(commandId); |
| } else { |
| previousCommandIds.add(commandId); |
| } |
| } else { |
| previousCommandIds = null; |
| } |
| |
| fireCommandManagerChanged(new CommandManagerEvent(this, false, false, false, false, categoryIdsChanged, |
| commandIdsChanged, false, previousCategoryIds, previousCommandIds, null)); |
| } |
| |
| @Override |
| public void contextManagerChanged(final ContextManagerEvent event) { |
| fireCommandManagerChanged(new CommandManagerEvent(this, event.isActiveContextsChanged(), false, false, false, |
| false, false, false, null, null, null)); |
| } |
| |
| private void fireCommandManagerChanged(CommandManagerEvent commandManagerEvent) { |
| if (commandManagerEvent == null) { |
| throw new NullPointerException(); |
| } |
| if (commandManagerListeners != null) { |
| for (ICommandManagerListener commandManagerListener : commandManagerListeners) { |
| commandManagerListener.commandManagerChanged(commandManagerEvent); |
| } |
| } |
| } |
| |
| @Override |
| public Set getActiveContextIds() { |
| return contextManager.getActiveContextIds(); |
| } |
| |
| @Override |
| public String getActiveKeyConfigurationId() { |
| final Scheme scheme = bindingManager.getActiveScheme(); |
| if (scheme != null) { |
| return scheme.getId(); |
| } |
| |
| /* |
| * TODO This is possibly a breaking change. The id should be non-null, and |
| * presumably, a real scheme id. |
| */ |
| return Util.ZERO_LENGTH_STRING; |
| } |
| |
| @Override |
| public String getActiveLocale() { |
| return bindingManager.getLocale(); |
| } |
| |
| @Override |
| public String getActivePlatform() { |
| return bindingManager.getPlatform(); |
| } |
| |
| @Override |
| public ICategory getCategory(String categoryId) { |
| // TODO Provide access to the categories. |
| // return new CategoryWrapper(commandManager.getCategory(categoryId)); |
| return null; |
| } |
| |
| @Override |
| public ICommand getCommand(String commandId) { |
| final Command command = commandManager.getCommand(commandId); |
| if (!command.isDefined()) { |
| command.setHandler(HandlerServiceImpl.getHandler(commandId)); |
| } |
| return new CommandLegacyWrapper(command, bindingManager); |
| } |
| |
| @Override |
| public Set getDefinedCategoryIds() { |
| return commandManager.getDefinedCategoryIds(); |
| } |
| |
| @Override |
| public Set getDefinedCommandIds() { |
| return commandManager.getDefinedCommandIds(); |
| } |
| |
| @Override |
| public Set<String> getDefinedKeyConfigurationIds() { |
| final Set<String> definedIds = new HashSet<>(); |
| final Scheme[] schemes = bindingManager.getDefinedSchemes(); |
| for (Scheme scheme : schemes) { |
| definedIds.add(scheme.getId()); |
| } |
| return definedIds; |
| } |
| |
| @Override |
| public IKeyConfiguration getKeyConfiguration(String keyConfigurationId) { |
| final Scheme scheme = bindingManager.getScheme(keyConfigurationId); |
| return new SchemeLegacyWrapper(scheme, bindingManager); |
| } |
| |
| @Override |
| public Map<KeySequence, Binding> getPartialMatches(KeySequence keySequence) { |
| try { |
| final org.eclipse.jface.bindings.keys.KeySequence sequence = org.eclipse.jface.bindings.keys.KeySequence |
| .getInstance(keySequence.toString()); |
| final Map<TriggerSequence, Binding> partialMatches = bindingManager.getPartialMatches(sequence); |
| final Map<KeySequence, Binding> returnValue = new HashMap<>(); |
| final Iterator<Map.Entry<TriggerSequence, Binding>> matchItr = partialMatches.entrySet().iterator(); |
| while (matchItr.hasNext()) { |
| final Map.Entry<TriggerSequence, Binding> entry = matchItr.next(); |
| final TriggerSequence trigger = entry.getKey(); |
| if (trigger instanceof org.eclipse.jface.bindings.keys.KeySequence) { |
| final org.eclipse.jface.bindings.keys.KeySequence triggerKey = (org.eclipse.jface.bindings.keys.KeySequence) trigger; |
| returnValue.put(KeySequence.getInstance(triggerKey.toString()), entry.getValue()); |
| } |
| } |
| return returnValue; |
| } catch (final ParseException | org.eclipse.ui.keys.ParseException e) { |
| return new HashMap<>(); |
| } |
| } |
| |
| @Override |
| public String getPerfectMatch(KeySequence keySequence) { |
| try { |
| final org.eclipse.jface.bindings.keys.KeySequence sequence = org.eclipse.jface.bindings.keys.KeySequence |
| .getInstance(keySequence.toString()); |
| final Binding binding = bindingManager.getPerfectMatch(sequence); |
| if (binding == null) { |
| return null; |
| } |
| |
| return binding.getParameterizedCommand().getId(); |
| |
| } catch (final ParseException e) { |
| return null; |
| } |
| } |
| |
| @Override |
| public boolean isPartialMatch(KeySequence keySequence) { |
| try { |
| final org.eclipse.jface.bindings.keys.KeySequence sequence = org.eclipse.jface.bindings.keys.KeySequence |
| .getInstance(keySequence.toString()); |
| return bindingManager.isPartialMatch(sequence); |
| } catch (final ParseException e) { |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean isPerfectMatch(KeySequence keySequence) { |
| try { |
| final org.eclipse.jface.bindings.keys.KeySequence sequence = org.eclipse.jface.bindings.keys.KeySequence |
| .getInstance(keySequence.toString()); |
| return bindingManager.isPerfectMatch(sequence); |
| } catch (final ParseException e) { |
| return false; |
| } |
| } |
| |
| @Override |
| public void removeCommandManagerListener(ICommandManagerListener commandManagerListener) { |
| if (commandManagerListener == null) { |
| throw new NullPointerException("Cannot remove a null listener"); //$NON-NLS-1$ |
| } |
| |
| if (commandManagerListeners != null) { |
| commandManagerListeners.remove(commandManagerListener); |
| if (commandManagerListeners.isEmpty()) { |
| commandManagerListeners = null; |
| this.commandManager.removeCommandManagerListener(this); |
| this.bindingManager.removeBindingManagerListener(this); |
| this.contextManager.removeContextManagerListener(this); |
| } |
| } |
| } |
| |
| /** |
| * Updates the handlers for a block of commands all at once. |
| * |
| * @param handlersByCommandId The map of command identifier |
| * (<code>String</code>) to handler |
| * (<code>IHandler</code>). |
| */ |
| public void setHandlersByCommandId(final Map<String, IHandler> handlersByCommandId) { |
| // Wrap legacy handlers so they can be passed to the new API. |
| final Iterator<Map.Entry<String, IHandler>> entryItr = handlersByCommandId.entrySet().iterator(); |
| while (entryItr.hasNext()) { |
| final Map.Entry<String, IHandler> entry = entryItr.next(); |
| final Object handler = entry.getValue(); |
| if (handler instanceof org.eclipse.ui.commands.IHandler) { |
| final String commandId = entry.getKey(); |
| handlersByCommandId.put(commandId, |
| new LegacyHandlerWrapper((org.eclipse.ui.commands.IHandler) handler)); |
| } |
| } |
| |
| commandManager.setHandlersByCommandId(handlersByCommandId); |
| } |
| } |