Mercurial > projects > dwt2
diff org.eclipse.core.commands/src/org/eclipse/core/commands/CommandManager.d @ 12:bc29606a740c
Added dwt-addons in original directory structure of eclipse.org
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 14 Mar 2009 18:23:29 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.core.commands/src/org/eclipse/core/commands/CommandManager.d Sat Mar 14 18:23:29 2009 +0100 @@ -0,0 +1,1074 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module org.eclipse.core.commands.CommandManager; + +import org.eclipse.core.commands.common.HandleObjectManager; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.runtime.ListenerList; + +import org.eclipse.core.commands.ICategoryListener; +import org.eclipse.core.commands.ICommandListener; +import org.eclipse.core.commands.IExecutionListener; +import org.eclipse.core.commands.IExecutionListenerWithChecks; +import org.eclipse.core.commands.IParameterTypeListener; +import org.eclipse.core.commands.ICommandManagerListener; +import org.eclipse.core.commands.CommandEvent; +import org.eclipse.core.commands.CommandManagerEvent; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.Category; +import org.eclipse.core.commands.CategoryEvent; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.ParameterType; +import org.eclipse.core.commands.IParameter; +import org.eclipse.core.commands.Parameterization; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.core.commands.ParameterTypeEvent; +import org.eclipse.core.commands.SerializationException; + +import org.eclipse.core.commands.NotEnabledException; +import org.eclipse.core.commands.NotHandledException; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.ExecutionEvent; + +import java.lang.all; + +import java.util.WeakHashMap; +import java.util.HashMap; +import java.util.Map; +import java.util.Iterator; +import java.util.Collections; +import java.util.ArrayList; +import java.util.Set; +import java.util.HashSet; + +/** + * <p> + * A central repository for commands -- both in the defined and undefined + * states. Commands can be created and retrieved using this manager. It is + * possible to listen to changes in the collection of commands by attaching a + * listener to the manager. + * </p> + * + * @see CommandManager#getCommand(String) + * @since 3.1 + */ +public final class CommandManager : HandleObjectManager, + ICategoryListener, ICommandListener, IParameterTypeListener { + + /** + * A listener that forwards incoming execution events to execution listeners + * on this manager. The execution events will come from any command on this + * manager. + * + * @since 3.1 + */ + private final class ExecutionListener : + IExecutionListenerWithChecks { + + public void notDefined(String commandId, NotDefinedException exception) { + if (executionListeners !is null) { + Object[] listeners = executionListeners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + Object object = listeners[i]; + if ( auto listener = cast(IExecutionListenerWithChecks)object ) { + listener.notDefined(commandId, exception); + } + } + } + } + + public void notEnabled(String commandId, NotEnabledException exception) { + if (executionListeners !is null) { + Object[] listeners = executionListeners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + Object object = listeners[i]; + if ( auto listener = cast(IExecutionListenerWithChecks)object ) { + listener.notEnabled(commandId, exception); + } + } + } + } + + public final void notHandled(String commandId, + NotHandledException exception) { + if (executionListeners !is null) { + Object[] listeners = executionListeners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + Object object = listeners[i]; + if ( auto listener = cast(IExecutionListener)object ) { + listener.notHandled(commandId, exception); + } + } + } + } + + public final void postExecuteFailure(String commandId, + ExecutionException exception) { + if (executionListeners !is null) { + Object[] listeners = executionListeners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + Object object = listeners[i]; + if ( auto listener = cast(IExecutionListener)object ) { + listener.postExecuteFailure(commandId, exception); + } + } + } + } + + public final void postExecuteSuccess(String commandId, + Object returnValue) { + if (executionListeners !is null) { + Object[] listeners = executionListeners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + Object object = listeners[i]; + if ( auto listener = cast(IExecutionListener)object ) { + listener.postExecuteSuccess(commandId, returnValue); + } + } + } + } + + public final void preExecute(String commandId, + ExecutionEvent event) { + if (executionListeners !is null) { + Object[] listeners = executionListeners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + Object object = listeners[i]; + if ( auto listener = cast(IExecutionListener)object ) { + listener.preExecute(commandId, event); + } + } + } + } + } + + /** + * The identifier of the category in which all auto-generated commands will + * appear. This value must never be <code>null</code>. + * + * @since 3.2 + */ + public static const String AUTOGENERATED_CATEGORY_ID = "org.eclipse.core.commands.categories.autogenerated"; //$NON-NLS-1$ + + /** + * The escape character to use for serialization and deserialization of + * parameterized commands. + */ + static const char ESCAPE_CHAR = '%'; + + /** + * The character that separates a parameter id from its value. + */ + static const char ID_VALUE_CHAR = '='; + + /** + * The character that indicates the end of a list of parameters. + */ + static const char PARAMETER_END_CHAR = ')'; + + /** + * The character that separators parameters from each other. + */ + static const char PARAMETER_SEPARATOR_CHAR = ','; + + /** + * The character that indicates the start of a list of parameters. + */ + static const char PARAMETER_START_CHAR = '('; + + this(){ + categoriesById = new HashMap(); + definedCategoryIds = new HashSet(); + definedParameterTypeIds = new HashSet(); + helpContextIdsByHandler = new WeakHashMap(); + parameterTypesById = new HashMap(); + } + + /** + * Unescapes special characters in the command id, parameter ids and + * parameter values for {@link #deserialize(String)}. The special characters + * {@link #PARAMETER_START_CHAR}, {@link #PARAMETER_END_CHAR}, + * {@link #ID_VALUE_CHAR}, {@link #PARAMETER_SEPARATOR_CHAR} and + * {@link #ESCAPE_CHAR} are escaped by prepending an {@link #ESCAPE_CHAR} + * character. + * <p> + * See also ParameterizedCommand.escape(String) + * </p> + * + * @param escapedText + * a <code>String</code> that may contain escaped special + * characters for command serialization. + * @return a <code>String</code> representing <code>escapedText</code> + * with any escaped characters replaced by their literal values + * @throws SerializationException + * if <code>escapedText</code> contains an invalid escape + * sequence + * @since 3.2 + */ + private static final String unescape(String escapedText) { + + // defer initialization of a StringBuffer until we know we need one + StringBuffer buffer; + + for (int i = 0; i < escapedText.length; i++) { + + char c = escapedText.charAt(i); + if (c !is ESCAPE_CHAR) { + // normal unescaped character + if (buffer !is null) { + buffer.append(c); + } + } else { + if (buffer is null) { + buffer = new StringBuffer(escapedText.substring(0, i)); + } + + if (++i < escapedText.length) { + c = escapedText.charAt(i); + switch (c) { + case PARAMETER_START_CHAR: + case PARAMETER_END_CHAR: + case ID_VALUE_CHAR: + case PARAMETER_SEPARATOR_CHAR: + case ESCAPE_CHAR: + buffer.append(c); + break; + default: + throw new SerializationException( + "Invalid character '" ~ c ~ "' in escape sequence"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } else { + throw new SerializationException( + "Unexpected termination of escape sequence"); //$NON-NLS-1$ + } + } + + } + + if (buffer is null) { + return escapedText; + } + + return buffer.toString(); + } + + /** + * The map of category identifiers (<code>String</code>) to categories ( + * <code>Category</code>). This collection may be empty, but it is never + * <code>null</code>. + */ + private const Map categoriesById; + + /** + * The set of identifiers for those categories that are defined. This value + * may be empty, but it is never <code>null</code>. + */ + private const Set definedCategoryIds; + + /** + * The set of identifiers for those command parameter types that are + * defined. This value may be empty, but it is never <code>null</code>. + * + * @since 3.2 + */ + private const Set definedParameterTypeIds; + + /** + * The execution listener for this command manager. This just forwards + * events from commands controlled by this manager to listeners on this + * manager. + */ + private IExecutionListenerWithChecks executionListener = null; + + /** + * The collection of execution listeners. This collection is + * <code>null</code> if there are no listeners. + */ + private ListenerList executionListeners = null; + + /** + * The help context identifiers ({@link String}) for a handler ({@link IHandler}). + * This map may be empty, but it is never <code>null</code>. Entries are + * removed if all strong references to the handler are removed. + * + * @since 3.2 + */ + private const WeakHashMap helpContextIdsByHandler; + + /** + * The map of parameter type identifiers (<code>String</code>) to + * parameter types ( <code>ParameterType</code>). This collection may be + * empty, but it is never <code>null</code>. + * + * @since 3.2 + */ + private const Map parameterTypesById; + + /** + * Adds a listener to this command manager. The listener will be notified + * when the set of defined commands changes. This can be used to track the + * global appearance and disappearance of commands. + * + * @param listener + * The listener to attach; must not be <code>null</code>. + */ + public final void addCommandManagerListener( + ICommandManagerListener listener) { + addListenerObject(cast(Object)listener); + } + + /** + * Adds an execution listener to this manager. This listener will be + * notified if any of the commands controlled by this manager execute. This + * can be used to support macros and instrumentation of commands. + * + * @param listener + * The listener to attach; must not be <code>null</code>. + */ + public final void addExecutionListener(IExecutionListener listener) { + if (listener is null) { + throw new NullPointerException( + "Cannot add a null execution listener"); //$NON-NLS-1$ + } + + if (executionListeners is null) { + executionListeners = new ListenerList(ListenerList.IDENTITY); + + // Add an execution listener to every command. + executionListener = new ExecutionListener(); + Iterator commandItr = handleObjectsById.values().iterator(); + while (commandItr.hasNext()) { + Command command = cast(Command) commandItr.next(); + command.addExecutionListener(executionListener); + } + + } + + executionListeners.add(cast(Object)listener); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.commands.ICategoryListener#categoryChanged(org.eclipse.core.commands.CategoryEvent) + */ + public final void categoryChanged(CategoryEvent categoryEvent) { + if (categoryEvent.isDefinedChanged()) { + Category category = categoryEvent.getCategory(); + String categoryId = category.getId(); + bool categoryIdAdded = category.isDefined(); + if (categoryIdAdded) { + definedCategoryIds.add(categoryId); + } else { + definedCategoryIds.remove(categoryId); + } + if (isListenerAttached()) { + fireCommandManagerChanged(new CommandManagerEvent(this, null, + false, false, categoryId, categoryIdAdded, true)); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.commands.ICommandListener#commandChanged(org.eclipse.commands.CommandEvent) + */ + public final void commandChanged(CommandEvent commandEvent) { + if (commandEvent.isDefinedChanged()) { + Command command = commandEvent.getCommand(); + String commandId = command.getId(); + bool commandIdAdded = command.isDefined(); + if (commandIdAdded) { + definedHandleObjects.add(command); + } else { + definedHandleObjects.remove(command); + } + if (isListenerAttached()) { + fireCommandManagerChanged(new CommandManagerEvent(this, + commandId, commandIdAdded, true, null, false, false)); + } + } + } + + /** + * Sets the name and description of the category for uncategorized commands. + * This is the category that will be returned if + * {@link #getCategory(String)} is called with <code>null</code>. + * + * @param name + * The name of the category for uncategorized commands; must not + * be <code>null</code>. + * @param description + * The description of the category for uncategorized commands; + * may be <code>null</code>. + * @since 3.2 + */ + public final void defineUncategorizedCategory(String name, + String description) { + Category category = getCategory(AUTOGENERATED_CATEGORY_ID); + category.define(name, description); + } + + /** + * <p> + * Returns a {@link ParameterizedCommand} with a command and + * parameterizations as specified in the provided + * <code>serializedParameterizedCommand</code> string. The + * <code>serializedParameterizedCommand</code> must use the format + * returned by {@link ParameterizedCommand#serialize()} and described in the + * Javadoc for that method. + * </p> + * <p> + * If a parameter id encoded in the + * <code>serializedParameterizedCommand</code> does not exist in the + * encoded command, that parameter id and value are ignored. A given + * parameter id should not be used more than once in + * <code>serializedParameterizedCommand</code>. This will not result in + * an exception, but in this case the value of the parameter when the + * command is executed is unspecified. + * </p> + * <p> + * This method will never return <code>null</code>, however it may throw + * an exception if there is a problem processing the serialization string or + * the encoded command is undefined. + * </p> + * + * @param serializedParameterizedCommand + * a string representing a command id and parameter ids and + * values; must not be <code>null</code> + * @return a {@link ParameterizedCommand} with the command and + * parameterizations encoded in the + * <code>serializedParameterizedCommand</code>; never + * <code>null</code>. + * @throws NotDefinedException + * if the command indicated in + * <code>serializedParameterizedCommand</code> is not defined + * @throws SerializationException + * if there is an error deserializing + * <code>serializedParameterizedCommand</code> + * @see ParameterizedCommand#serialize() + * @since 3.2 + */ + public final ParameterizedCommand deserialize( + String serializedParameterizedCommand) { + + int lparenPosition = unescapedIndexOf( + serializedParameterizedCommand, PARAMETER_START_CHAR); + + String commandIdEscaped; + String serializedParameters; + if (lparenPosition is -1) { + commandIdEscaped = serializedParameterizedCommand; + serializedParameters = null; + } else { + commandIdEscaped = serializedParameterizedCommand.substring(0, + lparenPosition); + + if (serializedParameterizedCommand + .charAt(serializedParameterizedCommand.length - 1) !is PARAMETER_END_CHAR) { + throw new SerializationException( + "Parentheses must be balanced in serialized ParameterizedCommand"); //$NON-NLS-1$ + } + + serializedParameters = serializedParameterizedCommand.substring( + lparenPosition + 1, // skip PARAMETER_START_CHAR + serializedParameterizedCommand.length - 1); // skip + // PARAMETER_END_CHAR + } + + String commandId = unescape(commandIdEscaped); + Command command = getCommand(commandId); + IParameter[] parameters = command.getParameters(); + Parameterization[] parameterizations = getParameterizations( + serializedParameters, parameters); + + return new ParameterizedCommand(command, parameterizations); + } + + /** + * Notifies all of the listeners to this manager that the set of defined + * command identifiers has changed. + * + * @param event + * The event to send to all of the listeners; must not be + * <code>null</code>. + */ + private final void fireCommandManagerChanged(CommandManagerEvent event) { + if (event is null) { + throw new NullPointerException(); + } + + Object[] listeners = getListeners(); + for (int i = 0; i < listeners.length; i++) { + ICommandManagerListener listener = cast(ICommandManagerListener) listeners[i]; + listener.commandManagerChanged(event); + } + } + + /** + * Returns all of the commands known by this manager -- defined and + * undefined. + * + * @return All of the commands; may be empty, but never <code>null</code>. + * @since 3.2 + */ + public final Command[] getAllCommands() { + return arraycast!(Command)( handleObjectsById.values().toArray()); + } + + /** + * Gets the category with the given identifier. If no such category + * currently exists, then the category will be created (but be undefined). + * + * @param categoryId + * The identifier to find; must not be <code>null</code>. If + * the category is <code>null</code>, then a category suitable + * for uncategorized items is defined and returned. + * @return The category with the given identifier; this value will never be + * <code>null</code>, but it might be undefined. + * @see Category + */ + public final Category getCategory(String categoryId) { + if (categoryId is null) { + return getCategory(AUTOGENERATED_CATEGORY_ID); + } + + checkId(categoryId); + + Category category = cast(Category) categoriesById.get(categoryId); + if (category is null) { + category = new Category(categoryId); + categoriesById.put(categoryId, category); + category.addCategoryListener(this); + } + + return category; + } + + /** + * Gets the command with the given identifier. If no such command currently + * exists, then the command will be created (but will be undefined). + * + * @param commandId + * The identifier to find; must not be <code>null</code> and + * must not be zero-length. + * @return The command with the given identifier; this value will never be + * <code>null</code>, but it might be undefined. + * @see Command + */ + public final Command getCommand(String commandId) { + checkId(commandId); + + Command command = cast(Command) handleObjectsById.get(commandId); + if (command is null) { + command = new Command(commandId); + handleObjectsById.put(commandId, command); + command.addCommandListener(this); + + if (executionListener !is null) { + command.addExecutionListener(executionListener); + } + } + + return command; + } + + /** + * Returns the categories that are defined. + * + * @return The defined categories; this value may be empty, but it is never + * <code>null</code>. + * @since 3.2 + */ + public final Category[] getDefinedCategories() { + Category[] categories = new Category[definedCategoryIds.size()]; + Iterator categoryIdItr = definedCategoryIds.iterator(); + int i = 0; + while (categoryIdItr.hasNext()) { + String categoryId = stringcast( categoryIdItr.next()); + categories[i++] = getCategory(categoryId); + } + return categories; + } + + /** + * Returns the set of identifiers for those category that are defined. + * + * @return The set of defined category identifiers; this value may be empty, + * but it is never <code>null</code>. + */ + public final Set getDefinedCategoryIds() { + return Collections.unmodifiableSet(definedCategoryIds); + } + + /** + * Returns the set of identifiers for those commands that are defined. + * + * @return The set of defined command identifiers; this value may be empty, + * but it is never <code>null</code>. + */ + public final Set getDefinedCommandIds() { + return getDefinedHandleObjectIds(); + } + + /** + * Returns the commands that are defined. + * + * @return The defined commands; this value may be empty, but it is never + * <code>null</code>. + * @since 3.2 + */ + public final Command[] getDefinedCommands() { + return arraycast!(Command)( definedHandleObjects + .toArray()); + } + + /** + * Returns the set of identifiers for those parameter types that are + * defined. + * + * @return The set of defined command parameter type identifiers; this value + * may be empty, but it is never <code>null</code>. + * @since 3.2 + */ + public final Set getDefinedParameterTypeIds() { + return Collections.unmodifiableSet(definedParameterTypeIds); + } + + /** + * Returns the command parameter types that are defined. + * + * @return The defined command parameter types; this value may be empty, but + * it is never <code>null</code>. + * @since 3.2 + */ + public final ParameterType[] getDefinedParameterTypes() { + ParameterType[] parameterTypes = new ParameterType[definedParameterTypeIds + .size()]; + Iterator iterator = definedParameterTypeIds.iterator(); + int i = 0; + while (iterator.hasNext()) { + String parameterTypeId = stringcast( iterator.next()); + parameterTypes[i++] = getParameterType(parameterTypeId); + } + return parameterTypes; + } + + /** + * Gets the help context identifier for a particular command. The command's + * handler is first checked for a help context identifier. If the handler + * does not have a help context identifier, then the help context identifier + * for the command is returned. If neither has a help context identifier, + * then <code>null</code> is returned. + * + * @param command + * The command for which the help context should be retrieved; + * must not be <code>null</code>. + * @return The help context identifier to use for the given command; may be + * <code>null</code>. + * @throws NotDefinedException + * If the given command is not defined. + * @since 3.2 + */ + public final String getHelpContextId(Command command) { + // Check if the command is defined. + if (!command.isDefined()) { + throw new NotDefinedException("The command is not defined. " //$NON-NLS-1$ + ~ command.getId()); + } + + // Check the handler. + IHandler handler = command.getHandler(); + if (handler !is null) { + String helpContextId = stringcast( helpContextIdsByHandler.get( cast(Object) handler) ); + if (helpContextId !is null) { + return helpContextId; + } + } + + // Simply return whatever the command has as a help context identifier. + return command.getHelpContextId(); + } + + /** + * Returns an array of parameterizations for the provided command by + * deriving the parameter ids and values from the provided + * <code>serializedParameters</code> string. + * + * @param serializedParameters + * a String encoding parameter ids and values; must not be + * <code>null</code>. + * @param parameters + * array of parameters of the command being deserialized; may be + * <code>null</code>. + * @return an array of parameterizations; may be <code>null</code>. + * @throws SerializationException + * if there is an error deserializing the parameters + * @since 3.2 + */ + private final Parameterization[] getParameterizations( + String serializedParameters, IParameter[] parameters) { + + if (serializedParameters is null + || (serializedParameters.length is 0)) { + return null; + } + + if ((parameters is null) || (parameters.length is 0)) { + return null; + } + + ArrayList paramList = new ArrayList(); + + int commaPosition; // split off each param by looking for ',' + do { + commaPosition = unescapedIndexOf(serializedParameters, ','); + + String idEqualsValue; + if (commaPosition is -1) { + // no more parameters after this + idEqualsValue = serializedParameters; + } else { + // take the first parameter... + idEqualsValue = serializedParameters + .substring(0, commaPosition); + + // ... and put the rest back into serializedParameters + serializedParameters = serializedParameters + .substring(commaPosition + 1); + } + + int equalsPosition = unescapedIndexOf(idEqualsValue, '='); + + String parameterId; + String parameterValue; + if (equalsPosition is -1) { + // missing values are null + parameterId = unescape(idEqualsValue); + parameterValue = null; + } else { + parameterId = unescape(idEqualsValue.substring(0, + equalsPosition)); + parameterValue = unescape(idEqualsValue + .substring(equalsPosition + 1)); + } + + for (int i = 0; i < parameters.length; i++) { + IParameter parameter = parameters[i]; + if (parameter.getId().equals(parameterId)) { + paramList.add(new Parameterization(parameter, + parameterValue)); + break; + } + } + + } while (commaPosition !is -1); + + return arraycast!(Parameterization)( paramList + .toArray()); + } + + /** + * Gets the command {@link ParameterType} with the given identifier. If no + * such command parameter type currently exists, then the command parameter + * type will be created (but will be undefined). + * + * @param parameterTypeId + * The identifier to find; must not be <code>null</code> and + * must not be zero-length. + * @return The {@link ParameterType} with the given identifier; this value + * will never be <code>null</code>, but it might be undefined. + * @since 3.2 + */ + public final ParameterType getParameterType(String parameterTypeId) { + checkId(parameterTypeId); + + ParameterType parameterType = cast(ParameterType) parameterTypesById + .get(parameterTypeId); + if (parameterType is null) { + parameterType = new ParameterType(parameterTypeId); + parameterTypesById.put(parameterTypeId, parameterType); + parameterType.addListener(this); + } + + return parameterType; + } + + /** + * {@inheritDoc} + * + * @since 3.2 + */ + public final void parameterTypeChanged( + ParameterTypeEvent parameterTypeEvent) { + if (parameterTypeEvent.isDefinedChanged()) { + ParameterType parameterType = parameterTypeEvent + .getParameterType(); + String parameterTypeId = parameterType.getId(); + bool parameterTypeIdAdded = parameterType.isDefined(); + if (parameterTypeIdAdded) { + definedParameterTypeIds.add(parameterTypeId); + } else { + definedParameterTypeIds.remove(parameterTypeId); + } + + fireCommandManagerChanged(new CommandManagerEvent(this, + parameterTypeId, parameterTypeIdAdded, true)); + } + } + + /** + * Removes a listener from this command manager. + * + * @param listener + * The listener to be removed; must not be <code>null</code>. + */ + public final void removeCommandManagerListener( + ICommandManagerListener listener) { + removeListenerObject(cast(Object)listener); + } + + /** + * Removes an execution listener from this command manager. + * + * @param listener + * The listener to be removed; must not be <code>null</code>. + */ + public final void removeExecutionListener(IExecutionListener listener) { + if (listener is null) { + throw new NullPointerException("Cannot remove a null listener"); //$NON-NLS-1$ + } + + if (executionListeners is null) { + return; + } + + executionListeners.remove(cast(Object)listener); + + if (executionListeners.isEmpty()) { + executionListeners = null; + + // Remove the execution listener to every command. + Iterator commandItr = handleObjectsById.values().iterator(); + while (commandItr.hasNext()) { + Command command = cast(Command) commandItr.next(); + command.removeExecutionListener(executionListener); + } + executionListener = null; + + } + } + + /** + * Block updates all of the handlers for all of the commands. If the handler + * is <code>null</code> or the command id does not exist in the map, then + * the command becomes unhandled. Otherwise, the handler is set to the + * corresponding value in the map. + * + * @param handlersByCommandId + * A map of command identifiers (<code>String</code>) to + * handlers (<code>IHandler</code>). This map may be + * <code>null</code> if all handlers should be cleared. + * Similarly, if the map is empty, then all commands will become + * unhandled. + */ + public final void setHandlersByCommandId(Map handlersByCommandId) { + // Make that all the reference commands are created. + Iterator commandIdItr = handlersByCommandId.keySet().iterator(); + while (commandIdItr.hasNext()) { + getCommand(stringcast(commandIdItr.next())); + } + + // Now, set-up the handlers on all of the existing commands. + Iterator commandItr = handleObjectsById.values().iterator(); + while (commandItr.hasNext()) { + Command command = cast(Command) commandItr.next(); + String commandId = command.getId(); + Object value = handlersByCommandId.get(commandId); + if ( cast(IHandler)value ) { + command.setHandler(cast(IHandler) value); + } else { + command.setHandler(null); + } + } + } + + /** + * Sets the help context identifier to associate with a particular handler. + * + * @param handler + * The handler with which to register a help context identifier; + * must not be <code>null</code>. + * @param helpContextId + * The help context identifier to register; may be + * <code>null</code> if the help context identifier should be + * removed. + * @since 3.2 + */ + public final void setHelpContextId(IHandler handler, + String helpContextId) { + if (handler is null) { + throw new NullPointerException("The handler cannot be null"); //$NON-NLS-1$ + } + if (helpContextId is null) { + helpContextIdsByHandler.remove(cast(Object) handler); + } else { + helpContextIdsByHandler.put(cast(Object) handler, stringcast(helpContextId)); + } + } + + /** + * Searches for the index of a <code>char</code> in a <code>String</code> + * but disregards characters prefixed with the {@link #ESCAPE_CHAR} escape + * character. This is used by {@link #deserialize(String)} and + * {@link #getParameterizations(String, IParameter[])} to parse the + * serialized parameterized command string. + * + * @param escapedText + * the string to search for the index of <code>ch</code> in + * @param ch + * a character to search for in <code>escapedText</code> + * @return the index of the first unescaped occurrence of the character in + * <code>escapedText</code>, or <code>-1</code> if the + * character does not occur unescaped. + * @see String#indexOf(int) + */ + private final int unescapedIndexOf(String escapedText, char ch) { + + int pos = escapedText.indexOf(ch); + + // first char can't be escaped + if (pos is 0) { + return pos; + } + + while (pos !is -1) { + // look back for the escape character + if (escapedText.charAt(pos - 1) !is ESCAPE_CHAR) { + return pos; + } + + // scan for the next instance of ch + pos = escapedText.indexOf(ch, pos + 1); + } + + return pos; + + } + /** + * Fires the <code>notEnabled</code> event for + * <code>executionListeners</code>. + * <p> + * <b>Note:</b> This supports bridging actions to the command framework, + * and should not be used outside the framework. + * </p> + * + * @param commandId + * The command id of the command about to execute, never + * <code>null</code>. + * @param exception + * The exception, never <code>null</code>. + * @since 3.4 + */ + public void fireNotEnabled(String commandId, NotEnabledException exception) { + if (executionListener !is null) { + executionListener.notEnabled(commandId, exception); + } + } + + /** + * Fires the <code>notDefined</code> event for + * <code>executionListeners</code>. + * <p> + * <b>Note:</b> This supports bridging actions to the command framework, + * and should not be used outside the framework. + * </p> + * + * @param commandId + * The command id of the command about to execute, never + * <code>null</code>. + * @param exception + * The exception, never <code>null</code>. + * @since 3.4 + */ + public void fireNotDefined(String commandId, NotDefinedException exception) { + if (executionListener !is null) { + executionListener.notDefined(commandId, exception); + } + } + + /** + * Fires the <code>preExecute</code> event for + * <code>executionListeners</code>. + * <p> + * <b>Note:</b> This supports bridging actions to the command framework, + * and should not be used outside the framework. + * </p> + * + * @param commandId + * The command id of the command about to execute, never + * <code>null</code>. + * @param event + * The event that triggered the command, may be <code>null</code>. + * @since 3.4 + */ + public void firePreExecute(String commandId, ExecutionEvent event) { + if (executionListener !is null) { + executionListener.preExecute(commandId, event); + } + } + + /** + * Fires the <code>postExecuteSuccess</code> event for + * <code>executionListeners</code>. + * <p> + * <b>Note:</b> This supports bridging actions to the command framework, + * and should not be used outside the framework. + * </p> + * + * @param commandId + * The command id of the command executed, never + * <code>null</code>. + * @param returnValue + * The value returned from the command, may be <code>null</code>. + * @since 3.4 + */ + public void firePostExecuteSuccess(String commandId, Object returnValue) { + if (executionListener !is null) { + executionListener.postExecuteSuccess(commandId, returnValue); + } + } + + /** + * Fires the <code>postExecuteFailure</code> event for + * <code>executionListeners</code>. + * <p> + * <b>Note:</b> This supports bridging actions to the command framework, + * and should not be used outside the framework. + * </p> + * + * @param commandId + * The command id of the command executed, never + * <code>null</code>. + * @param exception + * The exception, never <code>null</code>. + * @since 3.4 + */ + public void firePostExecuteFailure(String commandId, + ExecutionException exception) { + if (executionListener !is null) { + executionListener.postExecuteFailure(commandId, exception); + } + } +}