# HG changeset patch
# User Frank Benoit
+ * This class is a partial implementation of
+ * Subclasses may extend the definition of this method (i.e., if a different
+ * type of listener can be attached to a subclass). This is used primarily
+ * for support of
+ * Returns true iff there is one or more IHandlerListeners attached to this
+ * AbstractHandler.
+ *
+ * Subclasses may extend the definition of this method (i.e., if a different
+ * type of listener can be attached to a subclass). This is used primarily
+ * for support of
+ * An abstract implementation of {@link IObjectWithState}. This provides basic
+ * handling for adding and remove state. When state is added, the handler
+ * attaches itself as a listener and fire a handleStateChange event to notify
+ * this handler. When state is removed, the handler removes itself as a
+ * listener.
+ *
+ * Clients may extend this class.
+ *
+ * Adds a state to this handler. This will add this handler as a listener to
+ * the state, and then fire a handleStateChange so that the handler can
+ * respond to the incoming state.
+ *
+ * Clients may extend this method, but they should call this super method
+ * first before doing anything else.
+ *
+ * Removes a state from this handler. This will remove this handler as a
+ * listener to the state. No event is fired to notify the handler of this
+ * change.
+ *
+ * Clients may extend this method, but they should call this super method
+ * first before doing anything else.
+ *
+ * Supports conversion between objects and strings for command parameter values.
+ * Extenders must produce strings that identify objects (of a specific command
+ * parameter type) as well as consume the strings to locate and return the
+ * objects they identify.
+ *
+ * This class offers multiple handlers of a command a consistent way of
+ * converting string parameter values into the objects that the handlers would
+ * prefer to deal with. This class also gives clients a way to serialize
+ * object parameters as strings so that entire parameterized commands can be
+ * serialized, stored and later deserialized and executed.
+ *
+ * This class will typically be extended so the subclass can be referenced from
+ * the
+ * A logical group for a set of commands. A command belongs to exactly one
+ * category. The category has no functional effect, but may be used in graphical
+ * tools that want to group the set of commands somehow.
+ *
+ * Defines this category by giving it a name, and possibly a description as
+ * well. The defined property automatically becomes
+ * Notification is sent to all listeners that something has changed.
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * A command is an abstract representation for some semantic behaviour. It is
+ * not the actual implementation of this behaviour, nor is it the visual
+ * appearance of this behaviour in the user interface. Instead, it is a bridge
+ * between the two.
+ *
+ * The concept of a command is based on the command design pattern. The notable
+ * difference is how the command delegates responsibility for execution. Rather
+ * than allowing concrete subclasses, it uses a handler mechanism (see the
+ *
+ * A command will exist in two states: defined and undefined. A command is
+ * defined if it is declared in the XML of a resolved plug-in. If the plug-in is
+ * unloaded or the command is simply not declared, then it is undefined. Trying
+ * to reference an undefined command will succeed, but trying to access any of
+ * its functionality will fail with a
+ * Commands are mutable and will change as their definition changes.
+ *
+ * Adds a state to this command. This will add this state to the active
+ * handler, if the active handler is an instance of {@link IObjectWithState}.
+ *
+ * A single instance of {@link State} cannot be registered with multiple
+ * commands. Each command requires its own unique instance.
+ *
+ * Defines this command by giving it a name, and possibly a description as
+ * well. The defined property automatically becomes
+ * Notification is sent to all listeners that something has changed.
+ *
+ * Defines this command by giving it a name, and possibly a description as
+ * well. The defined property automatically becomes
+ * Notification is sent to all listeners that something has changed.
+ *
+ * Defines this command by giving it a name, and possibly a description as
+ * well. The defined property automatically becomes
+ * Notification is sent to all listeners that something has changed.
+ *
+ * Defines this command by giving it a name, and possibly a description as
+ * well. The defined property automatically becomes
+ * Notification is sent to all listeners that something has changed.
+ *
+ * This value can change at any time and should never be cached.
+ *
+ * Removes a state from this command. This will remove the state from the
+ * active handler, if the active handler is an instance of
+ * {@link IObjectWithState}.
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * 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.
+ *
+ * Returns a {@link ParameterizedCommand} with a command and
+ * parameterizations as specified in the provided
+ *
+ * If a parameter id encoded in the
+ *
+ * This method will never return
+ * An event indicating that the set of defined command identifiers has changed.
+ *
+ * The data object to pass to the command (and its handler) as it executes. This
+ * carries information about the current state of the application, and the
+ * application context in which the command was executed.
+ *
+ * An execution event carries three blocks of data: the parameters, the trigger,
+ * and the application context. How these blocks are used is application
+ * dependent. In the Eclipse workbench, the trigger is an DWT event, and the
+ * application context contains information about the selection and active part.
+ *
+ * This is intended to be used in the scope of an
+ * {@link IHandler#execute(ExecutionEvent)} method, so any problem getting
+ * the object value causes
+ * This class is not intended to be extended by clients.
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * This interface may be implemented by clients.
+ *
+ * This interface may be implemented by clients.
+ *
+ * This interface may be implemented by clients.
+ *
+ * A listener to the execution of commands. This listener will be notified if a
+ * command is about to execute, and when that execution completes. It is not
+ * possible for the listener to prevent the execution, only to respond to it in
+ * some way.
+ *
+ * A listener to the execution of commands. This listener will be notified if
+ * someone tries to execute a command and it is not enabled or not defined. The
+ * listener also be notified if a command is about to execute, and when that
+ * execution completes. It is not possible for the listener to prevent the
+ * execution, only to respond to it in some way.
+ *
+ * Clients may implement, but must not extend.
+ *
+ * Attribute constants that have special meanings within this package. These
+ * attributes can be used to communicate extra information from the handler to
+ * either the command or the command manager.
+ *
+ * The name of the attribute indicating whether the handler is handled.
+ * This is intended largely for backward compatibility with the workbench
+ *
+ * This interface may be implemented by clients.
+ *
+ * State identifiers that are understood by named handle objects that implement
+ * {@link IObjectWithState}.
+ *
+ * Clients may implement or extend this class.
+ *
+ * An object that holds zero or more state objects. This state information can
+ * be shared between different instances of
+ * Clients may implement, but must not extend this interface.
+ *
+ * A parameter for a command. A parameter identifies a type of information that
+ * the command might accept. For example, a "Show View" command might accept the
+ * id of a view for display. This parameter also identifies possible values, for
+ * display in the user interface.
+ *
+ * This interface may be implemented by clients.
+ *
+ * The parameters for a command. This interface will only be consulted if the
+ * parameters need to be displayed to the user. Otherwise, they will be ignored.
+ *
+ * A listener to changes in some state.
+ *
+ * Clients may implement, but must not extend this interface.
+ *
+ * Note that the parameter type returned may be undefined.
+ *
+ * A named handle object that can carry state with it. This state can be used to
+ * override the name or description.
+ *
+ * Clients may neither instantiate nor extend this class.
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * Provides information about the type of a command parameter. Clients can use a
+ * parameter type to check if an object matches the type of the parameter with
+ * {@link #isCompatible(Object)} and can get an
+ * {@link AbstractParameterValueConverter} to convert between objects matching
+ * the parameter type and strings that encode the object's identity.
+ *
+ * A command parameter is not required to declare a type. To determine if a
+ * given parameter has a type, check if an {@link IParameter} implements
+ * {@link ITypedParameter} and if so, use
+ * {@link ITypedParameter#getParameterType()} like this:
+ *
+ * Defines this parameter type, setting the defined property to
+ *
+ * Notification is sent to all listeners that something has changed.
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * Signals that a problem has occurred while trying to create an instance of
+ *
+ * A parameter with a specific value. This is usually a part of a
+ *
+ * A command that has had one or more of its parameters specified. This class
+ * serves as a utility class for developers that need to manipulate commands
+ * with parameters. It handles the behaviour of generating a parameter map and a
+ * human-readable name.
+ *
+ * Generates all the possible combinations of command parameterizations for
+ * the given command. If the command has no parameters, then this is simply
+ * a parameterized version of that command. If a parameter is optional, both
+ * the included and not included cases are considered.
+ *
+ * If one of the parameters cannot be loaded due to a
+ *
+ * The syntax of the returned {@link String} is as follows:
+ *
+ * In the syntax above, sections inside square-brackets are optional. The
+ * characters in single quotes (
+ *
+ * The order of the parameters is not defined (and not important). A missing
+ *
+ * For example, the string shown below represents a serialized parameterized
+ * command that can be used to show the Resource perspective:
+ *
+ *
+ * This example shows the more general form with multiple parameters,
+ *
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * A piece of state information that can be shared between objects, and might be
+ * persisted between sessions. This can be used for commands that toggle between
+ * two states and wish to pass this state information between different
+ * handlers.
+ *
+ * This state object can either be used as a single state object shared between
+ * several commands, or one state object per command -- depending on the needs
+ * of the application.
+ *
+ * Clients may instantiate or extend this class.
+ *
+ * An event that carries with it two or more boolean values. This provides a
+ * single integer value which can then be used as a bit set.
+ *
+ * An event fired from a
+ * An event fired from a
+ * This class is not intended to be extended by clients.
+ *
+ * A manager to which listeners can be attached. This handles the management of
+ * a list of listeners -- optimizing memory and performance. All the methods on
+ * this class are guaranteed to be thread-safe.
+ *
+ * Clients may extend.
+ *
+ * An object that can exist in one of two states: defined and undefined. This is
+ * used by APIs that want to give a handle to an object, even though the object
+ * does not fully exist yet. This way, users can attach listeners to objects
+ * before they come into existence. It also protects the API from users that do
+ * not release references when they should.
+ *
+ * To enforce good coding practice, all handle objects must implement
+ *
+ * All handle objects are referred to using a single identifier. This identifier
+ * is a instance of
+ * A manager of {@link HandleObject} instances. This has some common behaviour
+ * which is shared between all such managers.
+ *
+ * Clients may extend.
+ *
* An object that is unique identifiable based on the combination of its class
* and its identifier.
*
+ * This class is not intended to be extended by clients.
+ *
+ * A context is an answer to the question "when". Other services can listen for
+ * the activation and deactivation of contexts, and change their own state in
+ * response to these changes. For example, Eclipse's key binding service listens
+ * to context activation and deactivation to determine which key bindings should
+ * be active.
+ *
+ * An instance of this interface can be obtained from an instance of
+ *
+ * The handle-based nature of this API allows it to work well with runtime
+ * plugin activation and deactivation. If a context is defined, that means that
+ * its corresponding plug-in is active. If the plug-in is then deactivated, the
+ * context will still exist but it will be undefined. An attempts to use an
+ * undefined context will result in a
+ * This class is not intended to be extended by clients.
+ *
+ * Defines this context by giving it a name, and possibly a description and
+ * a parent identifier as well. The defined property automatically becomes
+ *
+ * Notification is sent to all listeners that something has changed.
+ *
+ * Notification is sent to all registered listeners if this property
+ * changes.
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * A context manager tracks the sets of defined and enabled contexts within the
+ * application. The manager sends notification events to listeners when these
+ * sets change. It is also possible to retrieve any given context with its
+ * identifier.
+ *
+ * This class is not intended to be extended by clients.
+ *
+ * An event indicating that the set of defined context identifiers has changed.
+ *
+ * This interface may be implemented by clients.
+ *
+ * This interface may be implemented by clients.
+ *
+ * Abstract implementation for an undoable operation. At a minimum, subclasses
+ * should implement behavior for
+ * {@link IUndoableOperation#execute(dwtx.core.runtime.IProgressMonitor, dwtx.core.runtime.IAdaptable)},
+ * {@link IUndoableOperation#redo(dwtx.core.runtime.IProgressMonitor, dwtx.core.runtime.IAdaptable)},
+ * and
+ * {@link IUndoableOperation#undo(dwtx.core.runtime.IProgressMonitor, dwtx.core.runtime.IAdaptable)}.
+ * Subclasses may override this method. Default implementation. Subclasses may override this method.
+ * Default implementation. Subclasses may override this method.
+ * Default implementation. Subclasses may override this method.
+ * Default implementation. Subclasses may override this method.
+ * Default implementation. Subclasses may override this method.
+ * Default implementation. Subclasses may override this method.
+ *
+ * A base implementation of IOperationHistory that implements a linear undo and
+ * redo model . The most recently added operation is available for undo, and the
+ * most recently undone operation is available for redo.
+ *
+ * If the operation eligible for undo is not in a state where it can be undone,
+ * then no undo is available. No other operations are considered. Likewise, if
+ * the operation available for redo cannot be redone, then no redo is available.
+ *
+ * Implementations for the direct undo and redo of a specified operation are
+ * available. If a strict linear undo is to be enforced, than an
+ * IOperationApprover should be installed that prevents undo and redo of any
+ * operation that is not the most recently undone or redone operation in all of
+ * its undo contexts.
+ *
+ * The data structures used by the DefaultOperationHistory are synchronized, and
+ * entry points that modify the undo and redo history concurrently are also
+ * synchronized. This means that the DefaultOperationHistory is relatively
+ * "thread-friendly" in its implementation. Outbound notifications or operation
+ * approval requests will occur on the thread that initiated the request.
+ * Clients may use DefaultOperationHistory API from any thread; however,
+ * listeners or operation approvers that receive notifications from the
+ * DefaultOperationHistory must be prepared to receive these notifications from
+ * a background thread. Any UI access occurring inside these notifications must
+ * be properly synchronized using the techniques specified by the client's
+ * widget library.
+ *
+ * This implementation is not intended to be subclassed.
+ *
+ * Add the specified approver to the list of operation approvers consulted
+ * by the operation history before an undo or redo is allowed to proceed.
+ * This method has no effect if the instance being added is already in the
+ * list.
+ *
+ * Operation approvers must be prepared to receive these the operation
+ * approval messages from a background thread. Any UI access occurring
+ * inside the implementation must be properly synchronized using the
+ * techniques specified by the client's widget library.
+ *
+ * Add the specified listener to the list of operation history listeners
+ * that are notified about changes in the history or operations that are
+ * executed, undone, or redone. This method has no effect if the instance
+ * being added is already in the list.
+ *
+ * Operation history listeners must be prepared to receive notifications
+ * from a background thread. Any UI access occurring inside the
+ * implementation must be properly synchronized using the techniques
+ * specified by the client's widget library.
+ *
+ * IAdvancedUndoableOperation defines an interface for undoable operations that
+ * modify one or more elements in a model and attempt to keep model listeners up
+ * to date with changes that occur in the undo and redo history involving particular
+ * model elements. It also defines methods for computing the validity of an operation
+ * for undo or redo before attempting to perform the undo or redo.
+ *
+ * This interface is intended to be used by legacy frameworks that are adapting
+ * their original undo and redo support to this framework. The methods in this
+ * interface allow legacy clients to maintain features not supported in the
+ * basic operations framework.
+ *
+ * An operation history notification about this operation is about to be
+ * sent to operation history listeners. Any preparation needed before
+ * listeners are notified about this operation should be performed here.
+ *
+ *
+ * This method has been added to support legacy undo frameworks that are
+ * adapting to IUndoableOperation. Operations that previously relied on
+ * notification from their containing history or stack before any listeners
+ * are notified about changes to the operation should implement this
+ * interface.
+ *
+ * @param event
+ * the event that is about to be sent with the pending
+ * notification
+ *
+ */
+ void aboutToNotify(OperationHistoryEvent event);
+
+ /**
+ *
+ * Return an array of objects that are affected by executing, undoing, or
+ * redoing this operation. If it cannot be determined which objects are
+ * affected, return null.
+ *
+ * IAdvancedUndoableOperation2 defines a method for computing the validity of
+ * executing an operation before attempting to execute it. It also defines a way
+ * for clients to specify that computing status should be done quietly, without
+ * consulting the user. This interface is useful when implementing
+ * {@link IOperationApprover2}, or any other object that performs validation of
+ * the undo history. It also allows operations to specify whether they should be
+ * run in the UI thread.
+ *
+ * If the status computation methods typically need to consult the user in
+ * order to determine the severity of a particular situation, the least
+ * severe status that could be chosen by the user should be returned when
+ * this flag is
+ * ICompositeOperation defines an undoable operation that is composed of child
+ * operations. Requests to execute, undo, or redo a composite result in the the
+ * execution, undo, or redo of the composite as a whole. Similarly, a request to
+ * dispose the composite should result in all child operations being disposed.
+ *
+ * Add the specified operation as a child of this operation.
+ *
+ * Remove the specified operation from this operation.
+ *
+ * The composite operation should dispose the operation as part of removing
+ * it.
+ *
+ * This message has no effect if the original undo context is not present in
+ * the receiver.
+ *
+ * @param original the undo context which is to be replaced
+ * @param replacement the undo context which is replacing the original
+ *
+ */
+ void replaceContext(IUndoContext original, IUndoContext replacement);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/IOperationApprover.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/IOperationApprover.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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
+ * IOperationApprover defines an interface for approving the undo or redo of a
+ * particular operation within an operation history. Operations that are
+ * candidates for undo or redo have already been validated against their current
+ * state and according to the rules of the history.
+ *
+ * By the time an IOperationApprover is consulted, the undo has already been
+ * requested. Approvers should return an
+ * Operation approvers must be prepared to receive the approval messages from a
+ * background thread. Any UI access occurring inside the implementation must be
+ * properly synchronized using the techniques specified by the client's widget
+ * library.
+ *
+ * By the time an IOperationApprover2 is consulted, the execution has already
+ * been requested and it has been determined that the operation is valid.
+ * Approvers should return an
+ * Like {@link IOperationApprover}, implementers of this extension must be
+ * prepared to receive the approval messages from a background thread. Any UI
+ * access occurring inside the implementation must be properly synchronized
+ * using the techniques specified by the client's widget library.
+ *
+ * IOperationHistory tracks a history of operations that can be undone or
+ * redone. Operations are added to the history once they have been initially
+ * executed. Clients may choose whether to have the operations history perform
+ * the initial execution or to simply add an already-executed operation to the
+ * history.
+ *
+ * Once operations are added to the history, the methods
+ * {@link #canRedo(IUndoContext)} and {@link #canUndo(IUndoContext)} are used to
+ * determine whether there is an operation available for undo and redo in a
+ * given undo context. The context-based protocol implies that there is only one
+ * operation that can be undone or redone at a given time in a given context.
+ * This is typical of a linear undo model, when only the most recently executed
+ * operation is available for undo. When this protocol is used, a linear model
+ * is enforced by the history.
+ *
+ * It is up to clients to determine how to maintain a history that is invalid or
+ * stale. For example, when the most recent operation for a context cannot be
+ * performed, clients may wish to dispose the history for that context.
+ *
+ * Additional protocol allows direct undo and redo of a specified operation,
+ * regardless of its position in the history. When a more flexible undo model is
+ * supported, these methods can be implemented to undo and redo directly
+ * specified operations. If an implementer of IOperationHistory does not allow
+ * direct undo and redo, these methods can return a status indicating that it is
+ * not allowed.
+ *
+ * Listeners ({@link IOperationHistoryListener}) can listen for notifications
+ * about changes in the history (operations added or removed), and for
+ * notification before and after any operation is executed, undone or redone.
+ * Notification of operation execution only occurs when clients direct the
+ * history to execute the operation. If the operation is added after it is
+ * executed, there can be no notification of its execution.
+ *
+ * {@link IOperationApprover} defines an interface for approving an undo or redo
+ * before it occurs. This is useful for injecting policy-decisions into the undo
+ * model - whether direct undo and redo are supported, or warning the user about
+ * certain kinds of operations. It can also be used when clients maintain state
+ * related to an operation and need to determine whether an undo or redo will
+ * cause any conflicts with their local state.
+ *
+ * Add the specified operation to the history without executing it. The
+ * operation should have already been executed by the time it is added to
+ * the history. Listeners will be notified that the operation was added to
+ * the history (
+ * Add the specified approver to the list of operation approvers consulted
+ * by the operation history before an undo or redo is attempted.
+ *
+ * Add the specified listener to the list of operation history listeners
+ * that are notified about changes in the history or operations that are
+ * executed, undone, or redone.
+ *
+ * Close the current operation. If the operation has successfully completed,
+ * send listeners a
+ * Any operations that are executed and added after this operation is closed
+ * will no longer be considered part of this operation.
+ *
+ * This method has no effect if the caller has not previously called
+ * {@link #openOperation}.
+ *
+ * Return whether there is a valid redoable operation available in the given
+ * context.
+ *
+ * Return whether there is a valid undoable operation available in the given
+ * context
+ *
+ * Dispose of the specified context in the history. All operations that have
+ * only the given context will be disposed. References to the context in
+ * operations that have more than one context will also be removed. A
+ * history notification for the removal of each operation being disposed
+ * will be sent.
+ *
+ * Execute the specified operation and add it to the operations history if
+ * successful. This method is used by clients who wish operation history
+ * listeners to receive notifications before and after the execution of the
+ * operation. Execution of the operation is subject to approval by any
+ * registered {@link IOperationApprover2}. If execution is approved,
+ * listeners will be notified before (
+ * If the operation successfully executes, an additional notification that
+ * the operation has been added to the history (
+ * The severity code in the returned status describes whether the operation
+ * succeeded and whether it was added to the history.
+ *
+ * Return the limit on the undo and redo history for a particular context.
+ *
+ * Get the array of operations in the redo history for a the specified undo
+ * context. The operations are in the order that they were added to the
+ * history, with the most recently undone operation appearing last in the
+ * array. This history is used LIFO (last in, first out) when successive
+ * "Redo" commands are invoked.
+ *
+ *
+ * Get the operation that will next be redone in the given undo context.
+ *
+ * Get the array of operations in the undo history for the specified undo
+ * context. The operations are in the order that they were added to the
+ * history, with the most recently added operation appearing last in the
+ * array. This history is used LIFO (last in, first out) when successive
+ * "Undo" commands are invoked.
+ *
+ * Open this composite operation and consider it an operation that contains
+ * other related operations. Consider all operations that are subsequently
+ * executed or added to be part of this operation. When an operation is
+ * opened, listeners will immediately receive a notification for the opened
+ * operation. The specific notification depends on the mode in which the
+ * operation is opened (
+ * Note: This method is intended to be used by legacy undo frameworks that
+ * do not expect related undo operations to appear in the same undo history
+ * as the triggering undo operation. When an operation is open, any
+ * subsequent requests to execute, add, undo, or redo another operation will
+ * result in that operation being added to the open operation. Once the
+ * operation is closed, the composite will be considered an atomic
+ * operation. Clients should not modify the composite directly (by adding
+ * and removing children) while it is open.
+ *
+ * When a composite is open, operations that are added to the history will
+ * be considered part of the open operation instead. Operations that are
+ * executed while a composite is open will first be executed and then added
+ * to the composite.
+ *
+ * Open operations cannot be nested. If this method is called when a
+ * different operation is open, it is presumed to be an application coding
+ * error and this method will throw an IllegalStateException.
+ *
+ * The specified operation has changed in some way since it was added to the
+ * operation history. Notify listeners with an OPERATION_CHANGED event.
+ *
+ * Get the operation that will next be undone in the given undo context.
+ *
+ * Redo the most recently undone operation in the given context. The redo of
+ * the operation is subject to approval by any registered
+ * {@link IOperationApprover} before it is attempted.
+ *
+ * The severity code in the returned status describes whether the operation
+ * succeeded and whether it remains in the history.
+ * Other severity codes (
+ * Redo the specified operation. The redo of the operation is subject to
+ * approval by any registered {@link IOperationApprover} before it is
+ * attempted.
+ *
+ * The severity code in the returned status describes whether the operation
+ * succeeded and whether it remains in the history.
+ * Other severity codes (
+ * Remove the specified operation approver from the list of operation
+ * approvers that are consulted before an operation is undone or redone.
+ *
+ * Remove the specified listener from the list of operation history
+ * listeners.
+ *
+ * Replace the specified operation in the undo or redo history with the
+ * provided list of replacements. This protocol is typically used when a
+ * composite is broken up into its atomic parts. The replacements will be
+ * inserted so that the first replacement will be the first of the
+ * replacements to be undone or redone. Listeners will be notified about the
+ * removal of the replaced element and the addition of each replacement.
+ *
+ * Set the limit on the undo and redo history for a particular context.
+ *
+ * Undo the most recently executed operation in the given context. The undo
+ * of the operation is subject to approval by any registered
+ * {@link IOperationApprover} before it is attempted.
+ *
+ * The severity code in the returned status describes whether the operation
+ * succeeded and whether it remains in the history.
+ * Other severity codes (
+ * Undo the specified operation. The undo of the operation is subject to
+ * approval by any registered {@link IOperationApprover} before it is
+ * attempted.
+ *
+ * The severity code in the returned status describes whether the operation
+ * succeeded and whether it remains in the history.
+ * Other severity codes (
+ * This interface is used to listen to notifications from an IOperationHistory.
+ * The supplied OperationHistoryEvent describes the particular notification.
+ *
+ * Operation history listeners must be prepared to receive notifications from a
+ * background thread. Any UI access occurring inside the implementation must be
+ * properly synchronized using the techniques specified by the client's widget
+ * library.
+ *
+ * An undo context is used to "tag" operations as being applicable to a certain
+ * context. The undo context is used to filter the history of operations
+ * available for undo or redo so that only operations appropriate for a given
+ * undo context are shown when the application is presenting that context.
+ *
+ * The scope of an undo context is defined by the application that is making
+ * undo and redo of operations available. Undo contexts may be related to
+ * application models, or may be associated with UI objects that are providing
+ * undo and redo support.
+ *
+ * An undo context may be defined as "matching" another context. This allows
+ * applications to provide specialized implementations of an undo context that
+ * will appear in the operation history for their matching context.
+ *
+ * @since 3.1
+ */
+
+public interface IUndoContext {
+
+ /**
+ * Get the label that describes the undo context.
+ *
+ * @return the label for the context.
+ */
+ public String getLabel();
+
+ /**
+ * Return whether the specified context is considered a match for the
+ * receiving context. When a context matches another context, operations
+ * that have the context are considered to also have the matching context.
+ *
+ * @param context
+ * the context to be checked against the receiving context.
+ *
+ * @return
+ * IUndoableOperation defines an operation that can be executed, undone, and
+ * redone. Operations typically have fully defined parameters. That is, they are
+ * usually created after the user has been queried for any input needed to
+ * define the operation.
+ *
+ * Operations determine their ability to execute, undo, or redo according to the
+ * current state of the application. They do not make decisions about their
+ * validity based on where they occur in the operation history. That is left to
+ * the particular operation history.
+ *
+ * Add the specified context to the operation. If a context equal to the
+ * specified context is already present, do not add it again. Note that
+ * determining whether a context is already present is based on equality,
+ * not whether the context matches ({@link IUndoContext#matches(IUndoContext)})
+ * another context.
+ *
+ * Returns whether the operation can be executed in its current state.
+ *
+ * Note: The computation for this method must be fast, as it is called
+ * frequently. If necessary, this method can be optimistic in its
+ * computation (returning true) and later perform more time-consuming
+ * computations during the actual execution of the operation, returning the
+ * appropriate status if the operation cannot actually execute at that time.
+ *
+ * Returns whether the operation can be redone in its current state.
+ *
+ * Note: The computation for this method must be fast, as it is called
+ * frequently. If necessary, this method can be optimistic in its
+ * computation (returning true) and later perform more time-consuming
+ * computations during the actual redo of the operation, returning the
+ * appropriate status if the operation cannot actually be redone at that
+ * time.
+ *
+ * Returns whether the operation can be undone in its current state.
+ *
+ * Note: The computation for this method must be fast, as it is called
+ * frequently. If necessary, this method can be optimistic in its
+ * computation (returning true) and later perform more time-consuming
+ * computations during the actual undo of the operation, returning the
+ * appropriate status if the operation cannot actually be undone at that
+ * time.
+ *
+ * Returns the array of contexts that have been assigned to the operation.
+ *
+ * This method may be called by the operation history from inside a
+ * synchronized block. To avoid deadlock conditions, implementers of this
+ * method must avoid dispatching and waiting on threads that modify the
+ * operation history during this method.
+ *
+ * Returns whether the operation has a matching context for the specified
+ * context.
+ *
+ * This method may be called by the operation history from inside a
+ * synchronized block. To avoid deadlock conditions, implementers of this
+ * method must avoid dispatching and waiting on threads that modify the
+ * operation history during this method.
+ *
+ * An operation approver that enforces a strict linear undo. It does not allow
+ * the undo or redo of any operation that is not the latest available operation
+ * in all of its undo contexts. This class may be instantiated by clients.
+ *
+ * An abstract class for detecting violations in a strict linear undo/redo
+ * model. Once a violation is detected, subclasses implement the specific
+ * behavior for indicating whether or not the undo/redo should proceed.
+ *
+ * An undo context that can be used to represent any given object. Clients
+ * can add matching contexts to this context. This class may be instantiated
+ * by clients.
+ *
+ * OperationHistoryEvent is used to communicate changes that occur in a
+ * DefaultOperationHistory, including the addition or removal of operations, and
+ * the execution, undo, and redo of operations.
+ *
+ * Operation history listeners must be prepared to receive notifications from a
+ * background thread. Any UI access occurring inside the implementation must be
+ * properly synchronized using the techniques specified by the client's widget
+ * library.
+ *
+ * This class is used to maintain the instance of the operation history that
+ * should be used by classes that access the undo or redo history and add
+ * undoable operations to the history.
+ *
+ *
+ * It is intended that an application can create an operation history appropriate
+ * for its needs and set it into this class. Otherwise, a default operation history
+ * will be created. The operation history may only be set one time. All classes that
+ * access an operations history use this class to obtain the correct instance.
+ *
+ * @since 3.1
+ */
+public final class OperationHistoryFactory {
+
+ private static IOperationHistory operationHistory;
+
+ /**
+ * Return the operation history to be used for managing undoable operations.
+ *
+ * @return the operation history to be used for executing, undoing, and
+ * redoing operations.
+ */
+ public static IOperationHistory getOperationHistory() {
+ if (operationHistory is null) {
+ operationHistory = new DefaultOperationHistory();
+ }
+ return operationHistory;
+ }
+
+ /**
+ * Set the operation history to be used for managing undoable operations.
+ * This method may only be called one time, and must be called before any
+ * request to get the history. Attempts to set the operation history will
+ * be ignored after it has been already set, or after a default one has
+ * been created.
+ *
+ * @param history
+ * the operation history to be used for executing, undoing, and
+ * redoing operations.
+ */
+ public static void setOperationHistory(IOperationHistory history) {
+ // If one has already been set or created, ignore this request.
+ if (operationHistory is null) {
+ operationHistory = history;
+ }
+ }
+
+ private this() {
+ // may not be instantiated
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/OperationStatus.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/OperationStatus.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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
+ * OperationStatus describes the status of a request to execute, undo, or redo
+ * an operation. This class may be instantiated by clients.
+ *
+ * This class may be instantiated by clients.
+ *
+ * This message has no effect if the original undo context is not present in
+ * the receiver.
+ *
+ * @param original
+ * the undo context which is to be replaced
+ * @param replacement
+ * the undo context which is replacing the original
+ * @since 3.2
+ */
+ public void replaceContext(IUndoContext original, IUndoContext replacement) {
+
+ // first check the triggering operation
+ if (triggeringOperation !is null
+ && triggeringOperation.hasContext(original)) {
+ if ( auto trg = cast(IContextReplacingOperation)triggeringOperation ) {
+ trg.replaceContext(original, replacement);
+ } else {
+ triggeringOperation.removeContext(original);
+ triggeringOperation.addContext(replacement);
+ }
+ }
+ // Now check all the children
+ for (int i = 0; i < children.size(); i++) {
+ IUndoableOperation child = children.get(i);
+ if (child.hasContext(original)) {
+ if ( auto c = cast(IContextReplacingOperation)child ) {
+ c.replaceContext(
+ original, replacement);
+ } else {
+ child.removeContext(original);
+ child.addContext(replacement);
+ }
+ }
+ }
+ recomputeContexts();
+ }
+
+ /**
+ * Add the specified context to the operation. Overridden in
+ * TriggeredOperations to add the specified undo context to the triggering
+ * operation.
+ *
+ * @param context
+ * the context to be added
+ *
+ * @since 3.2
+ */
+ public void addContext(IUndoContext context) {
+ if (triggeringOperation !is null) {
+ triggeringOperation.addContext(context);
+ recomputeContexts();
+ }
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/UndoContext.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/UndoContext.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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
+ * A simple, lightweight undo context that can be used to tag any operation. It
+ * does not provided a specialized label. This class may be instantiated by
+ * clients. This class may also be subclassed.
+ *
+ * Get the label that describes the undo context. The default implementation
+ * returns the empty String. Subclasses may override.
+ *
+ * Return whether the specified context is considered a match for the
+ * receiving context. When a context matches another context, operations
+ * that have the context are considered to also have the matching context.
+ * The default implementation checks whether the supplied context is
+ * identical to this context. Subclasses may override.
+ *
+ * A utility class for printing tracing output to the console.
+ *
+ * Clients must not extend or instantiate this class.
+ *
+ * Prints a tracing message to standard out. The message is prefixed by a
+ * component identifier and some separator. See the example below.
+ *
+ * An operation context that matches to any context. It can be used to
+ * get an unfiltered (global) history.
+ *
+ * Assertion failure exceptions, like most runtime exceptions, are
+ * thrown when something is misbehaving. Assertion failures are invariably
+ * unspecified behavior; consequently, clients should never rely on
+ * these being thrown (and certainly should not being catching them
+ * specifically).
+ *
+ * This class can be used without OSGi running.
+ *
+ * This class is not intended to be instantiated or sub-classed by clients.
+ *
+ * This class can be used without OSGi running.
+ *
+ * This class is not intended to be instantiated or sub-classed by clients.
+ *
+ * Core exceptions contain a status object describing the
+ * cause of the exception.
+ *
+ * This class can be used without OSGi running.
+ *
+ * Adaptable objects can be dynamically extended to provide different
+ * interfaces (or "adapters"). Adapters are created by adapter
+ * factories, which are in turn managed by type by adapter managers.
+ *
+ * This interface can be used without OSGi running.
+ *
+ * Clients may implement this interface, or obtain a default implementation
+ * of this interface by subclassing
+ * This interface can be used without OSGi running.
+ *
+ * Clients may implement this interface.
+ *
+ * This method is generally used by an adapter manager
+ * to discover which adapter types are supported, in advance
+ * of dispatching any actual
+ * Adapter factories can be registered programmatically using the
+ * The following code snippet shows how one might register an adapter of type
+ *
+ *
+ *
+ * This interface can be used without OSGi running.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ * Note that the returned types do not guarantee that
+ * a subsequent call to
+ * Note that this method will never cause plug-ins to be loaded. If the
+ * only suitable factory is not yet loaded, this method will return
+ * Note that this method will never cause plug-ins to be loaded. If the
+ * only suitable factory is not yet loaded, this method will return
+ * Note that a return value of
+ * One of the following values can be returned:
+ * Note that unlike the
+ * If the type being extended is a class, the given factory's adapters are
+ * available on instances of that class and any of its subclasses. If it is
+ * an interface, the adapters are available to all classes that directly or
+ * indirectly implement that interface.
+ *
+ * This interface can be used without OSGi running.
+ *
+ * Clients may implement this interface.
+ *
+ * Note that paths are value objects; all operations on paths
+ * return a new path; the path that is operated on is unscathed.
+ *
+ * UNC paths are denoted by leading double-slashes such
+ * as
+ * This interface can be used without OSGi running.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ * The file extension portion is defined as the string
+ * following the last period (".") character in the last segment.
+ * The given extension should not include a leading ".".
+ *
+ * If this path already has a trailing separator,
+ * this path is returned.
+ *
+ * Equality for paths is defined to be: same sequence of segments,
+ * same absolute/relative status, and same device.
+ * Trailing separators are disregarded.
+ * Paths are not generally considered equal to objects other than paths.
+ *
+ * The file extension portion is defined as the string
+ * following the last period (".") character in the last segment.
+ * If there is no period in the last segment, the path has no
+ * file extension portion. If the last segment ends in a period,
+ * the file extension portion is the empty string.
+ *
+ * Note: In the root path ("/"), the separator is considered to
+ * be leading rather than trailing.
+ *
+ * Absolute paths start with a path separator.
+ * A root path, like
+ * An empty path is a prefix of all paths with the same device; a root path is a prefix of
+ * all absolute paths with the same device.
+ *
+ * The root path is the absolute non-UNC path with zero segments;
+ * e.g.,
+ * The file extension portion is defined as the string
+ * following the last period (".") character in the last segment.
+ * If there is no period in the last segment, the path has no
+ * file extension portion. If the last segment ends in a period,
+ * the file extension portion is the empty string.
+ *
+ * If this path has a trailing separator, it will still
+ * have a trailing separator after the last segments are removed
+ * (assuming there are some segments left). If there is no
+ * trailing separator, the result will not have a trailing
+ * separator.
+ * If the number equals or exceeds the number
+ * of segments in this path, a path with no segments is returned.
+ *
+ * If this path does not have a trailing separator,
+ * this path is returned.
+ *
+ * Note that both root and empty paths have 0 segments.
+ *
+ * For example, "C:" and "Server/Volume:" are typical device ids.
+ *
+ * This string is suitable for passing to
+ * This string is suitable for passing to
+ * Example result strings (without and with device id):
+ *
+ * If this path has a trailing separator, the result will too
+ * (assuming there are some segments left). If there is no
+ * trailing separator, the result will not have a trailing
+ * separator.
+ * Copying up to segment zero simply means making an copy with
+ * no path segments.
+ *
+ * All activity is broken down into a linear sequence of tasks against
+ * which progress is reported. When a task begins, a
+ * A request to cancel an operation can be signaled using the
+ *
+ * Since notification is synchronous with the activity itself, the listener should
+ * provide a fast and robust implementation. If the handling of notifications would
+ * involve blocking operations, or operations which might throw uncaught exceptions,
+ * the notifications should be queued, and the actual processing deferred (or perhaps
+ * delegated to a separate thread).
+ *
+ * This interface can be used without OSGi running.
+ *
+ * Clients may implement this interface.
+ *
+ * When a monitor that supports this extension is passed to an operation, the
+ * operation should call
+ * This interface can be used without OSGi running.
+ *
+ * Clients may implement this interface.
+ *
+ * If the caller is blocked by a currently executing job, this method will return
+ * an
+ * This interface can be used without OSGi running.
+ *
+ * Clients may implement this interface.
+ *
+ * A status carries the following information:
+ * IHandler
. This
+ * abstract implementation provides support for handler listeners. You should
+ * subclass from this method unless you want to implement your own listener
+ * support. Subclasses should call
+ * {@link AbstractHandler#fireHandlerChanged(HandlerEvent)}when the handler
+ * changes. Subclasses can also override {@link AbstractHandler#isEnabled()} and
+ * {@link AbstractHandler#isHandled()}.
+ * AbstractHandler
in
+ * dwtx.ui.workbench
, and clients should be wary of
+ * overriding this behaviour. If this method is overridden, then the first
+ * line of the method should be "super.fireHandlerChanged(handlerEvent);
".
+ * null
.
+ */
+ protected void fireHandlerChanged(HandlerEvent handlerEvent) {
+ if (handlerEvent is null) {
+ throw new NullPointerException();
+ }
+
+ Object[] listeners = getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IHandlerListener listener = cast(IHandlerListener) listeners[i];
+ listener.handlerChanged(handlerEvent);
+ }
+ }
+
+ /**
+ * Whether this handler is capable of executing at this time. Subclasses may
+ * override this method.
+ *
+ * @return true
+ */
+ public bool isEnabled() {
+ return true;
+ }
+
+ /**
+ * Whether this handler is capable of handling delegated responsibilities at
+ * this time. Subclasses may override this method.
+ *
+ * @return true
+ */
+ public bool isHandled() {
+ return true;
+ }
+
+ /**
+ * AbstractHandler
in
+ * dwtx.ui.workbench
, and clients should be wary of
+ * overriding this behaviour. If this method is overridden, then the return
+ * value should include "super.hasListeners() ||
".
+ * null
.
+ */
+ private Map!(String,State) states = null;
+
+ /**
+ * null
.
+ * @param state
+ * The state to add; must not be null
.
+ */
+ public void addState(String stateId, State state) {
+ if (state is null) {
+ throw new NullPointerException("Cannot add a null state"); //$NON-NLS-1$
+ }
+
+ if (states is null) {
+ states = new HashMap!(String,State)(/+3+/);
+ }
+ states.add(stateId, state);
+ state.addListener(this);
+ handleStateChange(state, null);
+ }
+
+ public final State getState(String stateId) {
+ if ((states is null) || (states.drained())) {
+ return null;
+ }
+
+ return cast(State) states.get(stateId);
+ }
+
+ public final String[] getStateIds() {
+ if ((states is null) || (states.drained())) {
+ return null;
+ }
+
+ String[] res;
+ foreach( k, v; states.keys() ){
+ res ~= k;
+ }
+ return res;
+ }
+
+ /**
+ * null
.
+ */
+ public void removeState(String stateId) {
+ if (stateId is null) {
+ throw new NullPointerException("Cannot remove a null state"); //$NON-NLS-1$
+ }
+
+ State state = cast(State) states.get(stateId);
+ if (state !is null) {
+ state.removeListener(this);
+ if (states !is null) {
+ states.remove(state);
+ if (states.drained()) {
+ states = null;
+ }
+ }
+ }
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/AbstractParameterValueConverter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/AbstractParameterValueConverter.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 converter
attribute of the
+ * commandParameterType
elemement of the
+ * dwtx.ui.commands
extension-point. Objects implementing
+ * this interface may also be passed directly to
+ * {@link ParameterType#define(String, AbstractParameterValueConverter)} by
+ * clients.
+ * null
+ * @return the object described by the command parameter value string; may
+ * be null
+ * @throws ParameterValueConversionException
+ * if an object cannot be produced from the
+ * parameterValue
string
+ */
+ public abstract Object convertToObject(String parameterValue);
+
+ /**
+ * Converts a command parameter value object into a string that encodes a
+ * reference to the object or serialization of the object.
+ *
+ * @param parameterValue
+ * an object to convert into an identifying string; may be
+ * null
+ * @return a string describing the provided object; may be null
+ * @throws ParameterValueConversionException
+ * if a string reference or serialization cannot be provided for
+ * the parameterValue
+ */
+ public abstract String convertToString(Object parameterValue);
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/Category.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/Category.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
if there are no listeners.
+ */
+ private ArraySeq!(ICategoryListener) categoryListeners;
+
+ /**
+ * Constructs a new instance of Category
based on the given
+ * identifier. When a category is first constructed, it is undefined.
+ * Category should only be constructed by the CommandManager
+ * to ensure that identifier remain unique.
+ *
+ * @param id
+ * The identifier for the category. This value must not be
+ * null
, and must be unique amongst all
+ * categories.
+ */
+ this(String id) {
+ super(id);
+ }
+
+ /**
+ * Adds a listener to this category that will be notified when this
+ * category's state changes.
+ *
+ * @param categoryListener
+ * The listener to be added; must not be null
.
+ */
+ public final void addCategoryListener(
+ ICategoryListener categoryListener) {
+ if (categoryListener is null) {
+ throw new NullPointerException();
+ }
+ if (categoryListeners is null) {
+ categoryListeners = new ArraySeq!(ICategoryListener);
+ }
+ if (!categoryListeners.contains(categoryListener)) {
+ categoryListeners.append(categoryListener);
+ }
+ }
+
+ /**
+ * true
.
+ * null
.
+ * @param description
+ * The description for this command; may be null
.
+ */
+ public final void define(String name, String description) {
+ if (name is null) {
+ throw new NullPointerException(
+ "The name of a command cannot be null"); //$NON-NLS-1$
+ }
+
+ bool definedChanged = !this.defined;
+ this.defined = true;
+
+ bool nameChanged = !Util.equals(this.name, name);
+ this.name = name;
+
+ bool descriptionChanged = !Util.equals(this.description,
+ description);
+ this.description = description;
+
+ fireCategoryChanged(new CategoryEvent(this, definedChanged,
+ descriptionChanged, nameChanged));
+ }
+
+ /**
+ * Notifies the listeners for this category that it has changed in some way.
+ *
+ * @param categoryEvent
+ * The event to send to all of the listener; must not be
+ * null
.
+ */
+ private final void fireCategoryChanged(CategoryEvent categoryEvent) {
+ if (categoryEvent is null) {
+ throw new NullPointerException();
+ }
+ if (categoryListeners !is null) {
+ foreach( listener; categoryListeners ){
+ listener.categoryChanged(categoryEvent);
+ }
+ }
+ }
+
+ /**
+ * Removes a listener from this category.
+ *
+ * @param categoryListener
+ * The listener to be removed; must not be null
.
+ *
+ */
+ public final void removeCategoryListener(
+ ICategoryListener categoryListener) {
+ if (categoryListener is null) {
+ throw new NullPointerException();
+ }
+
+ if (categoryListeners !is null) {
+ categoryListeners.remove(categoryListener);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.core.commands.common.HandleObject#toString()
+ */
+ public String toString() {
+ if (string is null) {
+ string = Format( "Category({},{},{},{})", id, name, description, defined );
+ }
+ return string;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.core.commands.common.HandleObject#undefine()
+ */
+ public void undefine() {
+ string = null;
+
+ final bool definedChanged = defined;
+ defined = false;
+
+ final bool nameChanged = name !is null;
+ name = null;
+
+ final bool descriptionChanged = description !is null;
+ description = null;
+
+ fireCategoryChanged(new CategoryEvent(this, definedChanged,
+ descriptionChanged, nameChanged));
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/CategoryEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/CategoryEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 Category
.
+ * null
.
+ */
+ private final Category category;
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param category
+ * the instance of the interface that changed.
+ * @param definedChanged
+ * true, iff the defined property changed.
+ * @param descriptionChanged
+ * true, iff the description property changed.
+ * @param nameChanged
+ * true, iff the name property changed.
+ */
+ public this(Category category, bool definedChanged,
+ bool descriptionChanged, bool nameChanged) {
+ super(definedChanged, descriptionChanged, nameChanged);
+
+ if (category is null) {
+ throw new NullPointerException();
+ }
+ this.category = category;
+ }
+
+ /**
+ * Returns the instance of the interface that changed.
+ *
+ * @return the instance of the interface that changed. Guaranteed not to be
+ * null
.
+ */
+ public final Category getCategory() {
+ return category;
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/Command.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/Command.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,1103 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 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 handlers
extension point). This provides another level of
+ * indirection.
+ * NotDefinedException
. If
+ * you need to know when a command changes from defined to undefined (or vice
+ * versa), then attach a command listener.
+ * true
if commands should print
+ * information to System.out
when executing.
+ */
+ public static bool DEBUG_COMMAND_EXECUTION = false;
+
+ /**
+ * This flag can be set to true
if commands should print
+ * information to System.out
when changing handlers.
+ */
+ public static bool DEBUG_HANDLERS = false;
+
+ /**
+ * This flag can be set to a particular command identifier if only that
+ * command should print information to System.out
when
+ * changing handlers.
+ */
+ public static String DEBUG_HANDLERS_COMMAND_ID = null;
+
+ /**
+ * The category to which this command belongs. This value should not be
+ * null
unless the command is undefined.
+ */
+ private Category category = null;
+
+ /**
+ * A collection of objects listening to the execution of this command. This
+ * collection is null
if there are no listeners.
+ */
+ private /+transient+/ ListenerList executionListeners = null;
+
+ /**
+ * The handler currently associated with this command. This value may be
+ * null
if there is no handler currently.
+ */
+ private /+transient+/ IHandler handler = null;
+
+ /**
+ * The help context identifier for this command. This can be
+ * null
if there is no help currently associated with the
+ * command.
+ *
+ * @since 3.2
+ */
+ private String helpContextId;
+
+ /**
+ * The ordered array of parameters understood by this command. This value
+ * may be null
if there are no parameters, or if the command
+ * is undefined. It may also be empty.
+ */
+ private IParameter[] parameters = null;
+
+ /**
+ * The type of the return value of this command. This value may be
+ * null
if the command does not declare a return type.
+ *
+ * @since 3.2
+ */
+ private ParameterType returnType = null;
+
+ /**
+ * Our command will listen to the active handler for enablement changes so
+ * that they can be fired from the command itself.
+ *
+ * @since 3.3
+ */
+ private IHandlerListener handlerListener;
+
+ /**
+ * Constructs a new instance of Command
based on the given
+ * identifier. When a command is first constructed, it is undefined.
+ * Commands should only be constructed by the CommandManager
+ * to ensure that the identifier remains unique.
+ *
+ * @param id
+ * The identifier for the command. This value must not be
+ * null
, and must be unique amongst all commands.
+ */
+ this(String id) {
+ super(id);
+ }
+
+ /**
+ * Adds a listener to this command that will be notified when this command's
+ * state changes.
+ *
+ * @param commandListener
+ * The listener to be added; must not be null
.
+ */
+ public final void addCommandListener(ICommandListener commandListener) {
+ if (commandListener is null) {
+ throw new NullPointerException("Cannot add a null command listener"); //$NON-NLS-1$
+ }
+ addListenerObject(cast(Object)commandListener);
+ }
+
+ /**
+ * Adds a listener to this command that will be notified when this command
+ * is about to execute.
+ *
+ * @param executionListener
+ * The listener to be added; must not be null
.
+ */
+ public final void addExecutionListener(
+ IExecutionListener executionListener) {
+ if (executionListener is null) {
+ throw new NullPointerException(
+ "Cannot add a null execution listener"); //$NON-NLS-1$
+ }
+
+ if (executionListeners is null) {
+ executionListeners = new ListenerList(ListenerList.IDENTITY);
+ }
+
+ executionListeners.add(cast(Object)executionListener);
+ }
+
+ /**
+ * null
.
+ * @param state
+ * The state to add; must not be null
.
+ * @since 3.2
+ */
+ public void addState(String id, State state) {
+ super.addState(id, state);
+ state.setId(id);
+ if ( auto h = cast(IObjectWithState)handler) {
+ h.addState(id, state);
+ }
+ }
+
+ /**
+ * Compares this command with another command by comparing each of its
+ * non-transient attributes.
+ *
+ * @param object
+ * The object with which to compare; must be an instance of
+ * Command
.
+ * @return A negative integer, zero or a postivie integer, if the object is
+ * greater than, equal to or less than this command.
+ */
+ public final int compareTo(Object object) {
+ Command castedObject = cast(Command) object;
+ int compareTo = Util.compare(category, castedObject.category);
+ if (compareTo is 0) {
+ compareTo = Util.compare(defined, castedObject.defined);
+ if (compareTo is 0) {
+ compareTo = Util.compare(description, castedObject.description);
+ if (compareTo is 0) {
+ compareTo = Util.compare(cast(Object)handler, cast(Object)castedObject.handler);
+ if (compareTo is 0) {
+ compareTo = Util.compare(id, castedObject.id);
+ if (compareTo is 0) {
+ compareTo = Util.compare(name, castedObject.name);
+ if (compareTo is 0) {
+ Object[] left, right;
+ foreach( p; parameters ){
+ left ~= cast(Object)p;
+ }
+ foreach( p; castedObject.parameters ){
+ right ~= cast(Object)p;
+ }
+ compareTo = Util.compare(left,
+ right);
+ }
+ }
+ }
+ }
+ }
+ }
+ return compareTo;
+ }
+
+ /**
+ * true
.
+ * null
.
+ * @param description
+ * The description for this command; may be null
.
+ * @param category
+ * The category for this command; must not be null
.
+ * @since 3.2
+ */
+ public final void define(String name, String description,
+ Category category) {
+ define(name, description, category, null);
+ }
+
+ /**
+ * true
.
+ * null
.
+ * @param description
+ * The description for this command; may be null
.
+ * @param category
+ * The category for this command; must not be null
.
+ * @param parameters
+ * The parameters understood by this command. This value may be
+ * either null
or empty if the command does not
+ * accept parameters.
+ */
+ public final void define(String name, String description,
+ Category category, IParameter[] parameters) {
+ define(name, description, category, parameters, null);
+ }
+
+ /**
+ * true
.
+ * null
.
+ * @param description
+ * The description for this command; may be null
.
+ * @param category
+ * The category for this command; must not be null
.
+ * @param parameters
+ * The parameters understood by this command. This value may be
+ * either null
or empty if the command does not
+ * accept parameters.
+ * @param returnType
+ * The type of value returned by this command. This value may be
+ * null
if the command does not declare a return
+ * type.
+ * @since 3.2
+ */
+ public final void define(String name, String description,
+ Category category, IParameter[] parameters,
+ ParameterType returnType) {
+ define(name, description, category, parameters, returnType, null);
+ }
+
+ /**
+ * true
.
+ * null
.
+ * @param description
+ * The description for this command; may be null
.
+ * @param category
+ * The category for this command; must not be null
.
+ * @param parameters
+ * The parameters understood by this command. This value may be
+ * either null
or empty if the command does not
+ * accept parameters.
+ * @param returnType
+ * The type of value returned by this command. This value may be
+ * null
if the command does not declare a return
+ * type.
+ * @param helpContextId
+ * The identifier of the help context to associate with this
+ * command; may be null
if this command does not
+ * have any help associated with it.
+ * @since 3.2
+ */
+ public final void define(String name, String description,
+ Category category, IParameter[] parameters,
+ ParameterType returnType, String helpContextId) {
+ if (name is null) {
+ throw new NullPointerException(
+ "The name of a command cannot be null"); //$NON-NLS-1$
+ }
+
+ if (category is null) {
+ throw new NullPointerException(
+ "The category of a command cannot be null"); //$NON-NLS-1$
+ }
+
+ bool definedChanged = !this.defined;
+ this.defined = true;
+
+ bool nameChanged = !Util.equals(this.name, name);
+ this.name = name;
+
+ bool descriptionChanged = !Util.equals(this.description,
+ description);
+ this.description = description;
+
+ bool categoryChanged = !Util.equals(this.category, category);
+ this.category = category;
+
+ Object[] pLeft, pRight;
+ foreach( p; this.parameters ){
+ pLeft ~= cast(Object)p;
+ }
+ foreach( p; parameters ){
+ pRight ~= cast(Object)p;
+ }
+ bool parametersChanged = !Util.equals(pLeft,
+ pRight);
+ this.parameters = parameters;
+
+ bool returnTypeChanged = !Util.equals(this.returnType,
+ returnType);
+ this.returnType = returnType;
+
+ bool helpContextIdChanged = !Util.equals(this.helpContextId,
+ helpContextId);
+ this.helpContextId = helpContextId;
+
+ fireCommandChanged(new CommandEvent(this, categoryChanged,
+ definedChanged, descriptionChanged, false, nameChanged,
+ parametersChanged, returnTypeChanged, helpContextIdChanged));
+ }
+
+ /**
+ * Executes this command by delegating to the current handler, if any. If
+ * the debugging flag is set, then this method prints information about
+ * which handler is selected for performing this command. This method will
+ * succeed regardless of whether the command is enabled or defined. It is
+ * generally preferred to call {@link #executeWithChecks(ExecutionEvent)}.
+ *
+ * @param event
+ * An event containing all the information about the current
+ * state of the application; must not be null
.
+ * @return The result of the execution; may be null
. This
+ * result will be available to the client executing the command, and
+ * execution listeners.
+ * @throws ExecutionException
+ * If the handler has problems executing this command.
+ * @throws NotHandledException
+ * If there is no handler.
+ * @deprecated Please use {@link #executeWithChecks(ExecutionEvent)}
+ * instead.
+ */
+ public final Object execute(ExecutionEvent event) {
+ firePreExecute(event);
+ IHandler handler = this.handler;
+
+ // Perform the execution, if there is a handler.
+ if ((handler !is null) && (handler.isHandled())) {
+ try {
+ Object returnValue = handler.execute(event);
+ firePostExecuteSuccess(returnValue);
+ return returnValue;
+ } catch (ExecutionException e) {
+ firePostExecuteFailure(e);
+ throw e;
+ }
+ }
+
+ NotHandledException e = new NotHandledException(
+ "There is no handler to execute. " ~ getId()); //$NON-NLS-1$
+ fireNotHandled(e);
+ throw e;
+ }
+
+ /**
+ * Executes this command by delegating to the current handler, if any. If
+ * the debugging flag is set, then this method prints information about
+ * which handler is selected for performing this command. This does checks
+ * to see if the command is enabled and defined. If it is not both enabled
+ * and defined, then the execution listeners will be notified and an
+ * exception thrown.
+ *
+ * @param event
+ * An event containing all the information about the current
+ * state of the application; must not be null
.
+ * @return The result of the execution; may be null
. This
+ * result will be available to the client executing the command, and
+ * execution listeners.
+ * @throws ExecutionException
+ * If the handler has problems executing this command.
+ * @throws NotDefinedException
+ * If the command you are trying to execute is not defined.
+ * @throws NotEnabledException
+ * If the command you are trying to execute is not enabled.
+ * @throws NotHandledException
+ * If there is no handler.
+ * @since 3.2
+ */
+ public final Object executeWithChecks(ExecutionEvent event) {
+ firePreExecute(event);
+ IHandler handler = this.handler;
+
+ if (!isDefined()) {
+ NotDefinedException exception = new NotDefinedException(
+ "Trying to execute a command that is not defined. " //$NON-NLS-1$
+ ~ getId());
+ fireNotDefined(exception);
+ throw exception;
+ }
+
+ // Perform the execution, if there is a handler.
+ if ((handler !is null) && (handler.isHandled())) {
+ if (!isEnabled()) {
+ NotEnabledException exception = new NotEnabledException(
+ "Trying to execute the disabled command " ~ getId()); //$NON-NLS-1$
+ fireNotEnabled(exception);
+ throw exception;
+ }
+
+ try {
+ Object returnValue = handler.execute(event);
+ firePostExecuteSuccess(returnValue);
+ return returnValue;
+ } catch (ExecutionException e) {
+ firePostExecuteFailure(e);
+ throw e;
+ }
+ }
+
+ NotHandledException e = new NotHandledException(
+ "There is no handler to execute for command " ~ getId()); //$NON-NLS-1$
+ fireNotHandled(e);
+ throw e;
+ }
+
+ /**
+ * Notifies the listeners for this command that it has changed in some way.
+ *
+ * @param commandEvent
+ * The event to send to all of the listener; must not be
+ * null
.
+ */
+ private final void fireCommandChanged(CommandEvent commandEvent) {
+ if (commandEvent is null) {
+ throw new NullPointerException("Cannot fire a null event"); //$NON-NLS-1$
+ }
+
+ Object[] listeners = getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ ICommandListener listener = cast(ICommandListener) listeners[i];
+ SafeRunner.run(new class() ISafeRunnable {
+ ICommandListener listener_;
+ this(){ this.listener_ = listener; }
+ public void handleException(Exception exception) {
+ }
+
+ public void run() {
+ listener_.commandChanged(commandEvent);
+ }
+ });
+ }
+ }
+
+ /**
+ * Notifies the execution listeners for this command that an attempt to
+ * execute has failed because the command is not defined.
+ *
+ * @param e
+ * The exception that is about to be thrown; never
+ * null
.
+ * @since 3.2
+ */
+ private final void fireNotDefined(NotDefinedException e) {
+ // Debugging output
+ if (DEBUG_COMMAND_EXECUTION) {
+ Tracing.printTrace("COMMANDS", "execute" ~ Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
+ ~ "not defined: id=" ~ getId() ~ "; exception=" ~ e.toString ); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ 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(getId(), e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Notifies the execution listeners for this command that an attempt to
+ * execute has failed because there is no handler.
+ *
+ * @param e
+ * The exception that is about to be thrown; never
+ * null
.
+ * @since 3.2
+ */
+ private final void fireNotEnabled(NotEnabledException e) {
+ // Debugging output
+ if (DEBUG_COMMAND_EXECUTION) {
+ Tracing.printTrace("COMMANDS", "execute" ~ Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
+ ~ "not enabled: id=" ~ getId() ~ "; exception=" ~ e.toString ); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ 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(getId(), e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Notifies the execution listeners for this command that an attempt to
+ * execute has failed because there is no handler.
+ *
+ * @param e
+ * The exception that is about to be thrown; never
+ * null
.
+ */
+ private final void fireNotHandled(NotHandledException e) {
+ // Debugging output
+ if (DEBUG_COMMAND_EXECUTION) {
+ Tracing.printTrace("COMMANDS", "execute" ~ Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
+ ~ "not handled: id=" ~ getId() ~ "; exception=" ~ e.toString ); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (executionListeners !is null) {
+ Object[] listeners = executionListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IExecutionListener listener = cast(IExecutionListener) listeners[i];
+ listener.notHandled(getId(), e);
+ }
+ }
+ }
+
+ /**
+ * Notifies the execution listeners for this command that an attempt to
+ * execute has failed during the execution.
+ *
+ * @param e
+ * The exception that has been thrown; never null
.
+ * After this method completes, the exception will be thrown
+ * again.
+ */
+ private final void firePostExecuteFailure(ExecutionException e) {
+ // Debugging output
+ if (DEBUG_COMMAND_EXECUTION) {
+ Tracing.printTrace("COMMANDS", "execute" ~ Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
+ ~ "failure: id=" ~ getId() ~ "; exception=" ~ e.toString ); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (executionListeners !is null) {
+ Object[] listeners = executionListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IExecutionListener listener = cast(IExecutionListener) listeners[i];
+ listener.postExecuteFailure(getId(), e);
+ }
+ }
+ }
+
+ /**
+ * Notifies the execution listeners for this command that an execution has
+ * completed successfully.
+ *
+ * @param returnValue
+ * The return value from the command; may be null
.
+ */
+ private final void firePostExecuteSuccess(Object returnValue) {
+ // Debugging output
+ if (DEBUG_COMMAND_EXECUTION) {
+ Tracing.printTrace("COMMANDS", "execute" ~ Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
+ ~ "success: id=" ~ getId() ~ "; returnValue=" //$NON-NLS-1$ //$NON-NLS-2$
+ ~ returnValue.toString );
+ }
+
+ if (executionListeners !is null) {
+ Object[] listeners = executionListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IExecutionListener listener = cast(IExecutionListener) listeners[i];
+ listener.postExecuteSuccess(getId(), returnValue);
+ }
+ }
+ }
+
+ /**
+ * Notifies the execution listeners for this command that an attempt to
+ * execute is about to start.
+ *
+ * @param event
+ * The execution event that will be used; never null
.
+ */
+ private final void firePreExecute(ExecutionEvent event) {
+ // Debugging output
+ if (DEBUG_COMMAND_EXECUTION) {
+ Tracing.printTrace("COMMANDS", "execute" ~ Tracing.SEPARATOR //$NON-NLS-1$ //$NON-NLS-2$
+ ~ "starting: id=" ~ getId() ~ "; event=" ~ event.toString ); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (executionListeners !is null) {
+ Object[] listeners = executionListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IExecutionListener listener = cast(IExecutionListener) listeners[i];
+ listener.preExecute(getId(), event);
+ }
+ }
+ }
+
+ /**
+ * Returns the category for this command.
+ *
+ * @return The category for this command; never null
.
+ * @throws NotDefinedException
+ * If the handle is not currently defined.
+ */
+ public final Category getCategory() {
+ if (!isDefined()) {
+ throw new NotDefinedException(
+ "Cannot get the category from an undefined command. " //$NON-NLS-1$
+ ~ id);
+ }
+
+ return category;
+ }
+
+ /**
+ * Returns the current handler for this command. This is used by the command
+ * manager for determining the appropriate help context identifiers and by
+ * the command service to allow handlers to update elements.
+ * null
.
+ * @since 3.3
+ */
+ public final IHandler getHandler() {
+ return handler;
+ }
+
+ /**
+ * Returns the help context identifier associated with this command. This
+ * method should not be called by clients. Clients should use
+ * {@link CommandManager#getHelpContextId(String)} instead.
+ *
+ * @return The help context identifier for this command; may be
+ * null
if there is none.
+ * @since 3.2
+ */
+ final String getHelpContextId() {
+ return helpContextId;
+ }
+
+ /**
+ * Returns the parameter with the provided id or null
if this
+ * command does not have a parameter with the id.
+ *
+ * @param parameterId
+ * The id of the parameter to retrieve.
+ * @return The parameter with the provided id or null
if this
+ * command does not have a parameter with the id.
+ * @throws NotDefinedException
+ * If the handle is not currently defined.
+ * @since 3.2
+ */
+ public final IParameter getParameter(String parameterId) {
+ if (!isDefined()) {
+ throw new NotDefinedException(
+ "Cannot get a parameter from an undefined command. " //$NON-NLS-1$
+ ~ id);
+ }
+
+ if (parameters is null) {
+ return null;
+ }
+
+ for (int i = 0; i < parameters.length; i++) {
+ IParameter parameter = parameters[i];
+ if (parameter.getId().equals(parameterId)) {
+ return parameter;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the parameters for this command. This call triggers provides a
+ * copy of the array, so excessive calls to this method should be avoided.
+ *
+ * @return The parameters for this command. This value might be
+ * null
, if the command has no parameters.
+ * @throws NotDefinedException
+ * If the handle is not currently defined.
+ */
+ public final IParameter[] getParameters() {
+ if (!isDefined()) {
+ throw new NotDefinedException(
+ "Cannot get the parameters from an undefined command. " //$NON-NLS-1$
+ ~ id);
+ }
+
+ if ((parameters is null) || (parameters.length is 0)) {
+ return null;
+ }
+
+ IParameter[] returnValue = new IParameter[parameters.length];
+ SimpleType!(IParameter).arraycopy(parameters, 0, returnValue, 0, parameters.length);
+ return returnValue;
+ }
+
+ /**
+ * Returns the {@link ParameterType} for the parameter with the provided id
+ * or null
if this command does not have a parameter type
+ * with the id.
+ *
+ * @param parameterId
+ * The id of the parameter to retrieve the {@link ParameterType}
+ * of.
+ * @return The {@link ParameterType} for the parameter with the provided id
+ * or null
if this command does not have a parameter
+ * type with the provided id.
+ * @throws NotDefinedException
+ * If the handle is not currently defined.
+ * @since 3.2
+ */
+ public final ParameterType getParameterType(String parameterId) {
+ IParameter parameter = getParameter(parameterId);
+ if ( auto parameterWithType = cast(ITypedParameter)parameter ) {
+ return parameterWithType.getParameterType();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the {@link ParameterType} for the return value of this command or
+ * null
if this command does not declare a return value
+ * parameter type.
+ *
+ * @return The {@link ParameterType} for the return value of this command or
+ * null
if this command does not declare a return
+ * value parameter type.
+ * @throws NotDefinedException
+ * If the handle is not currently defined.
+ * @since 3.2
+ */
+ public final ParameterType getReturnType() {
+ if (!isDefined()) {
+ throw new NotDefinedException(
+ "Cannot get the return type of an undefined command. " //$NON-NLS-1$
+ ~ id);
+ }
+
+ return returnType;
+ }
+
+ /**
+ * Returns whether this command has a handler, and whether this handler is
+ * also handled and enabled.
+ *
+ * @return true
if the command is handled; false
+ * otherwise.
+ */
+ public final bool isEnabled() {
+ if (handler is null) {
+ return false;
+ }
+
+ return handler.isEnabled();
+ }
+
+ /**
+ * Returns whether this command has a handler, and whether this handler is
+ * also handled.
+ *
+ * @return true
if the command is handled; false
+ * otherwise.
+ */
+ public final bool isHandled() {
+ if (handler is null) {
+ return false;
+ }
+
+ return handler.isHandled();
+ }
+
+ /**
+ * Removes a listener from this command.
+ *
+ * @param commandListener
+ * The listener to be removed; must not be null
.
+ *
+ */
+ public final void removeCommandListener(
+ ICommandListener commandListener) {
+ if (commandListener is null) {
+ throw new NullPointerException(
+ "Cannot remove a null command listener"); //$NON-NLS-1$
+ }
+
+ removeListenerObject(cast(Object)commandListener);
+ }
+
+ /**
+ * Removes a listener from this command.
+ *
+ * @param executionListener
+ * The listener to be removed; must not be null
.
+ *
+ */
+ public final void removeExecutionListener(
+ IExecutionListener executionListener) {
+ if (executionListener is null) {
+ throw new NullPointerException(
+ "Cannot remove a null execution listener"); //$NON-NLS-1$
+ }
+
+ if (executionListeners !is null) {
+ executionListeners.remove(cast(Object)executionListener);
+ if (executionListeners.isEmpty()) {
+ executionListeners = null;
+ }
+ }
+ }
+
+ /**
+ * null
.
+ * @since 3.2
+ */
+ public void removeState(String stateId) {
+ if ( auto h = cast(IObjectWithState)handler ) {
+ h.removeState(stateId);
+ }
+ super.removeState(stateId);
+ }
+
+ /**
+ * Changes the handler for this command. This will remove all the state from
+ * the currently active handler (if any), and add it to handler
.
+ * If debugging is turned on, then this will also print information about
+ * the change to System.out
.
+ *
+ * @param handler
+ * The new handler; may be null
if none.
+ * @return true
if the handler changed; false
+ * otherwise.
+ */
+ public final bool setHandler(IHandler handler) {
+ if (Util.equals(cast(Object)handler, cast(Object)this.handler)) {
+ return false;
+ }
+
+ // Swap the state around.
+ String[] stateIds = getStateIds();
+ if (stateIds !is null) {
+ for (int i = 0; i < stateIds.length; i++) {
+ String stateId = stateIds[i];
+ if ( auto h = cast(IObjectWithState)this.handler ) {
+ h.removeState(stateId);
+ }
+ if ( auto h = cast(IObjectWithState)handler ) {
+ State stateToAdd = getState(stateId);
+ h.addState(stateId, stateToAdd);
+ }
+ }
+ }
+
+ bool enabled = isEnabled();
+ if (this.handler !is null) {
+ this.handler.removeHandlerListener(getHandlerListener());
+ }
+
+ // Update the handler, and flush the string representation.
+ this.handler = handler;
+ if (this.handler !is null) {
+ this.handler.addHandlerListener(getHandlerListener());
+ }
+ string = null;
+
+ // Debugging output
+ if ((DEBUG_HANDLERS)
+ && ((DEBUG_HANDLERS_COMMAND_ID is null) || (DEBUG_HANDLERS_COMMAND_ID
+ .equals(id)))) {
+ StringBuffer buffer = new StringBuffer("Command('"); //$NON-NLS-1$
+ buffer.append(id);
+ buffer.append("') has changed to "); //$NON-NLS-1$
+ if (handler is null) {
+ buffer.append("no handler"); //$NON-NLS-1$
+ } else {
+ buffer.append('\'');
+ buffer.append(( cast(Object)handler).toString);
+ buffer.append("' as its handler"); //$NON-NLS-1$
+ }
+ Tracing.printTrace("HANDLERS", buffer.toString()); //$NON-NLS-1$
+ }
+
+ // Send notification
+ fireCommandChanged(new CommandEvent(this, false, false, false, true,
+ false, false, false, false, enabled !is isEnabled()));
+
+ return true;
+ }
+
+ /**
+ * @return
+ */
+ private IHandlerListener getHandlerListener() {
+ if (handlerListener is null) {
+ handlerListener = new class IHandlerListener {
+ public void handlerChanged(HandlerEvent handlerEvent) {
+ bool enabledChanged = handlerEvent.isEnabledChanged();
+ bool handledChanged = handlerEvent.isHandledChanged();
+ fireCommandChanged(new CommandEvent(this.outer, false,
+ false, false, handledChanged, false, false, false,
+ false, enabledChanged));
+ }
+ };
+ }
+ return handlerListener;
+ }
+
+ /**
+ * The string representation of this command -- for debugging purposes only.
+ * This string should not be shown to an end user.
+ *
+ * @return The string representation; never null
.
+ */
+ public override final String toString() {
+ if (string is null) {
+ String parms;
+ foreach( p; parameters ){
+ parms ~= "{"~(cast(Object)p).toString~"}";
+ }
+ string = Format("Command({},{},\n\t\t{},\n\t\t{},\n\t\t{},\n\t\t{},{},{})",
+ id,
+ name is null ? "":name,
+ description is null?"":description,
+ category is null?"":category.toString(),
+ handler is null?"": (cast(Object)handler).toString(),
+ parms,
+ returnType is null?"":returnType.toString(),
+ defined
+ );
+ }
+ return string;
+ }
+
+ /**
+ * Makes this command become undefined. This has the side effect of changing
+ * the name and description to null
. This also removes all
+ * state and disposes of it. Notification is sent to all listeners.
+ */
+ public final void undefine() {
+ bool enabledChanged = isEnabled();
+
+ string = null;
+
+ bool definedChanged = defined;
+ defined = false;
+
+ bool nameChanged = name !is null;
+ name = null;
+
+ bool descriptionChanged = description !is null;
+ description = null;
+
+ bool categoryChanged = category !is null;
+ category = null;
+
+ bool parametersChanged = parameters !is null;
+ parameters = null;
+
+ bool returnTypeChanged = returnType !is null;
+ returnType = null;
+
+ String[] stateIds = getStateIds();
+ if (stateIds !is null) {
+ if ( auto handlerWithState = cast(IObjectWithState)handler ) {
+ for (int i = 0; i < stateIds.length; i++) {
+ String stateId = stateIds[i];
+ handlerWithState.removeState(stateId);
+
+ State state = getState(stateId);
+ removeState(stateId);
+ state.dispose();
+ }
+ } else {
+ for (int i = 0; i < stateIds.length; i++) {
+ String stateId = stateIds[i];
+ State state = getState(stateId);
+ removeState(stateId);
+ state.dispose();
+ }
+ }
+ }
+
+ fireCommandChanged(new CommandEvent(this, categoryChanged,
+ definedChanged, descriptionChanged, false, nameChanged,
+ parametersChanged, returnTypeChanged, false, enabledChanged));
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/CommandEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/CommandEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 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 Command
.
+ * null
.
+ */
+ private const Command command;
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param command
+ * the instance of the interface that changed.
+ * @param categoryChanged
+ * true
, iff the category property changed.
+ * @param definedChanged
+ * true
, iff the defined property changed.
+ * @param descriptionChanged
+ * true
, iff the description property changed.
+ * @param handledChanged
+ * true
, iff the handled property changed.
+ * @param nameChanged
+ * true
, iff the name property changed.
+ * @param parametersChanged
+ * true
if the parameters have changed;
+ * false
otherwise.
+ */
+ public this(Command command, bool categoryChanged,
+ bool definedChanged, bool descriptionChanged,
+ bool handledChanged, bool nameChanged,
+ bool parametersChanged) {
+ this(command, categoryChanged, definedChanged, descriptionChanged,
+ handledChanged, nameChanged, parametersChanged, false);
+ }
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param command
+ * the instance of the interface that changed.
+ * @param categoryChanged
+ * true
, iff the category property changed.
+ * @param definedChanged
+ * true
, iff the defined property changed.
+ * @param descriptionChanged
+ * true
, iff the description property changed.
+ * @param handledChanged
+ * true
, iff the handled property changed.
+ * @param nameChanged
+ * true
, iff the name property changed.
+ * @param parametersChanged
+ * true
if the parameters have changed;
+ * false
otherwise.
+ * @param returnTypeChanged
+ * true
iff the return type property changed;
+ * false
otherwise.
+ * @since 3.2
+ */
+ public this(Command command, bool categoryChanged,
+ bool definedChanged, bool descriptionChanged,
+ bool handledChanged, bool nameChanged,
+ bool parametersChanged, bool returnTypeChanged) {
+ this(command, categoryChanged, definedChanged, descriptionChanged,
+ handledChanged, nameChanged, parametersChanged,
+ returnTypeChanged, false);
+ }
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param command
+ * the instance of the interface that changed.
+ * @param categoryChanged
+ * true
, iff the category property changed.
+ * @param definedChanged
+ * true
, iff the defined property changed.
+ * @param descriptionChanged
+ * true
, iff the description property changed.
+ * @param handledChanged
+ * true
, iff the handled property changed.
+ * @param nameChanged
+ * true
, iff the name property changed.
+ * @param parametersChanged
+ * true
if the parameters have changed;
+ * false
otherwise.
+ * @param returnTypeChanged
+ * true
iff the return type property changed;
+ * false
otherwise.
+ * @param helpContextIdChanged
+ * true
iff the help context identifier changed;
+ * false
otherwise.
+ * @since 3.2
+ */
+ public this(Command command, bool categoryChanged,
+ bool definedChanged, bool descriptionChanged,
+ bool handledChanged, bool nameChanged,
+ bool parametersChanged, bool returnTypeChanged,
+ bool helpContextIdChanged) {
+ this(command, categoryChanged, definedChanged, descriptionChanged,
+ handledChanged, nameChanged, parametersChanged,
+ returnTypeChanged, helpContextIdChanged, false);
+ }
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param command
+ * the instance of the interface that changed.
+ * @param categoryChanged
+ * true
, iff the category property changed.
+ * @param definedChanged
+ * true
, iff the defined property changed.
+ * @param descriptionChanged
+ * true
, iff the description property changed.
+ * @param handledChanged
+ * true
, iff the handled property changed.
+ * @param nameChanged
+ * true
, iff the name property changed.
+ * @param parametersChanged
+ * true
if the parameters have changed;
+ * false
otherwise.
+ * @param returnTypeChanged
+ * true
iff the return type property changed;
+ * false
otherwise.
+ * @param helpContextIdChanged
+ * true
iff the help context identifier changed;
+ * false
otherwise.
+ * @param enabledChanged
+ * true
iff the comand enablement changed;
+ * false
otherwise.
+ * @since 3.3
+ */
+ public this(Command command, bool categoryChanged,
+ bool definedChanged, bool descriptionChanged,
+ bool handledChanged, bool nameChanged,
+ bool parametersChanged, bool returnTypeChanged,
+ bool helpContextIdChanged, bool enabledChanged) {
+ super(definedChanged, descriptionChanged, nameChanged);
+
+ if (command is null) {
+ throw new NullPointerException();
+ }
+ this.command = command;
+
+ if (categoryChanged) {
+ changedValues |= CHANGED_CATEGORY;
+ }
+ if (handledChanged) {
+ changedValues |= CHANGED_HANDLED;
+ }
+ if (parametersChanged) {
+ changedValues |= CHANGED_PARAMETERS;
+ }
+ if (returnTypeChanged) {
+ changedValues |= CHANGED_RETURN_TYPE;
+ }
+ if (helpContextIdChanged) {
+ changedValues |= CHANGED_HELP_CONTEXT_ID;
+ }
+ if (enabledChanged) {
+ changedValues |= CHANGED_ENABLED;
+ }
+ }
+
+ /**
+ * Returns the instance of the interface that changed.
+ *
+ * @return the instance of the interface that changed. Guaranteed not to be
+ * null
.
+ */
+ public final Command getCommand() {
+ return command;
+ }
+
+ /**
+ * Returns whether or not the category property changed.
+ *
+ * @return true
, iff the category property changed.
+ */
+ public final bool isCategoryChanged() {
+ return ((changedValues & CHANGED_CATEGORY) !is 0);
+ }
+
+ /**
+ * Returns whether or not the handled property changed.
+ *
+ * @return true
, iff the handled property changed.
+ */
+ public final bool isHandledChanged() {
+ return ((changedValues & CHANGED_HANDLED) !is 0);
+ }
+
+ /**
+ * Returns whether or not the help context identifier changed.
+ *
+ * @return true
, iff the help context identifier changed.
+ * @since 3.2
+ */
+ public final bool isHelpContextIdChanged() {
+ return ((changedValues & CHANGED_HELP_CONTEXT_ID) !is 0);
+ }
+
+ /**
+ * Returns whether or not the parameters have changed.
+ *
+ * @return true
, iff the parameters property changed.
+ */
+ public final bool isParametersChanged() {
+ return ((changedValues & CHANGED_PARAMETERS) !is 0);
+ }
+
+ /**
+ * Returns whether or not the return type property changed.
+ *
+ * @return true
, iff the return type property changed.
+ * @since 3.2
+ */
+ public final bool isReturnTypeChanged() {
+ return ((changedValues & CHANGED_RETURN_TYPE) !is 0);
+ }
+
+ /**
+ * Return whether the enable property changed.
+ *
+ * @return true
iff the comand enablement changed
+ * @since 3.3
+ */
+ public final bool isEnabledChanged() {
+ return ((changedValues & CHANGED_ENABLED) !is 0);
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/CommandManager.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/CommandManager.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,989 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 null
.
+ *
+ * @since 3.2
+ */
+ public static const String AUTOGENERATED_CATEGORY_ID = "dwtx.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!(String,Category);
+ definedCategoryIds = new HashSet!(String);
+ definedParameterTypeIds = new HashSet!(String);
+ parameterTypesById = new HashMap!(String,ParameterType);
+ helpContextIdsByHandler = new WeakHashMap!(IHandler,String);
+ }
+
+ /**
+ * Unescapes special characters in the command id, parameter ids and
+ * parameter values for {@link #deserialize()}. 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.
+ *
+ * @param escapedText
+ * a String
that may contain escaped special
+ * characters for command serialization.
+ * @return a String
representing escapedText
+ * with any escaped characters replaced by their literal values
+ * @throws SerializationException
+ * if escapedText
contains an invalid escape
+ * sequence
+ * @see ParameterizedCommand#escape(String)
+ * @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 (String
) to categories (
+ * Category
). This collection may be empty, but it is never
+ * null
.
+ */
+ private const Map!(String,Category) categoriesById;
+
+ /**
+ * The set of identifiers for those categories that are defined. This value
+ * may be empty, but it is never null
.
+ */
+ private const Set!(String) definedCategoryIds;
+
+ /**
+ * The set of identifiers for those command parameter types that are
+ * defined. This value may be empty, but it is never null
.
+ *
+ * @since 3.2
+ */
+ private const Set!(String) definedParameterTypeIds;
+
+ /**
+ * The execution listener for this command manager. This just forwards
+ * events from commands controlled by this manager to listeners on this
+ * manager.
+ */
+ private IExecutionListener executionListener = null;
+
+ /**
+ * The collection of execution listeners. This collection is
+ * null
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 null
. Entries are
+ * removed if all strong references to the handler are removed.
+ *
+ * @since 3.2
+ */
+ private const WeakHashMap!(IHandler,String) helpContextIdsByHandler;
+
+ /**
+ * The map of parameter type identifiers (String
) to
+ * parameter types ( ParameterType
). This collection may be
+ * empty, but it is never null
.
+ *
+ * @since 3.2
+ */
+ private const Map!(String,ParameterType) 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 null
.
+ */
+ 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 null
.
+ */
+ 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();
+ foreach( k, v; handleObjectsById ){
+ Command command = cast(Command) v;
+ command.addExecutionListener(executionListener);
+ }
+
+ }
+
+ executionListeners.add(cast(Object)listener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.core.commands.ICategoryListener#categoryChanged(dwtx.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 dwtx.commands.ICommandListener#commandChanged(dwtx.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 null
.
+ *
+ * @param name
+ * The name of the category for uncategorized commands; must not
+ * be null
.
+ * @param description
+ * The description of the category for uncategorized commands;
+ * may be null
.
+ * @since 3.2
+ */
+ public final void defineUncategorizedCategory(String name,
+ String description) {
+ Category category = getCategory(AUTOGENERATED_CATEGORY_ID);
+ category.define(name, description);
+ }
+
+ /**
+ * serializedParameterizedCommand
string. The
+ * serializedParameterizedCommand
must use the format
+ * returned by {@link ParameterizedCommand#serialize()} and described in the
+ * Javadoc for that method.
+ * serializedParameterizedCommand
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
+ * serializedParameterizedCommand
. This will not result in
+ * an exception, but in this case the value of the parameter when the
+ * command is executed is unspecified.
+ * null
, however it may throw
+ * an exception if there is a problem processing the serialization string or
+ * the encoded command is undefined.
+ * null
+ * @return a {@link ParameterizedCommand} with the command and
+ * parameterizations encoded in the
+ * serializedParameterizedCommand
; never
+ * null
.
+ * @throws NotDefinedException
+ * if the command indicated in
+ * serializedParameterizedCommand
is not defined
+ * @throws SerializationException
+ * if there is an error deserializing
+ * serializedParameterizedCommand
+ * @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
+ * null
.
+ */
+ 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 null
.
+ * @since 3.2
+ */
+ public final Command[] getAllCommands() {
+ Command[] res;
+ res.length = handleObjectsById.size();
+ int idx;
+ foreach( cmd; handleObjectsById.elements() ){
+ res[idx] = cast(Command)cmd;
+ idx++;
+ }
+ return res;
+ }
+
+ /**
+ * 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 null
. If
+ * the category is null
, then a category suitable
+ * for uncategorized items is defined and returned.
+ * @return The category with the given identifier; this value will never be
+ * null
, 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.add(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 null
and
+ * must not be zero-length.
+ * @return The command with the given identifier; this value will never be
+ * null
, 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.add(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
+ * null
.
+ * @since 3.2
+ */
+ public final Category[] getDefinedCategories() {
+ Category[] categories = new Category[definedCategoryIds.size()];
+// Iterator categoryIdItr = definedCategoryIds.iterator();
+ int i = 0;
+ foreach( categoryId; definedCategoryIds ){
+// while (categoryIdItr.hasNext()) {
+// String categoryId = cast(String) 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 null
.
+ */
+ public final SetView!(String) getDefinedCategoryIds() {
+ return 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 null
.
+ */
+ public final SetView!(String) getDefinedCommandIds() {
+ return getDefinedHandleObjectIds();
+ }
+
+ /**
+ * Returns the commands that are defined.
+ *
+ * @return The defined commands; this value may be empty, but it is never
+ * null
.
+ * @since 3.2
+ */
+ public final Command[] getDefinedCommands() {
+ return cast(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 null
.
+ * @since 3.2
+ */
+ public final SetView!(String) getDefinedParameterTypeIds() {
+ return definedParameterTypeIds;
+ }
+
+ /**
+ * Returns the command parameter types that are defined.
+ *
+ * @return The defined command parameter types; this value may be empty, but
+ * it is never null
.
+ * @since 3.2
+ */
+ public final ParameterType[] getDefinedParameterTypes() {
+ ParameterType[] parameterTypes = new ParameterType[definedParameterTypeIds
+ .size()];
+// Iterator iterator = definedParameterTypeIds.iterator();
+ int i = 0;
+ foreach( parameterTypeId; definedParameterTypeIds ){
+// while (iterator.hasNext()) {
+// String parameterTypeId = cast(String) 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 null
is returned.
+ *
+ * @param command
+ * The command for which the help context should be retrieved;
+ * must not be null
.
+ * @return The help context identifier to use for the given command; may be
+ * null
.
+ * @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 = cast(String) helpContextIdsByHandler
+ .get(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
+ * serializedParameters
string.
+ *
+ * @param serializedParameters
+ * a String encoding parameter ids and values; must not be
+ * null
.
+ * @param parameters
+ * array of parameters of the command being deserialized; may be
+ * null
.
+ * @return an array of parameterizations; may be null
.
+ * @throws NotDefinedException
+ * if the command is not defined
+ * @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;
+ }
+
+ auto paramList = new ArraySeq!(Parameterization);
+
+ 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.append(new Parameterization(parameter,
+ parameterValue));
+ break;
+ }
+ }
+
+ } while (commaPosition !is -1);
+
+ return cast(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 null
and
+ * must not be zero-length.
+ * @return The {@link ParameterType} with the given identifier; this value
+ * will never be null
, 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.add(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 null
.
+ */
+ 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 null
.
+ */
+ 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.
+ foreach( k, v; handleObjectsById ){
+// Iterator commandItr = handleObjectsById.values().iterator();
+// while (commandItr.hasNext()) {
+ Command command = cast(Command) v;
+ command.removeExecutionListener(executionListener);
+ }
+ executionListener = null;
+
+ }
+ }
+
+ /**
+ * Block updates all of the handlers for all of the commands. If the handler
+ * is null
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 (String
) to
+ * handlers (IHandler
). This map may be
+ * null
if all handlers should be cleared.
+ * Similarly, if the map is empty, then all commands will become
+ * unhandled.
+ */
+ public final void setHandlersByCommandId(Map!(String,Object) handlersByCommandId) {
+ // Make that all the reference commands are created.
+ foreach( k, v; handlersByCommandId ){
+ //Iterator commandIdItr = handlersByCommandId.keySet().iterator();
+ //while (commandIdItr.hasNext()) {
+ getCommand(k);
+ }
+
+ // Now, set-up the handlers on all of the existing commands.
+// Iterator commandItr = handleObjectsById.values().iterator();
+ foreach( k, v; handlersByCommandId ){
+// while (commandItr.hasNext()) {
+ Command command = cast(Command) v;
+ String commandId = command.getId();
+ Object value = handlersByCommandId.get(commandId);
+ if ( auto handler = cast(IHandler) value ) {
+ command.setHandler(handler);
+ } 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 null
.
+ * @param helpContextId
+ * The help context identifier to register; may be
+ * null
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.removeKey(handler);
+ } else {
+ helpContextIdsByHandler.add(handler, helpContextId);
+ }
+ }
+
+ /**
+ * Searches for the index of a char
in a String
+ * 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 ch
in
+ * @param ch
+ * a character to search for in escapedText
+ * @return the index of the first unescaped occurrence of the character in
+ * escapedText
, or -1
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;
+
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/CommandManagerEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/CommandManagerEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,310 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 null
if the
+ * list of defined category identifiers did not change.
+ */
+ private const String categoryId;
+
+ /**
+ * A collection of bits representing whether certain values have changed. A
+ * bit is set (i.e., 1
) if the corresponding property has
+ * changed.
+ */
+ private const int changedValues;
+
+ /**
+ * The command identifier that was added or removed from the list of defined
+ * command identifiers. This value is null
if the list of
+ * defined command identifiers did not change.
+ */
+ private const String commandId;
+
+ /**
+ * The command parameter type identifier that was added or removed from the
+ * list of defined parameter type identifiers. This value is
+ * null
if the list of defined parameter type identifiers did
+ * not change.
+ *
+ * @since 3.2
+ */
+ private const String parameterTypeId;
+
+ /**
+ * The command manager that has changed.
+ */
+ private const CommandManager commandManager;
+
+ /**
+ * Creates a new CommandManagerEvent
instance to describe
+ * changes to commands and/or categories.
+ *
+ * @param commandManager
+ * the instance of the interface that changed; must not be
+ * null
.
+ * @param commandId
+ * The command identifier that was added or removed; must not be
+ * null
if commandIdChanged is true
.
+ * @param commandIdAdded
+ * Whether the command identifier became defined (otherwise, it
+ * became undefined).
+ * @param commandIdChanged
+ * Whether the list of defined command identifiers has changed.
+ * @param categoryId
+ * The category identifier that was added or removed; must not be
+ * null
if categoryIdChanged is true
.
+ * @param categoryIdAdded
+ * Whether the category identifier became defined (otherwise, it
+ * became undefined).
+ * @param categoryIdChanged
+ * Whether the list of defined category identifiers has changed.
+ */
+ public this(CommandManager commandManager,
+ String commandId, bool commandIdAdded,
+ bool commandIdChanged, String categoryId,
+ bool categoryIdAdded, bool categoryIdChanged) {
+ if (commandManager is null) {
+ throw new NullPointerException(
+ "An event must refer to its command manager"); //$NON-NLS-1$
+ }
+
+ if (commandIdChanged && (commandId is null)) {
+ throw new NullPointerException(
+ "If the list of defined commands changed, then the added/removed command must be mentioned"); //$NON-NLS-1$
+ }
+
+ if (categoryIdChanged && (categoryId is null)) {
+ throw new NullPointerException(
+ "If the list of defined categories changed, then the added/removed category must be mentioned"); //$NON-NLS-1$
+ }
+
+ this.commandManager = commandManager;
+ this.commandId = commandId;
+ this.categoryId = categoryId;
+
+ // this constructor only works for changes to commands and categories
+ this.parameterTypeId = null;
+
+ int changedValues = 0;
+ if (categoryIdChanged && categoryIdAdded) {
+ changedValues |= CHANGED_CATEGORY_DEFINED;
+ }
+ if (commandIdChanged && commandIdAdded) {
+ changedValues |= CHANGED_COMMAND_DEFINED;
+ }
+ this.changedValues = changedValues;
+ }
+
+ /**
+ * Creates a new CommandManagerEvent
instance to describe
+ * changes to command parameter types.
+ *
+ * @param commandManager
+ * the instance of the interface that changed; must not be
+ * null
.
+ * @param parameterTypeId
+ * The command parameter type identifier that was added or
+ * removed; must not be null
if
+ * parameterTypeIdChanged is true
.
+ * @param parameterTypeIdAdded
+ * Whether the parameter type identifier became defined
+ * (otherwise, it became undefined).
+ * @param parameterTypeIdChanged
+ * Whether the list of defined parameter type identifiers has
+ * changed.
+ *
+ * @since 3.2
+ */
+ public this(CommandManager commandManager,
+ String parameterTypeId, bool parameterTypeIdAdded,
+ bool parameterTypeIdChanged) {
+
+ if (commandManager is null) {
+ throw new NullPointerException(
+ "An event must refer to its command manager"); //$NON-NLS-1$
+ }
+
+ if (parameterTypeIdChanged && (parameterTypeId is null)) {
+ throw new NullPointerException(
+ "If the list of defined command parameter types changed, then the added/removed parameter type must be mentioned"); //$NON-NLS-1$
+ }
+
+ this.commandManager = commandManager;
+ this.commandId = null;
+ this.categoryId = null;
+
+ this.parameterTypeId = parameterTypeId;
+
+ int changedValues = 0;
+ if (parameterTypeIdChanged && parameterTypeIdAdded) {
+ changedValues |= CHANGED_PARAMETER_TYPE_DEFINED;
+ }
+
+ this.changedValues = changedValues;
+ }
+
+ /**
+ * Returns the category identifier that was added or removed.
+ *
+ * @return The category identifier that was added or removed; may be
+ * null
.
+ */
+ public final String getCategoryId() {
+ return categoryId;
+ }
+
+ /**
+ * Returns the command identifier that was added or removed.
+ *
+ * @return The command identifier that was added or removed; may be
+ * null
.
+ */
+ public final String getCommandId() {
+ return commandId;
+ }
+
+ /**
+ * Returns the instance of the interface that changed.
+ *
+ * @return the instance of the interface that changed. Guaranteed not to be
+ * null
.
+ */
+ public final CommandManager getCommandManager() {
+ return commandManager;
+ }
+
+ /**
+ * Returns the command parameter type identifier that was added or removed.
+ *
+ * @return The command parameter type identifier that was added or removed;
+ * may be null
.
+ *
+ * @since 3.2
+ */
+ public final String getParameterTypeId() {
+ return parameterTypeId;
+ }
+
+ /**
+ * Returns whether the list of defined category identifiers has changed.
+ *
+ * @return true
if the list of category identifiers has
+ * changed; false
otherwise.
+ */
+ public final bool isCategoryChanged() {
+ return (categoryId !is null);
+ }
+
+ /**
+ * Returns whether the category identifier became defined. Otherwise, the
+ * category identifier became undefined.
+ *
+ * @return true
if the category identifier became defined;
+ * false
if the category identifier became undefined.
+ */
+ public final bool isCategoryDefined() {
+ return (((changedValues & CHANGED_CATEGORY_DEFINED) !is 0) && (categoryId !is null));
+ }
+
+ /**
+ * Returns whether the list of defined command identifiers has changed.
+ *
+ * @return true
if the list of command identifiers has
+ * changed; false
otherwise.
+ */
+ public final bool isCommandChanged() {
+ return (commandId !is null);
+ }
+
+ /**
+ * Returns whether the command identifier became defined. Otherwise, the
+ * command identifier became undefined.
+ *
+ * @return true
if the command identifier became defined;
+ * false
if the command identifier became undefined.
+ */
+ public final bool isCommandDefined() {
+ return (((changedValues & CHANGED_COMMAND_DEFINED) !is 0) && (commandId !is null));
+ }
+
+ /**
+ * Returns whether the list of defined command parameter type identifiers
+ * has changed.
+ *
+ * @return true
if the list of command parameter type
+ * identifiers has changed; false
otherwise.
+ *
+ * @since 3.2
+ */
+ public final bool isParameterTypeChanged() {
+ return (parameterTypeId !is null);
+ }
+
+ /**
+ * Returns whether the command parameter type identifier became defined.
+ * Otherwise, the command parameter type identifier became undefined.
+ *
+ * @return true
if the command parameter type identifier
+ * became defined; false
if the command parameter
+ * type identifier became undefined.
+ *
+ * @since 3.2
+ */
+ public final bool isParameterTypeDefined() {
+ return (((changedValues & CHANGED_PARAMETER_TYPE_DEFINED) !is 0) && (parameterTypeId !is null));
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ExecutionEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ExecutionEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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 null
.
+ */
+ private const Object applicationContext;
+
+ /**
+ * The command being executed. This value may be null
.
+ */
+ private const Command command;
+
+ /**
+ * The parameters to qualify the execution. For handlers that normally
+ * prompt for additional information, these can be used to avoid prompting.
+ * This value may be empty, but it is never null
.
+ */
+ private const Map!(String,String) parameters;
+
+ /**
+ * The object that triggered the execution. In an event-driven architecture,
+ * this is typically just another event. In the Eclipse workbench, this is
+ * typically an DWT event. This value may be null
.
+ */
+ private const Object trigger;
+
+ /**
+ * Constructs a new instance of ExecutionEvent
with no
+ * parameters, no trigger and no application context. This is just a
+ * convenience method.
+ *
+ * @since 3.2
+ */
+ public this() {
+ this(null, EMPTY_MAP, null, null);
+ }
+
+ /**
+ * Constructs a new instance of ExecutionEvent
.
+ *
+ * @param parameters
+ * The parameters to qualify the execution; must not be
+ * null
. This must be a map of parameter ids (String
)
+ * to parameter values (String
).
+ * @param trigger
+ * The object that triggered the execution; may be
+ * null
.
+ * @param applicationContext
+ * The state of the application at the time the execution was
+ * triggered; may be null
.
+ * @deprecated use
+ * {@link ExecutionEvent#ExecutionEvent(Command, Map, Object, Object)}
+ */
+ public this(Map!(String,String) parameters, Object trigger,
+ Object applicationContext) {
+ this(null, parameters, trigger, applicationContext);
+ }
+
+ /**
+ * Constructs a new instance of ExecutionEvent
.
+ *
+ * @param command
+ * The command being executed; may be null
.
+ * @param parameters
+ * The parameters to qualify the execution; must not be
+ * null
. This must be a map of parameter ids (String
)
+ * to parameter values (String
).
+ * @param trigger
+ * The object that triggered the execution; may be
+ * null
.
+ * @param applicationContext
+ * The state of the application at the time the execution was
+ * triggered; may be null
.
+ * @since 3.2
+ */
+ public this(Command command, Map!(String,String) parameters,
+ Object trigger, Object applicationContext) {
+ if (parameters is null) {
+ throw new NullPointerException(
+ "An execution event must have a non-null map of parameters"); //$NON-NLS-1$
+ }
+
+ this.command = command;
+ this.parameters = parameters;
+ this.trigger = trigger;
+ this.applicationContext = applicationContext;
+ }
+
+ /**
+ * Returns the state of the application at the time the execution was
+ * triggered.
+ *
+ * @return The application context; may be null
.
+ */
+ public final Object getApplicationContext() {
+ return applicationContext;
+ }
+
+ /**
+ * Returns the command being executed.
+ *
+ * @return The command being executed.
+ * @since 3.2
+ */
+ public final Command getCommand() {
+ return command;
+ }
+
+ /**
+ * Returns the object represented by the string value of the parameter with
+ * the provided id.
+ * ExecutionException
to be thrown.
+ * null
.
+ * @return The parameter value; null
if the parameter cannot
+ * be found.
+ */
+ public final String getParameter(String parameterId) {
+ return parameters.get(parameterId);
+ }
+
+ /**
+ * Returns all of the parameters.
+ *
+ * @return The parameters; never null
, but may be empty.
+ */
+ public final Map!(String,String) getParameters() {
+ return parameters;
+ }
+
+ /**
+ * Returns the object that triggered the execution
+ *
+ * @return The trigger; null
if there was no trigger.
+ */
+ public final Object getTrigger() {
+ return trigger;
+ }
+
+ /**
+ * The string representation of this execution event -- for debugging
+ * purposes only. This string should not be shown to an end user.
+ *
+ * @return The string representation; never null
.
+ */
+ public final String toString() {
+ String parm;
+ foreach( k, v; parameters ){
+ parm ~= "{"~k~","~v~"}";
+ }
+ return Format( "ExecutionEvent({},{},{})", command, parm, trigger, applicationContext );
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ExecutionException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ExecutionException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 null
.
+ * @since 3.2
+ */
+ public this(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new instance of this class with the specified detail message
+ * and cause.
+ *
+ * @param message
+ * the detail message; may be null
.
+ * @param cause
+ * the cause; may be null
.
+ */
+ public this(String message, Exception cause) {
+ super(message, cause);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/HandlerEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/HandlerEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 IHandler
.
+ * null
.
+ */
+ private final IHandler handler;
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param handler
+ * the instance of the interface that changed; must not be
+ * null
.
+ * @param enabledChanged
+ * Whether the enabled state of the handler has changed.
+ * @param handledChanged
+ * Whether the handled state of the handler has changed.
+ */
+ public this(IHandler handler, bool enabledChanged,
+ bool handledChanged) {
+ if (handler is null) {
+ throw new NullPointerException();
+ }
+ this.handler = handler;
+
+ if (enabledChanged) {
+ changedValues |= CHANGED_ENABLED;
+ }
+ if (handledChanged) {
+ changedValues |= CHANGED_HANDLED;
+ }
+ }
+
+ /**
+ * Returns the instance of the interface that changed.
+ *
+ * @return the instance of the interface that changed. Guaranteed not to be
+ * null
.
+ */
+ public IHandler getHandler() {
+ return handler;
+ }
+
+ /**
+ * Returns whether or not the enabled property changed.
+ *
+ * @return true
, iff the enabled property changed.
+ */
+ public bool isEnabledChanged() {
+ return ((changedValues & CHANGED_ENABLED) !is 0);
+ }
+
+ /**
+ * Returns whether or not the handled property changed.
+ *
+ * @return true
, iff the handled property changed.
+ */
+ public bool isHandledChanged() {
+ return ((changedValues & CHANGED_HANDLED) !is 0);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ICategoryListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ICategoryListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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 Category
.
+ * Category
have changed. Specific details are described in
+ * the CategoryEvent
.
+ *
+ * @param categoryEvent
+ * the category event. Guaranteed not to be null
.
+ */
+ void categoryChanged(CategoryEvent categoryEvent);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ICommandListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ICommandListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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 Command
.
+ * Command
have changed. Specific details are described in
+ * the CommandEvent
.
+ *
+ * @param commandEvent
+ * the command event. Guaranteed not to be null
.
+ */
+ void commandChanged(CommandEvent commandEvent);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ICommandManagerListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ICommandManagerListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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 ICommandManager
.
+ * ICommandManager
have changed. Specific details are
+ * described in the CommandManagerEvent
.
+ *
+ * @param commandManagerEvent
+ * the commandManager event. Guaranteed not to be
+ * null
.
+ */
+ void commandManagerChanged(CommandManagerEvent commandManagerEvent);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/IExecutionListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/IExecutionListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 null
+ * @param exception
+ * The exception that occurred; never null
.
+ */
+ public void notHandled(String commandId, NotHandledException exception);
+
+ /**
+ * Notifies the listener that a command has failed to complete execution.
+ *
+ * @param commandId
+ * The identifier of the command that has executed; never
+ * null
.
+ * @param exception
+ * The exception that occurred; never null
.
+ */
+ public void postExecuteFailure(String commandId,
+ ExecutionException exception);
+
+ /**
+ * Notifies the listener that a command has completed execution
+ * successfully.
+ *
+ * @param commandId
+ * The identifier of the command that has executed; never
+ * null
.
+ * @param returnValue
+ * The return value from the command; may be null
.
+ */
+ public void postExecuteSuccess(String commandId, Object returnValue);
+
+ /**
+ * Notifies the listener that a command is about to execute.
+ *
+ * @param commandId
+ * The identifier of the command that is about to execute, never
+ * null
.
+ * @param event
+ * The event that will be passed to the execute
+ * method; never null
.
+ */
+ public void preExecute(String commandId, ExecutionEvent event);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/IExecutionListenerWithChecks.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/IExecutionListenerWithChecks.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
+ * @param exception
+ * The exception that occurred; never null
.
+ */
+ public void notDefined(String commandId, NotDefinedException exception);
+
+ /**
+ * Notifies the listener that an attempt was made to execute a command that
+ * is disabled.
+ *
+ * @param commandId
+ * The identifier of command that is not enabled; never
+ * null
+ * @param exception
+ * The exception that occurred; never null
.
+ */
+ public void notEnabled(String commandId, NotEnabledException exception);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/IHandler.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/IHandler.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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 IHandlerListener
to listen for
+ * changes to properties of this instance.
+ *
+ * @param handlerListener
+ * the instance to register. Must not be null
. If
+ * an attempt is made to register an instance which is already
+ * registered with this instance, no operation is performed.
+ */
+ void addHandlerListener(IHandlerListener handlerListener);
+
+ /**
+ * Disposes of this handler. This method is run once when the object is no
+ * longer referenced. This can be used as an opportunity to unhook listeners
+ * from other objects.
+ */
+ public void dispose();
+
+ /**
+ * Executes with the map of parameter values by name.
+ *
+ * @param event
+ * An event containing all the information about the current
+ * state of the application; must not be null
.
+ * @return the result of the execution. Reserved for future use, must be
+ * null
.
+ * @throws ExecutionException
+ * if an exception occurred during execution.
+ */
+ Object execute(ExecutionEvent event);
+
+ /**
+ * Returns whether this handler is capable of executing at this moment in
+ * time.
+ *
+ * @return true
if the command is enabled; false
+ * otherwise.
+ */
+ public bool isEnabled();
+
+ /**
+ * Returns whether this handler is really capable of handling delegation. In
+ * the case of a handler that is a composition of other handlers, this reply
+ * is intended to indicate whether the handler is truly capable of receiving
+ * delegated responsibilities at this time.
+ *
+ * @return true
if the handler is handled; false
+ * otherwise.
+ */
+ public bool isHandled();
+
+ /**
+ * Unregisters an instance of IHandlerListener
listening for
+ * changes to properties of this instance.
+ *
+ * @param handlerListener
+ * the instance to unregister. Must not be null
.
+ * If an attempt is made to unregister an instance which is not
+ * already registered with this instance, no operation is
+ * performed.
+ */
+ void removeHandlerListener(IHandlerListener handlerListener);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/IHandlerAttributes.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/IHandlerAttributes.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 RetargetAction
class. It is used to indicate that while
+ * the handler is handling a command, it should not be treated as such.
+ * The command should act and behave as if it has no handler.
+ * IHandler
.
+ * IHandler
have changed. Specific details are described in
+ * the HandlerEvent
.
+ *
+ * @param handlerEvent
+ * the handler event. Guaranteed not to be null
.
+ */
+ void handlerChanged(HandlerEvent handlerEvent);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/INamedHandleStateIds.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/INamedHandleStateIds.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 IObjectWithState
.
+ * null
.
+ * @param state
+ * The new state to add to this object; must not be
+ * null
.
+ */
+ public void addState(String id, State state);
+
+ /**
+ * Gets the state with the given id.
+ *
+ * @param stateId
+ * The identifier of the state to retrieve; must not be
+ * null
.
+ * @return The state; may be null
if there is no state with
+ * the given id.
+ */
+ public State getState(String stateId);
+
+ /**
+ * Gets the identifiers for all of the state associated with this object.
+ *
+ * @return All of the state identifiers; may be empty, but never
+ * null
.
+ */
+ public String[] getStateIds();
+
+ /**
+ * Removes state from this object.
+ *
+ * @param stateId
+ * The id of the state to remove from this object; must not be
+ * null
.
+ */
+ public void removeState(String stateId);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/IParameter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/IParameter.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 null
.
+ */
+ public String getId();
+
+ /**
+ * Returns the human-readable name for this parameter.
+ *
+ * @return The parameter name; never null
.
+ */
+ public String getName();
+
+ /**
+ * Returns the values associated with this parameter.
+ *
+ * @return The values associated with this parameter. This must not be
+ * null
.
+ * @throws ParameterValuesException
+ * If the values can't be retrieved for some reason.
+ */
+ public IParameterValues getValues();
+
+ /**
+ * Returns whether parameter is optional. Otherwise, it is required.
+ *
+ * @return true
if the parameter is optional;
+ * false
if it is required.
+ */
+ public bool isOptional();
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/IParameterTypeListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/IParameterTypeListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
.
+ */
+ void parameterTypeChanged(ParameterTypeEvent parameterTypeEvent);
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/IParameterValues.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/IParameterValues.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 String
)
+ * to the actual value of the parameter (String
).
+ */
+ public Map!(String,String) getParameterValues();
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/IStateListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/IStateListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
. The
+ * value for this state has been updated to the new value.
+ * @param oldValue
+ * The old value; may be anything.
+ */
+ public void handleStateChange(State state, Object oldValue);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ITypedParameter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ITypedParameter.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
if the parameter does not declare a type.
+ * null
if the parameter does not declare a type
+ */
+ public ParameterType getParameterType();
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/NamedHandleObjectWithState.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/NamedHandleObjectWithState.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
.
+ */
+ private Map!(String,State) states = null;
+
+ /**
+ * Constructs a new instance of NamedHandleObject
+ * if no progress monitor is provided
+ * @param info
+ * the IAdaptable (or null
.
+ */
+ protected this(String id) {
+ super(id);
+ }
+
+ public void addState(String stateId, State state) {
+ if (state is null) {
+ throw new NullPointerException("Cannot add a null state"); //$NON-NLS-1$
+ }
+
+ if (states is null) {
+ states = new HashMap!(String,State)/+(3)+/;
+ }
+ states.add(stateId, state);
+ }
+
+ public final String getDescription() {
+ String description = super.getDescription(); // Trigger a NDE.
+
+ State descriptionState = getState(INamedHandleStateIds.DESCRIPTION);
+ if (descriptionState !is null) {
+ Object value = descriptionState.getValue();
+ if (value !is null) {
+ return value.toString();
+ }
+ }
+
+ return description;
+ }
+
+ public final String getName() {
+ String name = super.getName(); // Trigger a NDE, if necessary.
+
+ State nameState = getState(INamedHandleStateIds.NAME);
+ if (nameState !is null) {
+ final Object value = nameState.getValue();
+ if (value !is null) {
+ return value.toString();
+ }
+ }
+
+ return name;
+ }
+
+ public final State getState(String stateId) {
+ if ((states is null) || (states.drained())) {
+ return null;
+ }
+
+ return states.get(stateId);
+ }
+
+ public final String[] getStateIds() {
+ if ((states is null) || (states.drained())) {
+ return NO_STATE;
+ }
+
+ String[] res;
+ foreach( id, state; states){
+ res ~= id;
+ }
+ return res;
+ }
+
+ public void removeState(String id) {
+ if (id is null) {
+ throw new NullPointerException("Cannot remove a null id"); //$NON-NLS-1$
+ }
+
+ if (states !is null) {
+ states.removeKey(id);
+ if (states.drained()) {
+ states = null;
+ }
+ }
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/NotEnabledException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/NotEnabledException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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 null
.
+ */
+ public this(String s) {
+ super(s);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/NotHandledException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/NotHandledException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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
+ * IParameter parameter = // ... get IParameter from Command
+ * if (parameter instanceof ITypedParameter) {
+ * ParameterType type = ((ITypedParameter)parameter).getParameterType();
+ * if (type !is null) {
+ * // this parameter has a ParameterType
+ * }
+ * }
+ *
+ *
+ * @see IParameter
+ * @see ITypedParameter#getParameterType()
+ * @since 3.2
+ */
+public final class ParameterType : HandleObject, Comparable {
+
+ /**
+ * TODO: this was copied from
+ * dwtx.core.internal.expressions.Expressions is there a better place
+ * to reference this?
+ *
+ * @param element
+ * The element to test; may be null
.
+ * @param type
+ * The type against which we are testing;may be null
.
+ * @return true
if the element
is an instance
+ * of type
; false
otherwise.
+ */
+ private static final bool isInstanceOf(Object element,
+ String type) {
+ // null isn't an instanceof of anything.
+ if (element is null) {
+ return false;
+ }
+ return isSubtype(element.classinfo, type);
+ }
+
+ /**
+ * TODO: this was copied from
+ * dwtx.core.internal.expressions.Expressions is there a better place
+ * to reference this?
+ *
+ * @param clazz
+ * The class to match; may be null
.
+ * @param type
+ * The type against which we are testing;may be null
.
+ * @return true
if the element
is an instance
+ * of type
; false
otherwise.
+ */
+ private static final bool isSubtype(ClassInfo clazz, String type) {
+ if (clazz.name.equals(type)) {
+ return true;
+ }
+ ClassInfo superClass = clazz.base;
+ if (superClass !is null && isSubtype(superClass, type)) {
+ return true;
+ }
+ Interface[] interfaces = clazz.interfaces;
+ for (int i = 0; i < interfaces.length; i++) {
+ if (isSubtype(interfaces[i].classinfo, type)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * An {@link AbstractParameterValueConverter} for converting parameter
+ * values between objects and strings. This may be null
.
+ */
+ private /+transient+/ AbstractParameterValueConverter parameterTypeConverter;
+
+ /**
+ * A string specifying the object type of this parameter type. This will be
+ * null
when the parameter type is undefined but never null
+ * when it is defined.
+ */
+ private /+transient+/ String type = null;
+
+ /**
+ * Constructs a new instance based on the given identifier. When a parameter
+ * type is first constructed, it is undefined. Parameter types should only
+ * be constructed by the {@link CommandManager} to ensure that the
+ * identifier remains unique.
+ *
+ * @param id
+ * The identifier for this type. This value must not be
+ * null
, and must be unique amongst all parameter
+ * types.
+ */
+ this(String id) {
+ super(id);
+ }
+
+ /**
+ * Adds a listener to this parameter type that will be notified when its
+ * state changes.
+ *
+ * @param listener
+ * The listener to be added; must not be null
.
+ */
+ public final void addListener(IParameterTypeListener listener) {
+ addListenerObject(cast(Object)listener);
+ }
+
+ /**
+ * Compares this parameter type with another object by comparing each of the
+ * non-transient attributes.
+ *
+ * @param object
+ * The object with which to compare; must be an instance of
+ * {@link ParameterType}.
+ * @return A negative integer, zero or a positive integer, if the object is
+ * greater than, equal to or less than this parameter type.
+ */
+ public final int compareTo(Object object) {
+ ParameterType castedObject = cast(ParameterType) object;
+ int compareTo = Util.compare(defined, castedObject.defined);
+ if (compareTo is 0) {
+ compareTo = Util.compare(id, castedObject.id);
+ }
+ return compareTo;
+ }
+
+ /**
+ * true
.
+ * null
is interpreted as
+ * "java.lang.Object"
+ * @param parameterTypeConverter
+ * an {@link AbstractParameterValueConverter} to perform
+ * string/object conversions for parameter values; may be
+ * null
+ */
+ public final void define(String type,
+ AbstractParameterValueConverter parameterTypeConverter) {
+
+ bool definedChanged = !this.defined;
+ this.defined = true;
+
+ this.type = (type is null) ? Object.classinfo.name : type;
+ this.parameterTypeConverter = parameterTypeConverter;
+
+ fireParameterTypeChanged(new ParameterTypeEvent(this, definedChanged));
+ }
+
+ /**
+ * Notifies all listeners that this parameter type has changed. This sends
+ * the given event to all of the listeners, if any.
+ *
+ * @param event
+ * The event to send to the listeners; must not be
+ * null
.
+ */
+ private final void fireParameterTypeChanged(ParameterTypeEvent event) {
+ if (event is null) {
+ throw new NullPointerException(
+ "Cannot send a null event to listeners."); //$NON-NLS-1$
+ }
+
+ if (!isListenerAttached()) {
+ return;
+ }
+
+ Object[] listeners = getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IParameterTypeListener listener = cast(IParameterTypeListener) listeners[i];
+ listener.parameterTypeChanged(event);
+ }
+ }
+
+ /**
+ * Returns the value converter associated with this parameter, if any.
+ *
+ * @return The parameter value converter, or null
if there is
+ * no value converter for this parameter.
+ * @throws NotDefinedException
+ * if the parameter type is not currently defined
+ */
+ public final AbstractParameterValueConverter getValueConverter() {
+ if (!isDefined()) {
+ throw new NotDefinedException(
+ "Cannot use getValueConverter() with an undefined ParameterType"); //$NON-NLS-1$
+ }
+
+ return parameterTypeConverter;
+ }
+
+ /**
+ * Returns whether the provided value is compatible with this parameter
+ * type. An object is compatible with a parameter type if the object is an
+ * instance of the class defined as the parameter's type class.
+ *
+ * @param value
+ * an object to check for compatibility with this parameter type;
+ * may be null
.
+ * @return true
if the value is compatible with this type,
+ * false
otherwise
+ * @throws NotDefinedException
+ * if the parameter type is not currently defined
+ */
+ public bool isCompatible(Object value) {
+ if (!isDefined()) {
+ throw new NotDefinedException(
+ "Cannot use isCompatible() with an undefined ParameterType"); //$NON-NLS-1$
+ }
+ return isInstanceOf(value, type);
+ }
+
+ /**
+ * Unregisters listener for changes to properties of this parameter type.
+ *
+ * @param listener
+ * the instance to unregister. Must not be null
.
+ * If an attempt is made to unregister an instance which is not
+ * already registered with this instance, no operation is
+ * performed.
+ */
+ public final void removeListener(IParameterTypeListener listener) {
+ removeListenerObject(cast(Object)listener);
+ }
+
+ /**
+ * The string representation of this parameter type. For debugging purposes
+ * only. This string should not be shown to an end user.
+ *
+ * @return The string representation; never null
.
+ */
+ public override final String toString() {
+ if (string is null) {
+ string = Format( "ParameterType({},{})", id, defined );
+ }
+ return string;
+ }
+
+ /**
+ * Makes this parameter type become undefined. Notification is sent to all
+ * listeners.
+ */
+ public final void undefine() {
+ string = null;
+
+ final bool definedChanged = defined;
+ defined = false;
+
+ type = null;
+ parameterTypeConverter = null;
+
+ fireParameterTypeChanged(new ParameterTypeEvent(this, definedChanged));
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ParameterTypeEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ParameterTypeEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
.
+ */
+ private final ParameterType parameterType;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param parameterType
+ * The parameter type that changed; must not be null
.
+ * @param definedChanged
+ * true
, iff the defined property changed.
+ */
+ this(ParameterType parameterType,
+ bool definedChanged) {
+
+ super(definedChanged);
+
+ if (parameterType is null) {
+ throw new NullPointerException();
+ }
+
+ this.parameterType = parameterType;
+ }
+
+ /**
+ * Returns the instance of the parameter type that changed.
+ *
+ * @return the instance of the parameter type that changed. Guaranteed not
+ * to be null
.
+ */
+ public final ParameterType getParameterType() {
+ return parameterType;
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ParameterValueConversionException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ParameterValueConversionException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
.
+ */
+ public this(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new instance of this class with the specified detail message
+ * and cause.
+ *
+ * @param message
+ * the detail message; may be null
.
+ * @param cause
+ * the cause; may be null
.
+ */
+ public this(String message,
+ Exception cause) {
+ super(message, cause);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ParameterValuesException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ParameterValuesException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 IParameterValues
. In applications based on the registry
+ * provided by core, this usually indicates a problem creating an
+ * IExecutableExtension
. For other applications, this exception
+ * could be used to signify any general problem during initialization.
+ * null
.
+ * @param cause
+ * the cause; may be null
.
+ */
+ public this(String message, Exception cause) {
+ super(message, cause);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/Parameterization.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/Parameterization.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 ParameterizedCommand
, which is used to refer to a command
+ * with a collection of parameterizations.
+ * null
.
+ */
+ private const IParameter parameter;
+
+ /**
+ * The value that defines the parameterization. This value may be
+ * null
.
+ */
+ private const String value;
+
+ /**
+ * Constructs a new instance of Parameterization
.
+ *
+ * @param parameter
+ * The parameter that is being parameterized; must not be
+ * null
.
+ * @param value
+ * The value for the parameter; may be null
.
+ */
+ public this(IParameter parameter, String value) {
+ if (parameter is null) {
+ throw new NullPointerException(
+ "You cannot parameterize a null parameter"); //$NON-NLS-1$
+ }
+
+ this.parameter = parameter;
+ this.value = value;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public final bool equals(Object object) {
+ if (this is object) {
+ return true;
+ }
+
+ if (!(cast(Parameterization)object)) {
+ return false;
+ }
+
+ Parameterization parameterization = cast(Parameterization) object;
+ if (!(Util.equals(this.parameter.getId(), parameterization.parameter
+ .getId()))) {
+ return false;
+ }
+
+ return Util.equals(this.value, parameterization.value);
+ }
+
+ /**
+ * Returns the parameter that is being parameterized.
+ *
+ * @return The parameter; never null
.
+ */
+ public final IParameter getParameter() {
+ return parameter;
+ }
+
+ /**
+ * Returns the value for the parameter in this parameterization.
+ *
+ * @return The value; may be null
.
+ */
+ public final String getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the human-readable name for the current value, if any. If the
+ * name cannot be found, then it simply returns the value. It also ensures
+ * that any null
values are converted into an empty string.
+ *
+ * @return The human-readable name of the value; never null
.
+ * @throws ParameterValuesException
+ * If the parameter needed to be initialized, but couldn't be.
+ */
+ public final String getValueName() {
+ auto parameterValues = parameter.getValues().getParameterValues();
+ String returnValue = null;
+ foreach( k, v; parameterValues ){
+ if (Util.equals(value, v)) {
+ returnValue = k;
+ break;
+ }
+ }
+ if (returnValue is null) {
+ return Util.ZERO_LENGTH_STRING;
+ }
+
+ return returnValue;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public override final hash_t toHash() {
+ if (hashCode is HASH_CODE_NOT_COMPUTED) {
+ hashCode = HASH_INITIAL * HASH_FACTOR + Util.toHash(cast(Object)parameter);
+ hashCode = hashCode * HASH_FACTOR + Util.toHash(value);
+ if (hashCode is HASH_CODE_NOT_COMPUTED) {
+ hashCode++;
+ }
+ }
+ return hashCode;
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/ParameterizedCommand.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/ParameterizedCommand.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,666 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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 String
to escape special characters in for
+ * serialization.
+ * @return a String
representing rawText
with
+ * special serialization characters escaped
+ * @see CommandManager#unescape(String)
+ * @since 3.2
+ */
+ private static final String escape(String rawText) {
+
+ // defer initialization of a StringBuffer until we know we need one
+ StringBuffer buffer;
+
+ for (int i = 0; i < rawText.length; i++) {
+
+ char c = rawText.charAt(i);
+ switch (c) {
+ case CommandManager.PARAMETER_START_CHAR:
+ case CommandManager.PARAMETER_END_CHAR:
+ case CommandManager.ID_VALUE_CHAR:
+ case CommandManager.PARAMETER_SEPARATOR_CHAR:
+ case CommandManager.ESCAPE_CHAR:
+ if (buffer is null) {
+ buffer = new StringBuffer(rawText.substring(0, i));
+ }
+ buffer.append(CommandManager.ESCAPE_CHAR);
+ buffer.append(c);
+ break;
+ default:
+ if (buffer !is null) {
+ buffer.append(c);
+ }
+ break;
+ }
+
+ }
+
+ if (buffer is null) {
+ return rawText;
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Generates every possible combination of parameter values for the given
+ * parameters. Parameters values that cannot be initialized are just
+ * ignored. Optional parameters are considered.
+ *
+ * @param startIndex
+ * The index in the parameters
that we should
+ * process. This must be a valid index.
+ * @param parameters
+ * The parameters in to process; must not be null
.
+ * @return A collection (Collection
) of combinations (List
+ * of Parameterization
).
+ */
+ private static final Seq!(Object) expandParameters(int startIndex,
+ IParameter[] parameters) {
+ int nextIndex = startIndex + 1;
+ bool noMoreParameters = (nextIndex >= parameters.length);
+
+ IParameter parameter = parameters[startIndex];
+ auto parameterizations = new ArraySeq!(Object);
+ if (parameter.isOptional()) {
+ parameterizations.append( cast(Object) null);
+ }
+
+ IParameterValues values = null;
+ try {
+ values = parameter.getValues();
+ } catch (ParameterValuesException e) {
+ if (noMoreParameters) {
+ return parameterizations;
+ }
+
+ // Make recursive call
+ return expandParameters(nextIndex, parameters);
+ }
+
+// Iterator parameterValueItr = parameterValues.entrySet()
+// .iterator();
+ auto parameterValues = values.getParameterValues();
+ auto set = new HashSet!(String);
+ foreach( k,v; parameterValues ){
+ set.add( v );
+ }
+
+
+ //while (parameterValueItr.hasNext()) {
+ foreach( v; set ){
+ //Map.Entry entry = (Map.Entry) parameterValueItr.next();
+ Parameterization parameterization = new Parameterization(
+ parameter, v);
+ parameterizations.append(parameterization);
+ }
+
+ // Check if another iteration will produce any more names.
+ int parameterizationCount = parameterizations.size();
+ if (noMoreParameters) {
+ // This is it, so just return the current parameterizations.
+ for (int i = 0; i < parameterizationCount; i++) {
+ Parameterization parameterization = cast(Parameterization) parameterizations
+ .get(i);
+ auto combination = new ArraySeq!(Object);
+ combination.append(parameterization);
+ parameterizations.replaceAt(i, combination);
+ }
+ return parameterizations;
+ }
+
+ // Make recursive call
+ auto suffixes = expandParameters(nextIndex, parameters);
+ suffixes.removeAll(cast(Object)null);
+ if (suffixes.drained()) {
+ // This is it, so just return the current parameterizations.
+ for (int i = 0; i < parameterizationCount; i++) {
+ Parameterization parameterization = cast(Parameterization) parameterizations
+ .get(i);
+ auto combination = new ArraySeq!(Object);
+ combination.append(parameterization);
+ parameterizations.replaceAt(i, combination);
+ }
+ return parameterizations;
+ }
+ auto returnValue = new ArraySeq!(Object);
+// Iterator suffixItr = suffixes.iterator();
+// while (suffixItr.hasNext()) {
+ foreach( v; suffixes ){
+// final List combination = (List) suffixItr.next();
+ auto combination = cast(Seq!(Object)) v;
+ int combinationSize = combination.size();
+ for (int i = 0; i < parameterizationCount; i++) {
+ Parameterization parameterization = cast(Parameterization) parameterizations
+ .get(i);
+ auto newCombination = new ArraySeq!(Object);
+ newCombination.capacity(combinationSize + 1);
+ newCombination.append(parameterization);
+ foreach( c; combination ){
+ newCombination.append(c);
+ }
+ returnValue.append(newCombination);
+ }
+ }
+
+ return returnValue;
+ }
+
+ /**
+ * ParameterValuesException
, then it is simply ignored.
+ * null
.
+ * @return A collection of ParameterizedCommand
instances
+ * representing all of the possible combinations. This value is
+ * never empty and it is never null
.
+ * @throws NotDefinedException
+ * If the command is not defined.
+ */
+ public static final Seq!(Object) generateCombinations(Command command) {
+ IParameter[] parameters = command.getParameters();
+ if (parameters is null) {
+ auto res = new ArraySeq!(Object);
+ res.append( new ParameterizedCommand(command, null) );
+ return res;
+ }
+
+ auto expansion = expandParameters(0, parameters);
+ auto combinations = new ArraySeq!(Object);
+ combinations.capacity(expansion.size());
+ foreach( v; expansion ){
+// Iterator expansionItr = expansion.iterator();
+// while (expansionItr.hasNext()) {
+ auto combination = cast(Seq!(Object)) v;
+ if (combination is null) {
+ combinations.append(new ParameterizedCommand(command, null));
+ } else {
+ combination.removeAll(cast(Object)null);
+ if (combination.drained()) {
+ combinations.append(new ParameterizedCommand(command, null));
+ } else {
+ Parameterization[] parameterizations = cast(Parameterization[]) combination
+ .toArray();
+ combinations.append(new ParameterizedCommand(command,
+ parameterizations));
+ }
+ }
+ }
+
+ return combinations;
+ }
+
+ /**
+ * The base command which is being parameterized. This value is never
+ * null
.
+ */
+ private const Command command;
+
+ /**
+ * The hash code for this object. This value is computed lazily, and marked
+ * as invalid when one of the values on which it is based changes.
+ */
+ private /+transient+/ int hashCode = HASH_CODE_NOT_COMPUTED;
+
+ /**
+ * This is an array of parameterization defined for this command. This value
+ * may be null
if the command has no parameters.
+ */
+ private const Parameterization[] parameterizations;
+
+ private String name;
+
+ /**
+ * Constructs a new instance of ParameterizedCommand
with
+ * specific values for zero or more of its parameters.
+ *
+ * @param command
+ * The command that is parameterized; must not be
+ * null
.
+ * @param parameterizations
+ * An array of parameterizations binding parameters to values for
+ * the command. This value may be null
. This
+ * argument is not copied; if you need to make changes to it
+ * after constructing this parameterized command, then make a
+ * copy yourself.
+ */
+ public this(Command command,
+ Parameterization[] parameterizations) {
+ if (command is null) {
+ throw new NullPointerException(
+ "A parameterized command cannot have a null command"); //$NON-NLS-1$
+ }
+
+ this.command = command;
+ this.parameterizations = (parameterizations is null || parameterizations.length is 0) ? null
+ : parameterizations;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public final int compareTo(Object object) {
+ ParameterizedCommand command = cast(ParameterizedCommand) object;
+ bool thisDefined = this.command.isDefined();
+ bool otherDefined = command.command.isDefined();
+ if (!thisDefined || !otherDefined) {
+ return Util.compare(thisDefined, otherDefined);
+ }
+
+ try {
+ int compareTo = getName() < command.getName();
+ if (compareTo is 0) {
+ return getId() < command.getId();
+ }
+ return compareTo;
+ } catch (NotDefinedException e) {
+ throw new Exception (
+ "Concurrent modification of a command's defined state"); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public final bool equals(Object object) {
+ if (this is object) {
+ return true;
+ }
+
+ if (!(cast(ParameterizedCommand)object)) {
+ return false;
+ }
+
+ ParameterizedCommand command = cast(ParameterizedCommand) object;
+ if (!Util.equals(this.command, command.command)) {
+ return false;
+ }
+
+ return Util.equals(this.parameterizations, command.parameterizations);
+ }
+
+ /**
+ * Executes this command with its parameters. This method will succeed
+ * regardless of whether the command is enabled or defined. It is
+ * preferrable to use {@link #executeWithChecks(Object, Object)}.
+ *
+ * @param trigger
+ * The object that triggered the execution; may be
+ * null
.
+ * @param applicationContext
+ * The state of the application at the time the execution was
+ * triggered; may be null
.
+ * @return The result of the execution; may be null
.
+ * @throws ExecutionException
+ * If the handler has problems executing this command.
+ * @throws NotHandledException
+ * If there is no handler.
+ * @deprecated Please use {@link #executeWithChecks(Object, Object)}
+ * instead.
+ */
+ public final Object execute(Object trigger,
+ Object applicationContext) {
+ return command.execute(new ExecutionEvent(command, getParameterMap(),
+ trigger, applicationContext));
+ }
+
+ /**
+ * Executes this command with its parameters. This does extra checking to
+ * see if the command is enabled and defined. If it is not both enabled and
+ * defined, then the execution listeners will be notified and an exception
+ * thrown.
+ *
+ * @param trigger
+ * The object that triggered the execution; may be
+ * null
.
+ * @param applicationContext
+ * The state of the application at the time the execution was
+ * triggered; may be null
.
+ * @return The result of the execution; may be null
.
+ * @throws ExecutionException
+ * If the handler has problems executing this command.
+ * @throws NotDefinedException
+ * If the command you are trying to execute is not defined.
+ * @throws NotEnabledException
+ * If the command you are trying to execute is not enabled.
+ * @throws NotHandledException
+ * If there is no handler.
+ * @since 3.2
+ */
+ public final Object executeWithChecks(Object trigger,
+ Object applicationContext) {
+ return command.executeWithChecks(new ExecutionEvent(command,
+ getParameterMap(), trigger, applicationContext));
+ }
+
+ /**
+ * Returns the base command. It is possible for more than one parameterized
+ * command to have the same identifier.
+ *
+ * @return The command; never null
, but may be undefined.
+ */
+ public final Command getCommand() {
+ return command;
+ }
+
+ /**
+ * Returns the command's base identifier. It is possible for more than one
+ * parameterized command to have the same identifier.
+ *
+ * @return The command id; never null
.
+ */
+ public final String getId() {
+ return command.getId();
+ }
+
+ /**
+ * Returns a human-readable representation of this command with all of its
+ * parameterizations.
+ *
+ * @return The human-readable representation of this parameterized command;
+ * never null
.
+ * @throws NotDefinedException
+ * If the underlying command is not defined.
+ */
+ public final String getName() {
+ if (name is null) {
+ StringBuffer nameBuffer = new StringBuffer();
+ nameBuffer.append(command.getName());
+ if (parameterizations !is null) {
+ nameBuffer.append(" ("); //$NON-NLS-1$
+ int parameterizationCount = parameterizations.length;
+ for (int i = 0; i < parameterizationCount; i++) {
+ Parameterization parameterization = parameterizations[i];
+ nameBuffer
+ .append(parameterization.getParameter().getName());
+ nameBuffer.append(": "); //$NON-NLS-1$
+ try {
+ nameBuffer.append(parameterization.getValueName());
+ } catch (ParameterValuesException e) {
+ /*
+ * Just let it go for now. If someone complains we can
+ * add more info later.
+ */
+ }
+
+ // If there is another item, append a separator.
+ if (i + 1 < parameterizationCount) {
+ nameBuffer.append(", "); //$NON-NLS-1$
+ }
+ }
+ nameBuffer.append(')');
+ }
+ name = nameBuffer.toString();
+ }
+ return name;
+ }
+
+ /**
+ * Returns the parameter map, as can be used to construct an
+ * ExecutionEvent
.
+ *
+ * @return The map of parameter ids (String
) to parameter
+ * values (String
). This map is never
+ * null
, but may be empty.
+ */
+ public final Map!(String,String) getParameterMap() {
+ if ((parameterizations is null) || (parameterizations.length is 0)) {
+ return EMPTY_MAP;
+ }
+
+ auto parameterMap = new HashMap!(String,String);
+ for (int i = 0; i < parameterizations.length; i++) {
+ Parameterization parameterization = parameterizations[i];
+ parameterMap.add(parameterization.getParameter().getId(),
+ parameterization.getValue());
+ }
+ return parameterMap;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public override final hash_t toHash() {
+ if (hashCode is HASH_CODE_NOT_COMPUTED) {
+ hashCode = HASH_INITIAL * HASH_FACTOR + Util.toHash(command);
+ hashCode = hashCode * HASH_FACTOR;
+ if (parameterizations !is null) {
+ for (int i = 0; i < parameterizations.length; i++) {
+ hashCode += Util.toHash(parameterizations[i]);
+ }
+ }
+ if (hashCode is HASH_CODE_NOT_COMPUTED) {
+ hashCode++;
+ }
+ }
+ return hashCode;
+ }
+
+ /**
+ * Returns a {@link String} containing the command id, parameter ids and
+ * parameter values for this {@link ParameterizedCommand}. The returned
+ * {@link String} can be stored by a client and later used to reconstruct an
+ * equivalent {@link ParameterizedCommand} using the
+ * {@link CommandManager#deserialize(String)} method.
+ *
+ *
+ *
+ * serialization = commandId [ '(' parameters ')' ]
+ * parameters = parameter [ ',' parameters ]
+ * parameter = parameterId [ '=' parameterValue ]
+ * (
, )
,
+ * ,
and =
) indicate literal characters.
+ * commandId
represents the command id encoded with
+ * separator characters escaped. parameterId
and
+ * parameterValue
represent the parameter ids and
+ * values encoded with separator characters escaped. The separator
+ * characters (
, )
, ,
and
+ * =
are escaped by prepending a %
. This
+ * requires %
to be escaped, which is also done by prepending
+ * a %
.
+ * parameterValue
indicates that the value of the
+ * parameter is null
.
+ * dwtx.ui.perspectives.showPerspective(dwtx.ui.perspectives.showPerspective.perspectiveId=dwtx.ui.resourcePerspective)
+ * null
value parameters, and escaped =
in the
+ * third parameter value.
+ * command.id(param1.id=value1,param2.id,param3.id=esc%=val3)
+ * null
.
+ * @see CommandManager#deserialize(String)
+ * @since 3.2
+ */
+ public final String serialize() {
+ String escapedId = escape(getId());
+
+ if ((parameterizations is null) || (parameterizations.length is 0)) {
+ return escapedId;
+ }
+
+ StringBuffer buffer = new StringBuffer(escapedId);
+ buffer.append(CommandManager.PARAMETER_START_CHAR);
+
+ for (int i = 0; i < parameterizations.length; i++) {
+
+ if (i > 0) {
+ // insert separator between parameters
+ buffer.append(CommandManager.PARAMETER_SEPARATOR_CHAR);
+ }
+
+ Parameterization parameterization = parameterizations[i];
+ String parameterId = parameterization.getParameter().getId();
+ String escapedParameterId = escape(parameterId);
+
+ buffer.append(escapedParameterId);
+
+ String parameterValue = parameterization.getValue();
+ if (parameterValue !is null) {
+ String escapedParameterValue = escape(parameterValue);
+ buffer.append(CommandManager.ID_VALUE_CHAR);
+ buffer.append(escapedParameterValue);
+ }
+ }
+
+ buffer.append(CommandManager.PARAMETER_END_CHAR);
+
+ return buffer.toString();
+ }
+
+ public override final String toString() {
+ return Format( "ParameterizedCommand({},{})", command, parameterizations);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/SerializationException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/SerializationException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 null
.
+ */
+ public this(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new instance of this class with the specified detail message
+ * and cause.
+ *
+ * @param message
+ * the detail message; may be null
.
+ * @param cause
+ * the cause; may be null
.
+ */
+ public this(String message, Exception cause) {
+ super(message, cause);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/State.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/State.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
if it has not
+ * been initialized.
+ */
+ private String id;
+
+ /**
+ * The value held by this state; may be anything at all.
+ */
+ private Object value;
+
+ /**
+ * Adds a listener to changes for this state.
+ *
+ * @param listener
+ * The listener to add; must not be null
.
+ */
+ public void addListener(IStateListener listener) {
+ addListenerObject(cast(Object)listener);
+ }
+
+ /**
+ * Disposes of this state. This allows the state to unregister itself with
+ * any managers or as a listener.
+ */
+ public void dispose() {
+ // The default implementation does nothing.
+ }
+
+ /**
+ * Notifies listeners to this state that it has changed in some way.
+ *
+ * @param oldValue
+ * The old value; may be anything.
+ */
+ protected final void fireStateChanged(Object oldValue) {
+ final Object[] listeners = getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IStateListener listener = cast(IStateListener) listeners[i];
+ listener.handleStateChange(this, oldValue);
+ }
+ }
+
+ /**
+ * Returns the identifier for this state.
+ *
+ * @return The id; may be null
.
+ */
+ public final String getId() {
+ return id;
+ }
+
+ /**
+ * The current value associated with this state. This can be any type of
+ * object, but implementations will usually restrict this value to a
+ * particular type.
+ *
+ * @return The current value; may be anything.
+ */
+
+ public Object getValue() {
+ return value;
+ }
+
+ /**
+ * Removes a listener to changes from this state.
+ *
+ * @param listener
+ * The listener to remove; must not be null
.
+ */
+
+ public void removeListener(IStateListener listener) {
+ removeListenerObject(cast(Object)listener);
+ }
+
+ /**
+ * Sets the identifier for this object. This method should only be called
+ * by the command framework. Clients should not call this method.
+ *
+ * @param id
+ * The id; must not be null
.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Sets the value for this state object.
+ *
+ * @param value
+ * The value to set; may be anything.
+ */
+ public void setValue(Object value) {
+ if (!Util.equals(this.value, value)) {
+ final Object oldValue = this.value;
+ this.value = value;
+ fireStateChanged(oldValue);
+ }
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/AbstractBitSetEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/AbstractBitSetEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 1
) if the corresponding property has
+ * changed. It can be assumed that this value will be correctly initialized
+ * by the superconstructor.
+ */
+ protected int changedValues = 0;
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/AbstractHandleObjectEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/AbstractHandleObjectEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 NamedHandleObject
. This provides
+ * notification of changes to the defined state, the name and the description.
+ * AbstractHandleObjectEvent
.
+ *
+ * @param definedChanged
+ * true
, iff the defined property changed.
+ */
+ protected this( bool definedChanged) {
+ if (definedChanged) {
+ changedValues |= CHANGED_DEFINED;
+ }
+ }
+
+ /**
+ * Returns whether or not the defined property changed.
+ *
+ * @return true
, iff the defined property changed.
+ */
+ public final bool isDefinedChanged() {
+ return ((changedValues & CHANGED_DEFINED) !is 0);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/AbstractNamedHandleEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/AbstractNamedHandleEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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
+ ******************************************************************************/
+
+module dwtx.core.commands.common.AbstractNamedHandleEvent;
+
+import dwtx.core.commands.common.AbstractHandleObjectEvent;
+
+/**
+ * NamedHandleObject
. This provides
+ * notification of changes to the defined state, the name and the description.
+ * AbstractHandleObjectEvent
.
+ *
+ * @param definedChanged
+ * true
, iff the defined property changed.
+ * @param descriptionChanged
+ * true
, iff the description property changed.
+ * @param nameChanged
+ * true
, iff the name property changed.
+ */
+ protected this(bool definedChanged,
+ bool descriptionChanged, bool nameChanged) {
+ super(definedChanged);
+
+ if (descriptionChanged) {
+ changedValues |= CHANGED_DESCRIPTION;
+ }
+ if (nameChanged) {
+ changedValues |= CHANGED_NAME;
+ }
+ }
+
+ /**
+ * Returns whether or not the description property changed.
+ *
+ * @return true
, iff the description property changed.
+ */
+ public final bool isDescriptionChanged() {
+ return ((changedValues & CHANGED_DESCRIPTION) !is 0);
+ }
+
+ /**
+ * Returns whether or not the name property changed.
+ *
+ * @return true
, iff the name property changed.
+ */
+ public final bool isNameChanged() {
+ return ((changedValues & CHANGED_NAME) !is 0);
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/CommandException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/CommandException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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 null
.
+ */
+ private Exception cause;
+
+ /**
+ * Creates a new instance of this class with the specified detail message.
+ *
+ * @param message
+ * the detail message; may be null
.
+ */
+ public this(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new instance of this class with the specified detail message
+ * and cause.
+ *
+ * @param message
+ * the detail message; may be null
.
+ * @param cause
+ * the cause; may be null
.
+ */
+ public this(String message, Exception cause) {
+ super(message);
+ // don't pass the cause to super, to allow compilation against JCL Foundation
+ this.cause = cause;
+ }
+
+ /**
+ * Returns the cause of this throwable or null
if the
+ * cause is nonexistent or unknown.
+ *
+ * @return the cause or null
+ */
+ public Exception getCause() {
+ return cause;
+ }
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/EventManager.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/EventManager.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
.
+ */
+ private static const Object[] EMPTY_ARRAY = null;
+
+ /**
+ * A collection of objects listening to changes to this manager. This
+ * collection is null
if there are no listeners.
+ */
+ private /+transient+/ ListenerList listenerList = null;
+
+ /**
+ * Adds a listener to this manager that will be notified when this manager's
+ * state changes.
+ *
+ * @param listener
+ * The listener to be added; must not be null
.
+ */
+ protected synchronized final void addListenerObject(Object listener) {
+ if (listenerList is null) {
+ listenerList = new ListenerList(ListenerList.IDENTITY);
+ }
+
+ listenerList.add(listener);
+ }
+
+ /**
+ * Clears all of the listeners from the listener list.
+ */
+ protected synchronized final void clearListeners() {
+ if (listenerList !is null) {
+ listenerList.clear();
+ }
+ }
+
+ /**
+ * Returns the listeners attached to this event manager.
+ *
+ * @return The listeners currently attached; may be empty, but never
+ * null
+ */
+ protected final Object[] getListeners() {
+ ListenerList list = listenerList;
+ if (list is null) {
+ return EMPTY_ARRAY;
+ }
+
+ return list.getListeners();
+ }
+
+ /**
+ * Whether one or more listeners are attached to the manager.
+ *
+ * @return true
if listeners are attached to the manager;
+ * false
otherwise.
+ */
+ protected final bool isListenerAttached() {
+ return listenerList !is null;
+ }
+
+ /**
+ * Removes a listener from this manager.
+ *
+ * @param listener
+ * The listener to be removed; must not be null
.
+ */
+ protected synchronized final void removeListenerObject(Object listener) {
+ if (listenerList !is null) {
+ listenerList.remove(listener);
+
+ if (listenerList.isEmpty()) {
+ listenerList = null;
+ }
+ }
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/HandleObject.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/HandleObject.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 equals
and toString
. Please use
+ * string
to cache the result for toString
once
+ * calculated.
+ * String
. It is important that this identifier
+ * remain unique within whatever context that handle object is being used. For
+ * example, there should only ever be one instance of Command
+ * with a given identifier.
+ * null
.
+ */
+ protected /+final+/ String id;
+
+ /**
+ * The string representation of this object. This string is for debugging
+ * purposes only, and is not meant to be displayed to the user. This value
+ * is computed lazily, and is cleared if one of its dependent values
+ * changes.
+ */
+ protected /+transient+/ String string = null;
+
+ /**
+ * Constructs a new instance of HandleObject
.
+ *
+ * @param id
+ * The id of this handle; must not be null
.
+ */
+ protected this(String id) {
+ if (id is null) {
+ throw new NullPointerException(
+ "Cannot create a handle with a null id"); //$NON-NLS-1$
+ }
+
+ this.id = id;
+ }
+
+ /**
+ * Tests whether this object is equal to another object. A handle object is
+ * only equal to another handle object with the same id and the same class.
+ *
+ * @param object
+ * The object with which to compare; may be null
.
+ * @return true
if the objects are equal; false
+ * otherwise.
+ */
+ public override int opEquals(Object object) {
+ // Check if they're the same.
+ if (object is this) {
+ return true;
+ }
+
+ // Check if they're the same type.
+ if (!(cast(HandleObject)object)) {
+ return false;
+ }
+
+ // Check each property in turn.
+ final HandleObject handle= cast(HandleObject) object;
+ return Util.equals(id, handle.id)
+ && (this.classinfo is handle.classinfo);
+ }
+
+ public override final String getId() {
+ return id;
+ }
+
+ /**
+ * Computes the hash code for this object based on the id.
+ *
+ * @return The hash code for this object.
+ */
+ public final override hash_t toHash() {
+ if (hashCode is HASH_CODE_NOT_COMPUTED) {
+ hashCode = HASH_INITIAL * HASH_FACTOR + Util.toHash(id);
+ if (hashCode is HASH_CODE_NOT_COMPUTED) {
+ hashCode++;
+ }
+ }
+ return hashCode;
+ }
+
+ /**
+ * Whether this instance is defined. A defined instance is one that has been
+ * fully initialized. This allows objects to effectively disappear even
+ * though other objects may still have references to them.
+ *
+ * @return true
if this object is defined; false
+ * otherwise.
+ */
+ public final bool isDefined() {
+ return defined;
+ }
+
+ /**
+ * The string representation of this object -- for debugging purposes only.
+ * This string should not be shown to an end user.
+ *
+ * @return The string representation; never null
.
+ */
+ public override abstract String toString();
+
+ /**
+ * Makes this object becomes undefined. This method should make any defined
+ * properties null
. It should also send notification to any
+ * listeners that these properties have changed.
+ */
+ public abstract void undefine();
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/HandleObjectManager.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/HandleObjectManager.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
.
+ */
+ protected const Set!(Object) definedHandleObjects;
+
+ /**
+ * The map of identifiers (String
) to handle objects (
+ * HandleObject
). This collection may be empty, but it is
+ * never null
.
+ */
+ protected const Map!( String, Object ) handleObjectsById;
+
+ public this(){
+ definedHandleObjects = new HashSet!(Object)();
+ handleObjectsById = new HashMap!( String, Object )();
+ }
+
+ /**
+ * Verifies that the identifier is valid. Exceptions will be thrown if the
+ * identifier is invalid in some way.
+ *
+ * @param id
+ * The identifier to validate; may be anything.
+ */
+ protected final void checkId(String id) {
+ if (id is null) {
+ throw new NullPointerException(
+ "A handle object may not have a null identifier"); //$NON-NLS-1$
+ }
+
+ if (id.length < 1) {
+ throw new IllegalArgumentException(
+ "The handle object must not have a zero-length identifier"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Returns the set of identifiers for those handle objects that are defined.
+ *
+ * @return The set of defined handle object identifiers; this value may be
+ * empty, but it is never null
.
+ */
+ protected final HashSet!(String) getDefinedHandleObjectIds() {
+ HashSet!(String) definedHandleObjectIds = new HashSet!(String)(/+definedHandleObjects
+ .size()+/);
+ foreach ( v; definedHandleObjects.elements() ) {
+ auto handleObject = cast(HandleObject)v;
+ String id = handleObject.getId();
+ definedHandleObjectIds.add(id);
+ }
+ return definedHandleObjectIds;
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/IIdentifiable.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/IIdentifiable.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,1 @@
+/*******************************************************************************
* Copyright (c) 2006 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 null
.
*/
String getId();
}
\ No newline at end of file
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/NamedHandleObject.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/NamedHandleObject.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 Command
, Context
and Scheme
.
+ *
+ * @since 3.1
+ */
+public abstract class NamedHandleObject : HandleObject {
+
+ /**
+ * The description for this handle. This value may be null
if
+ * the handle is undefined or has no description.
+ */
+ protected String description = null;
+
+ /**
+ * The name of this handle. This valud should not be null
+ * unless the handle is undefined.
+ */
+ protected String name = null;
+
+ /**
+ * Constructs a new instance of NamedHandleObject
.
+ *
+ * @param id
+ * The identifier for this handle; must not be null
.
+ */
+ protected this(String id) {
+ super(id);
+ }
+
+ /**
+ * Returns the description for this handle.
+ *
+ * @return The description; may be null
if there is no
+ * description.
+ * @throws NotDefinedException
+ * If the handle is not currently defined.
+ */
+ public String getDescription() {
+ if (!isDefined()) {
+ throw new NotDefinedException(
+ "Cannot get a description from an undefined object. " //$NON-NLS-1$
+ ~ id);
+ }
+
+ return description;
+ }
+
+ /**
+ * Returns the name for this handle.
+ *
+ * @return The name for this handle; never null
.
+ * @throws NotDefinedException
+ * If the handle is not currently defined.
+ */
+ public String getName() {
+ if (!isDefined()) {
+ throw new NotDefinedException(
+ "Cannot get the name from an undefined object. " //$NON-NLS-1$
+ ~ id);
+ }
+
+ return name;
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/NamedHandleObjectComparator.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/NamedHandleObjectComparator.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,1 @@
+/*******************************************************************************
* Copyright (c) 2005 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 NamedHandleObject
for display to
* an end user. The comparison is based on the name of the instances.
*
* @since 3.2
*/
public class NamedHandleObjectComparator /+: Comparator+/ {
/**
* Compares to instances of NamedHandleObject based on their names. This is
* useful is they are display to an end user.
*
* @param left
* The first obect to compare; may be null
.
* @param right
* The second object to compare; may be null
.
* @return -1
if left
is null
* and right
is not null
;
* 0
if they are both null
;
* 1
if left
is not null
* and right
is null
. Otherwise, the
* result of left.compareTo(right)
.
*/
public final int compare(Object left, Object right) {
NamedHandleObject a = cast(NamedHandleObject) left;
NamedHandleObject b = cast(NamedHandleObject) right;
String aName = null;
try {
aName = a.getName();
} catch (NotDefinedException e) {
// Leave aName as null.
}
String bName = null;
try {
bName = b.getName();
} catch (NotDefinedException e) {
// Leave bName as null.
}
return Util.compare(aName, bName);
}
}
\ No newline at end of file
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/common/NotDefinedException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/common/NotDefinedException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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 null
.
+ */
+ public this(String s) {
+ super(s);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/contexts/Context.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/contexts/Context.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 ContextManager
for any identifier, whether or not an context
+ * with that identifier is defined in the extension registry.
+ * NotDefinedException
being
+ * thrown.
+ * null
if there are no listeners.
+ */
+ private Set!(IContextListener) listeners = null;
+
+ /**
+ * The parent identifier for this context. The meaning of a parent is
+ * dependent on the system using contexts. This value can be
+ * null
if the context has no parent.
+ */
+ private String parentId = null;
+
+ /**
+ * Constructs a new instance of Context
.
+ *
+ * @param id
+ * The id for this context; must not be null
.
+ */
+ this(String id) {
+ super(id);
+ }
+
+ /**
+ * Registers an instance of IContextListener
to listen for
+ * changes to properties of this instance.
+ *
+ * @param listener
+ * the instance to register. Must not be null
. If
+ * an attempt is made to register an instance which is already
+ * registered with this instance, no operation is performed.
+ */
+ public final void addContextListener(IContextListener listener) {
+ if (listener is null) {
+ throw new NullPointerException();
+ }
+
+ if (listeners is null) {
+ listeners = new HashSet!(IContextListener);
+ }
+
+ listeners.add(listener);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public final int compareTo(Object object) {
+ Context scheme = cast(Context) object;
+ int compareTo = Util.compare(this.id, scheme.id);
+ if (compareTo is 0) {
+ compareTo = Util.compare(this.name, scheme.name);
+ if (compareTo is 0) {
+ compareTo = Util.compare(this.parentId, scheme.parentId);
+ if (compareTo is 0) {
+ compareTo = Util.compare(this.description,
+ scheme.description);
+ if (compareTo is 0) {
+ compareTo = Util.compare(this.defined, scheme.defined);
+ }
+ }
+ }
+ }
+
+ return compareTo;
+ }
+
+ /**
+ * true
.
+ * null
.
+ * @param description
+ * The description for this context; may be null
.
+ * @param parentId
+ * The parent identifier for this context; may be
+ * null
.
+ */
+ public final void define(String name, String description,
+ String parentId) {
+ if (name is null) {
+ throw new NullPointerException(
+ "The name of a scheme cannot be null"); //$NON-NLS-1$
+ }
+
+ bool definedChanged = !this.defined;
+ this.defined = true;
+
+ bool nameChanged = !Util.equals(this.name, name);
+ this.name = name;
+
+ bool descriptionChanged = !Util.equals(this.description,
+ description);
+ this.description = description;
+
+ bool parentIdChanged = !Util.equals(this.parentId, parentId);
+ this.parentId = parentId;
+
+ fireContextChanged(new ContextEvent(this, definedChanged, nameChanged,
+ descriptionChanged, parentIdChanged));
+ }
+
+ /**
+ * Notifies all listeners that this context has changed. This sends the
+ * given event to all of the listeners, if any.
+ *
+ * @param event
+ * The event to send to the listeners; must not be
+ * null
.
+ */
+ private final void fireContextChanged(ContextEvent event) {
+ if (event is null) {
+ throw new NullPointerException(
+ "Cannot send a null event to listeners."); //$NON-NLS-1$
+ }
+
+ if (listeners is null) {
+ return;
+ }
+
+ foreach( listener; listeners){
+ listener.contextChanged(event);
+ }
+ }
+
+ /**
+ * Returns the identifier of the parent of this instance.
+ * null
.
+ * @throws NotDefinedException
+ * if this instance is not defined.
+ */
+ public final String getParentId() {
+ if (!defined) {
+ throw new NotDefinedException(
+ "Cannot get the parent identifier from an undefined context. " //$NON-NLS-1$
+ ~ id);
+ }
+
+ return parentId;
+ }
+
+ /**
+ * Unregisters an instance of IContextListener
listening for
+ * changes to properties of this instance.
+ *
+ * @param contextListener
+ * the instance to unregister. Must not be null
.
+ * If an attempt is made to unregister an instance which is not
+ * already registered with this instance, no operation is
+ * performed.
+ */
+ public final void removeContextListener(
+ IContextListener contextListener) {
+ if (contextListener is null) {
+ throw new NullPointerException("Cannot remove a null listener."); //$NON-NLS-1$
+ }
+
+ if (listeners is null) {
+ return;
+ }
+
+ listeners.remove(contextListener);
+
+ if (listeners.drained()) {
+ listeners = null;
+ }
+ }
+
+ /**
+ * The string representation of this context -- for debugging purposes only.
+ * This string should not be shown to an end user.
+ *
+ * @return The string representation; never null
.
+ */
+ public override final String toString() {
+ if (string is null) {
+ final StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append("Context("); //$NON-NLS-1$
+ stringBuffer.append(id);
+ stringBuffer.append(',');
+ stringBuffer.append(name);
+ stringBuffer.append(',');
+ stringBuffer.append(description);
+ stringBuffer.append(',');
+ stringBuffer.append(parentId);
+ stringBuffer.append(',');
+ stringBuffer.append(defined ? "true" : "false");
+ stringBuffer.append(')');
+ string = stringBuffer.toString();
+ }
+ return string;
+ }
+
+ /**
+ * Makes this context become undefined. This has the side effect of changing
+ * the name, description and parent identifier to null
.
+ * Notification is sent to all listeners.
+ */
+ public final void undefine() {
+ string = null;
+
+ bool definedChanged = defined;
+ defined = false;
+
+ bool nameChanged = name !is null;
+ name = null;
+
+ bool descriptionChanged = description !is null;
+ description = null;
+
+ bool parentIdChanged = parentId !is null;
+ parentId = null;
+
+ fireContextChanged(new ContextEvent(this, definedChanged, nameChanged,
+ descriptionChanged, parentIdChanged));
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/contexts/ContextEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/contexts/ContextEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 IContext
.
+ * null
.
+ */
+ private Context context;
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param context
+ * the instance of the interface that changed; must not be
+ * null
.
+ * @param definedChanged
+ * true
, iff the defined property changed.
+ * @param nameChanged
+ * true
, iff the name property changed.
+ * @param descriptionChanged
+ * true
, iff the description property changed.
+ * @param parentIdChanged
+ * true
, iff the parentId property changed.
+ */
+ public this(Context context, bool definedChanged,
+ bool nameChanged, bool descriptionChanged,
+ bool parentIdChanged) {
+ super(definedChanged, descriptionChanged, nameChanged);
+
+ if (context is null) {
+ throw new NullPointerException();
+ }
+ this.context = context;
+
+ if (parentIdChanged) {
+ changedValues |= CHANGED_PARENT_ID;
+ }
+ }
+
+ /**
+ * Returns the instance of the interface that changed.
+ *
+ * @return the instance of the interface that changed. Guaranteed not to be
+ * null
.
+ */
+ public final Context getContext() {
+ return context;
+ }
+
+ /**
+ * Returns whether or not the parentId property changed.
+ *
+ * @return true
, iff the parentId property changed.
+ */
+ public final bool isParentIdChanged() {
+ return ((changedValues & CHANGED_PARENT_ID) !is 0);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/contexts/ContextManager.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/contexts/ContextManager.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,339 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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 true
if the context manager should
+ * print information to System.out
when certain boundary
+ * conditions occur.
+ */
+ public static bool DEBUG = false;
+
+ /**
+ * The set of active context identifiers. This value may be empty, but it is
+ * never null
.
+ */
+ private Set!(String) activeContextIds;
+ private static Set!(String) EMPTY_SET;
+
+ // allow the ContextManager to send one event for a larger delta
+ private bool caching = false;
+
+ private int cachingRef = 0;
+
+ private bool activeContextsChange = false;
+
+ private Set!(String) oldIds = null;
+
+ public this(){
+ activeContextIds = new HashSet!(String);
+ if( EMPTY_SET is null ){
+ EMPTY_SET = new HashSet!(String);
+ }
+ }
+
+ /**
+ * Activates a context in this context manager.
+ *
+ * @param contextId
+ * The identifier of the context to activate; must not be
+ * null
.
+ */
+ public final void addActiveContext(String contextId) {
+ if (DEFER_EVENTS.equals(contextId)) {
+ cachingRef++;
+ if (cachingRef is 1 ) {
+ setEventCaching(true);
+ }
+ return;
+ } else if (SEND_EVENTS.equals(contextId)) {
+ cachingRef--;
+ if (cachingRef is 0) {
+ setEventCaching(false);
+ }
+ return;
+ }
+
+ if (activeContextIds.contains(contextId)) {
+ return;
+ }
+ activeContextsChange = true;
+
+ if (caching) {
+ activeContextIds.add(contextId);
+ } else {
+ Set!(String) previouslyActiveContextIds = activeContextIds.duplicate();
+ activeContextIds.add(contextId);
+
+ fireContextManagerChanged(new ContextManagerEvent(this, null,
+ false, true, previouslyActiveContextIds));
+ }
+
+ if (DEBUG) {
+ Tracing.printTrace("CONTEXTS", SetToString(activeContextIds)); //$NON-NLS-1$
+ }
+
+ }
+
+ /**
+ * Adds a listener to this context manager. The listener will be notified
+ * when the set of defined contexts changes. This can be used to track the
+ * global appearance and disappearance of contexts.
+ *
+ * @param listener
+ * The listener to attach; must not be null
.
+ */
+ public final void addContextManagerListener(
+ IContextManagerListener listener) {
+ addListenerObject(cast(Object)listener);
+ }
+
+ public final void contextChanged(ContextEvent contextEvent) {
+ if (contextEvent.isDefinedChanged()) {
+ Context context = contextEvent.getContext();
+ String contextId = context.getId();
+ bool contextIdAdded = context.isDefined();
+ if (contextIdAdded) {
+ definedHandleObjects.add(context);
+ } else {
+ definedHandleObjects.remove(context);
+ }
+ if (isListenerAttached()) {
+ fireContextManagerChanged(new ContextManagerEvent(this,
+ contextId, contextIdAdded, false, null));
+ }
+ }
+ }
+
+ /**
+ * Notifies all of the listeners to this manager that the set of defined
+ * context identifiers has changed.
+ *
+ * @param event
+ * The event to send to all of the listeners; must not be
+ * null
.
+ */
+ private final void fireContextManagerChanged(ContextManagerEvent event) {
+ if (event is null) {
+ throw new NullPointerException();
+ }
+
+ Object[] listeners = getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IContextManagerListener listener = cast(IContextManagerListener) listeners[i];
+ listener.contextManagerChanged(event);
+ }
+ }
+
+ /**
+ * Returns the set of active context identifiers.
+ *
+ * @return The set of active context identifiers; this value may be
+ * null
if no active contexts have been set yet. If
+ * the set is not null
, then it contains only
+ * instances of String
.
+ */
+ public final SetView!(String) getActiveContextIds() {
+ return /+Collections.unmodifiableSet(+/activeContextIds/+)+/;
+ }
+
+ /**
+ * Gets the context with the given identifier. If no such context currently
+ * exists, then the context will be created (but be undefined).
+ *
+ * @param contextId
+ * The identifier to find; must not be null
.
+ * @return The context with the given identifier; this value will never be
+ * null
, but it might be undefined.
+ * @see Context
+ */
+ public final Context getContext(String contextId) {
+ checkId(contextId);
+
+ Context context = cast(Context) handleObjectsById.get(contextId);
+ if (context is null) {
+ context = new Context(contextId);
+ handleObjectsById.add(contextId, context);
+ context.addContextListener(this);
+ }
+
+ return context;
+ }
+
+ /**
+ * Returns the set of identifiers for those contexts that are defined.
+ *
+ * @return The set of defined context identifiers; this value may be empty,
+ * but it is never null
.
+ */
+ public final Set!(String) getDefinedContextIds() {
+ return getDefinedHandleObjectIds();
+ }
+
+ /**
+ * Returns the those contexts that are defined.
+ *
+ * @return The defined contexts; this value may be empty, but it is never
+ * null
.
+ * @since 3.2
+ */
+ public final Context[] getDefinedContexts() {
+ return cast(Context[]) definedHandleObjects
+ .toArray(/+new Context[definedHandleObjects.size()]+/);
+ }
+
+ /**
+ * Deactivates a context in this context manager.
+ *
+ * @param contextId
+ * The identifier of the context to deactivate; must not be
+ * null
.
+ */
+ public final void removeActiveContext(String contextId) {
+ if (!activeContextIds.contains(contextId)) {
+ return;
+ }
+
+ activeContextsChange = true;
+ if (caching) {
+ activeContextIds.remove(contextId);
+ } else {
+ auto previouslyActiveContextIds = activeContextIds.dup;
+ activeContextIds.remove(contextId);
+
+ fireContextManagerChanged(new ContextManagerEvent(this, null,
+ false, true, previouslyActiveContextIds));
+ }
+
+ if (DEBUG) {
+ Tracing.printTrace("CONTEXTS", SetToString(activeContextIds)); //$NON-NLS-1$
+ }
+ }
+ private String SetToString( Set!(String) set ){
+ String s = "[";
+ foreach( id; set ){
+ if( s.length > 1 ) s ~= ", ";
+ s ~= id;
+ }
+ s ~= "]";
+ return s;
+ }
+ /**
+ * Removes a listener from this context manager.
+ *
+ * @param listener
+ * The listener to be removed; must not be null
.
+ */
+ public final void removeContextManagerListener(
+ IContextManagerListener listener) {
+ removeListenerObject(cast(Object)listener);
+ }
+
+ /**
+ * Changes the set of active contexts for this context manager. The whole
+ * set is required so that internal consistency can be maintained and so
+ * that excessive recomputations do nothing occur.
+ *
+ * @param activeContextIds
+ * The new set of active context identifiers; may be
+ * null
.
+ */
+ public final void setActiveContextIds(Set!(String) activeContextIds) {
+ if (Util.equals(this.activeContextIds.toArray, activeContextIds.toArray)) {
+ return;
+ }
+
+ activeContextsChange = true;
+
+ Set!(String) previouslyActiveContextIds = this.activeContextIds;
+ if (activeContextIds !is null) {
+ this.activeContextIds = activeContextIds.duplicate;
+ } else {
+ this.activeContextIds = null;
+ }
+
+ if (DEBUG) {
+ Tracing.printTrace("CONTEXTS", (activeContextIds is null) ? "none" //$NON-NLS-1$ //$NON-NLS-2$
+ : SetToString(activeContextIds));
+ }
+
+ if (!caching) {
+ fireContextManagerChanged(new ContextManagerEvent(this, null,
+ false, true, previouslyActiveContextIds));
+ }
+ }
+
+ /**
+ * Set the manager to cache context id changes.
+ *
+ * @param cache
+ * true
to turn caching on, false
+ * to turn caching off and send an event if necessary.
+ * @since 3.3
+ */
+ private void setEventCaching(bool cache) {
+ if (caching is cache) {
+ return;
+ }
+ caching = cache;
+ bool fireChange = activeContextsChange;
+ Set!(String) holdOldIds = (oldIds is null? EMPTY_SET : oldIds );
+
+ if (caching) {
+ oldIds = activeContextIds.duplicate;
+ } else {
+ oldIds = null;
+ }
+ activeContextsChange = false;
+
+ if (!caching && fireChange) {
+ fireContextManagerChanged(new ContextManagerEvent(this, null,
+ false, true, holdOldIds));
+ }
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/contexts/ContextManagerEvent.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/contexts/ContextManagerEvent.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 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 null
.
+ */
+ private const Set!(String) previouslyActiveContextIds;
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param contextManager
+ * the instance of the interface that changed; must not be
+ * null
.
+ * @param contextId
+ * The context identifier that was added or removed; may be
+ * null
if the active contexts are changing.
+ * @param contextIdAdded
+ * Whether the context identifier became defined (otherwise, it
+ * became undefined).
+ * @param activeContextsChanged
+ * Whether the list of active contexts has changed.
+ * @param previouslyActiveContextIds
+ * the set of identifiers of previously active contexts. This set
+ * may be empty. If this set is not empty, it must only contain
+ * instances of String
. This set must be
+ * null
if activeContextChanged is
+ * false
and must not be null if
+ * activeContextChanged is true
.
+ */
+ public this(ContextManager contextManager,
+ String contextId, bool contextIdAdded,
+ bool activeContextsChanged,
+ Set!(String) previouslyActiveContextIds) {
+ if (contextManager is null) {
+ throw new NullPointerException();
+ }
+
+ this.contextManager = contextManager;
+ this.contextId = contextId;
+ this.previouslyActiveContextIds = previouslyActiveContextIds;
+
+ if (contextIdAdded) {
+ changedValues |= CHANGED_CONTEXT_DEFINED;
+ }
+ if (activeContextsChanged) {
+ changedValues |= CHANGED_CONTEXTS_ACTIVE;
+ }
+ }
+
+ /**
+ * Returns the context identifier that was added or removed.
+ *
+ * @return The context identifier that was added or removed. This value may
+ * be null
if no context identifier was added or
+ * removed.
+ */
+ public final String getContextId() {
+ return contextId;
+ }
+
+ /**
+ * Returns the instance of the interface that changed.
+ *
+ * @return the instance of the interface that changed. Guaranteed not to be
+ * null
.
+ */
+ public final ContextManager getContextManager() {
+ return contextManager;
+ }
+
+ /**
+ * Returns the set of identifiers to previously active contexts.
+ *
+ * @return the set of identifiers to previously active contexts. This set
+ * may be empty. If this set is not empty, it is guaranteed to only
+ * contain instances of String
. This set is
+ * guaranteed to be null
if
+ * haveActiveContextChanged() is false
and is
+ * guaranteed to not be null
if
+ * haveActiveContextsChanged() is true
.
+ */
+ public final Set!(String) getPreviouslyActiveContextIds() {
+ return previouslyActiveContextIds;
+ }
+
+ /**
+ * Returns whether the active context identifiers have changed.
+ *
+ * @return true
if the collection of active contexts changed;
+ * false
otherwise.
+ */
+ public final bool isActiveContextsChanged() {
+ return ((changedValues & CHANGED_CONTEXTS_ACTIVE) !is 0);
+ }
+
+ /**
+ * Returns whether the list of defined context identifiers has changed.
+ *
+ * @return true
if the list of context identifiers has
+ * changed; false
otherwise.
+ */
+ public final bool isContextChanged() {
+ return (contextId !is null);
+ }
+
+ /**
+ * Returns whether the context identifier became defined. Otherwise, the
+ * context identifier became undefined.
+ *
+ * @return true
if the context identifier became defined;
+ * false
if the context identifier became undefined.
+ */
+ public final bool isContextDefined() {
+ return (((changedValues & CHANGED_CONTEXT_DEFINED) !is 0) && (contextId !is null));
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/contexts/IContextListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/contexts/IContextListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 IContext
.
+ * IContext
have changed. Specific details are described in
+ * the ContextEvent
.
+ *
+ * @param contextEvent
+ * the context event. Guaranteed not to be null
.
+ */
+ void contextChanged(ContextEvent contextEvent);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/contexts/IContextManagerListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/contexts/IContextManagerListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 IContextManager
.
+ * IContextManager
have changed. Specific details are
+ * described in the ContextManagerEvent
.
+ *
+ * @param contextManagerEvent
+ * the context manager event. Guaranteed not to be
+ * null
.
+ */
+ void contextManagerChanged(ContextManagerEvent contextManagerEvent);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/AbstractOperation.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/AbstractOperation.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 true
if the history should print
+ * information to System.out
whenever notifications about
+ * changes to the history occur. This flag should be used for debug purposes
+ * only.
+ */
+ public static bool DEBUG_OPERATION_HISTORY_NOTIFICATION = false;
+
+ /**
+ * This flag can be set to true
if the history should print
+ * information to System.out
whenever an unexpected condition
+ * arises. This flag should be used for debug purposes only.
+ */
+ public static bool DEBUG_OPERATION_HISTORY_UNEXPECTED = false;
+
+ /**
+ * This flag can be set to true
if the history should print
+ * information to System.out
whenever an undo context is
+ * disposed. This flag should be used for debug purposes only.
+ */
+ public static bool DEBUG_OPERATION_HISTORY_DISPOSE = false;
+
+ /**
+ * This flag can be set to true
if the history should print
+ * information to System.out
during the open/close sequence.
+ * This flag should be used for debug purposes only.
+ */
+ public static bool DEBUG_OPERATION_HISTORY_OPENOPERATION = false;
+
+ /**
+ * This flag can be set to true
if the history should print
+ * information to System.out
whenever an operation is not
+ * approved. This flag should be used for debug purposes only.
+ */
+ public static bool DEBUG_OPERATION_HISTORY_APPROVAL = false;
+
+ static const int DEFAULT_LIMIT = 20;
+
+ /**
+ * the list of {@link IOperationApprover}s
+ */
+ ListenerList approvers;
+
+ /**
+ * a map of undo limits per context
+ */
+ private Map!(IUndoContext,Integer) limits;
+
+ /**
+ * the list of {@link IOperationHistoryListener}s
+ */
+ ListenerList listeners;
+
+ /**
+ * the list of operations available for redo, LIFO
+ */
+ private ArraySeq!(IUndoableOperation) redoList;
+
+ /**
+ * the list of operations available for undo, LIFO
+ */
+ private ArraySeq!(IUndoableOperation) undoList;
+
+ /**
+ * a lock that is used to synchronize access between the undo and redo
+ * history
+ */
+ final Object undoRedoHistoryLock;
+
+ /**
+ * An operation that is "absorbing" all other operations while it is open.
+ * When this is not null, other operations added or executed are added to
+ * this composite.
+ *
+ */
+ private ICompositeOperation openComposite = null;
+
+ /**
+ * a lock that is used to synchronize access to the open composite.
+ */
+ const Object openCompositeLock;
+
+ /**
+ * Create an instance of DefaultOperationHistory.
+ */
+ public this() {
+ openCompositeLock = new Object();
+ undoRedoHistoryLock = new Object();
+ approvers = new ListenerList(ListenerList.IDENTITY);
+ limits = new HashMap!(IUndoContext,Integer);
+ listeners = new ListenerList(ListenerList.IDENTITY);
+ redoList = new ArraySeq!(IUndoableOperation);
+ undoList = new ArraySeq!(IUndoableOperation);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.core.commands.operations.IOperationHistory#add(dwtx.core.commands.operations.IUndoableOperation)
+ */
+ public void add(IUndoableOperation operation) {
+ Assert.isNotNull( cast(Object)operation);
+
+ /*
+ * If we are in the middle of executing an open batching operation, and
+ * this is not that operation, then we need only add the context of the
+ * new operation to the batch. The operation itself is disposed since we
+ * will never undo or redo it. We consider it to be triggered by the
+ * batching operation and assume that its undo will be triggered by the
+ * batching operation undo.
+ */
+ synchronized (openCompositeLock) {
+ if (openComposite !is null && openComposite !is operation) {
+ openComposite.add(operation);
+ return;
+ }
+ }
+
+ if (checkUndoLimit(operation)) {
+ synchronized (undoRedoHistoryLock) {
+ undoList.append(operation);
+ }
+ notifyAdd(operation);
+
+ // flush redo stack for related contexts
+ IUndoContext[] contexts = operation.getContexts();
+ for (int i = 0; i < contexts.length; i++) {
+ flushRedo(contexts[i]);
+ }
+ } else {
+ // Dispose the operation since we will not have a reference to it.
+ operation.dispose();
+ }
+ }
+
+ /**
+ * null
if the affected objects cannot be determined.
+ */
+ Object[] getAffectedObjects();
+
+ /**
+ * Return a status indicating the projected outcome of undoing the receiver.
+ *
+ * This method should be used to report the possible outcome of an undo and
+ * is used when computing the validity of an undo is too expensive to
+ * perform in {@link IUndoableOperation#canUndo()}. It is not called by the
+ * operation history, but instead is used by clients (such as implementers
+ * of {@link IOperationApprover}) who wish to perform advanced validation of
+ * an operation before attempting to undo it.
+ *
+ * If the result of this method is the discovery that an operation can in
+ * fact not be undone, then the operation is expected to correctly answer
+ * false
on subsequent calls to
+ * {@link IUndoableOperation#canUndo()}.
+ *
+ * @param monitor
+ * the progress monitor (or null
) to use for
+ * reporting progress to the user while computing the validity.
+ *
+ * @return the IStatus indicating the validity of the undo. The status
+ * severity should be set to OK
if the undo can
+ * successfully be performed, and ERROR
if it
+ * cannnot. Any other status is assumed to represent an ambiguous
+ * state.
+ * @throws ExecutionException
+ * if an exception occurs while computing the validity.
+ */
+ IStatus computeUndoableStatus(IProgressMonitor monitor);
+
+ /**
+ * Return a status indicating the projected outcome of redoing the receiver.
+ *
+ * This method should be used to report the possible outcome of a redo and
+ * is used when computing the validity of a redo is too expensive to perform
+ * in {@link IUndoableOperation#canRedo()}. It is not called by the
+ * operation history, but instead is used by clients (such as implementers
+ * of {@link IOperationApprover}) who wish to perform advanced validation of
+ * an operation before attempting to redo it.
+ *
+ * If the result of this method is the discovery that an operation can in
+ * fact not be redone, then the operation is expected to correctly answer
+ * false
on subsequent calls to
+ * {@link IUndoableOperation#canRedo()}.
+ *
+ * @param monitor
+ * the progress monitor (or null
) to use for
+ * reporting progress to the user while computing the validity.
+ *
+ * @return the IStatus indicating the validity of the redo. The status
+ * severity should be set to OK
if the redo can
+ * successfully be performed, and ERROR
if it
+ * cannnot. Any other status is assumed to represent an ambiguous
+ * state.
+ * @throws ExecutionException
+ * if an exception occurs while computing the validity.
+ */
+ IStatus computeRedoableStatus(IProgressMonitor monitor);
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/IAdvancedUndoableOperation2.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/IAdvancedUndoableOperation2.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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 false
on subsequent calls to
+ * {@link IUndoableOperation#canExecute()}.
+ *
+ * @param monitor
+ * the progress monitor (or null
) to use for
+ * reporting progress to the user while computing the validity.
+ *
+ * @return the IStatus indicating the validity of the execute. The status
+ * severity should be set to OK
if the execute can
+ * successfully be performed, and ERROR
if it cannot.
+ * Any other severity is assumed to represent an ambiguous state.
+ * @throws ExecutionException
+ * if an exception occurs while computing the validity.
+ */
+ IStatus computeExecutionStatus(IProgressMonitor monitor);
+
+ /**
+ * Set a bool that instructs whether the computation of the receiver's
+ * execution, undo, or redo status should quietly compute status without
+ * consulting or prompting the user. The default value is false
.
+ * This flag should only be set to true
while the execution,
+ * undo, or redo status computations are being performed in the background,
+ * and should be restored to false
when complete.
+ * true
. This can help to prevent overzealous
+ * disposal of the operation history when an operation is in an ambiguous
+ * state. Typically, the status computation methods are invoked with this
+ * flag set to false
just before the actual execution, undo,
+ * or redo occurs, so the user can be consulted for the final outcome.
+ *
+ * @param quiet
+ * true
if it is inappropriate to consult or
+ * otherwise prompt the user while computing status, and
+ * false
if the user may be prompted.
+ *
+ * @see #computeExecutionStatus(IProgressMonitor)
+ * @see IAdvancedUndoableOperation#computeUndoableStatus(IProgressMonitor)
+ * @see IAdvancedUndoableOperation#computeRedoableStatus(IProgressMonitor)
+ */
+ public void setQuietCompute(bool quiet);
+
+ /**
+ * Return a bool that instructs whether the operation should be executed,
+ * undone, or redone in a background thread.
+ *
+ * @return true
if the operation should be run in the
+ * background, false
if it should not.
+ */
+ public bool runInBackground();
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/ICompositeOperation.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/ICompositeOperation.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 IStatus
object with
+ * severity OK
if the operation should proceed, and any other
+ * severity if it should not. When an operation is not approved, it is expected
+ * that the object not allowing the operation has already consulted the user if
+ * necessary or otherwise provided any necessary information to the user about
+ * the fact that the operation is not approved.
+ * IStatus.OK
+ * will not be approved. Implementers should not assume that the redo will
+ * be performed when the status is OK
, since other operation
+ * approvers may veto the redo.
+ *
+ * @param operation
+ * the operation to be redone
+ * @param history
+ * the history redoing the operation
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class. Even if UI
+ * information is provided, the implementation of this method
+ * must be prepared for being called from a background thread.
+ * Any UI access must be properly synchronized using the
+ * techniques specified by the client's widget library.
+ * @return the IStatus describing whether the operation is approved. The
+ * redo will not proceed if the status severity is not
+ * OK
, and the caller requesting the redo will be
+ * returned the status that caused the rejection. Any other status
+ * severities will not be interpreted by the history.
+ */
+ IStatus proceedRedoing(IUndoableOperation operation,
+ IOperationHistory history, IAdaptable info);
+
+ /**
+ * Return a status indicating whether the specified operation should be
+ * undone. Any status that does not have severity IStatus.OK
+ * will not be approved. Implementers should not assume that the undo will
+ * be performed when the status is OK
, since other operation
+ * approvers can veto the undo.
+ *
+ * @param operation
+ * the operation to be undone
+ * @param history
+ * the history undoing the operation
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class. Even if UI
+ * information is provided, the implementation of this method
+ * must be prepared for being called from a background thread.
+ * Any UI access must be properly synchronized using the
+ * techniques specified by the client's widget library.
+ * @return the IStatus describing whether the operation is approved. The
+ * undo will not proceed if the status severity is not
+ * OK
, and the caller requesting the undo will be
+ * returned the status that caused the rejection. Any other status
+ * severities will not be interpreted by the history.
+ */
+ IStatus proceedUndoing(IUndoableOperation operation,
+ IOperationHistory history, IAdaptable info);
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/IOperationApprover2.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/IOperationApprover2.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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 IStatus
object with severity
+ * OK
if the operation should proceed, and any other severity if
+ * it should not. When an operation is not approved, it is expected that the
+ * object not allowing the operation has already consulted the user if necessary
+ * or otherwise provided any necessary information to the user about the fact
+ * that the operation is not approved.
+ * IStatus.OK
+ * will not be approved. Implementers should not assume that the execution
+ * will be performed when the status is OK
, since other
+ * operation approvers may veto the execution.
+ *
+ * @param operation
+ * the operation to be executed
+ * @param history
+ * the history performing the execution of the operation
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class. Even if UI
+ * information is provided, the implementation of this method
+ * must be prepared for being called from a background thread.
+ * Any UI access must be properly synchronized using the
+ * techniques specified by the client's widget library.
+ * @return the IStatus describing whether the operation is approved. The
+ * execution will not proceed if the status severity is not
+ * OK
, and the caller requesting the execution will
+ * be returned the status that caused the rejection. Any other
+ * status severities will not be interpreted by the history.
+ */
+ IStatus proceedExecuting(IUndoableOperation operation,
+ IOperationHistory history, IAdaptable info);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/IOperationHistory.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/IOperationHistory.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,712 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 OPERATION_ADDED
).
+ * null
. If an attempt is
+ * made to register an instance which is already registered with
+ * this instance, this method has no effect.
+ *
+ * @see dwtx.core.commands.operations.IOperationApprover
+ */
+ void addOperationApprover(IOperationApprover approver);
+
+ /**
+ * null
. If an attempt is made to register
+ * an instance which is already registered with this instance,
+ * this method has no effect.
+ *
+ * @see dwtx.core.commands.operations.IOperationHistoryListener
+ * @see dwtx.core.commands.operations.OperationHistoryEvent
+ */
+ void addOperationHistoryListener(IOperationHistoryListener listener);
+
+ /**
+ * DONE
, UNDONE
, or
+ * REDONE
notification, depending on the mode. Otherwise send
+ * an OPERATION_NOT_OK
notification. Add the operation to the
+ * history if specified and send an OPERATION_ADDED
+ * notification.
+ * true
if the operation successfully completed.
+ * Listeners should be notified with DONE
,
+ * UNDONE
, or REDONE
.
+ * false
if the operation did not successfully
+ * complete. Listeners should be notified with
+ * OPERATION_NOT_OK
.
+ * @param addToHistory
+ * true
if the operation should be added to the
+ * history, false
if it should not. If the
+ * operationOK
parameter is false
,
+ * the operation will never be added to the history.
+ * @param mode
+ * the mode the operation was opened in. Can be one of
+ * EXECUTE
, UNDO
, or
+ * REDO
. This determines what notifications are
+ * sent.
+ */
+ void closeOperation(bool operationOK, bool addToHistory, int mode);
+
+ /**
+ * true
if there is a redoable operation,
+ * false
otherwise.
+ */
+
+ bool canRedo(IUndoContext context);
+
+ /**
+ * true
if there is an undoable operation,
+ * false
otherwise.
+ */
+ bool canUndo(IUndoContext context);
+
+ /**
+ * true
if the context should be flushed from the
+ * undo history, false
if it should not
+ * @param flushRedo
+ * true
if the context should be flushed from the
+ * redo history, false
if it should not.
+ * @param flushContext
+ * true
if the context is no longer in use and
+ * references to it should be flushed.
+ */
+ void dispose(IUndoContext context, bool flushUndo, bool flushRedo,
+ bool flushContext);
+
+ /**
+ * ABOUT_TO_EXECUTE
) and
+ * after (DONE
or OPERATION_NOT_OK
).
+ * OPERATION_ADDED
)
+ * will be sent.
+ * null
)
+ * during the operation.
+ *
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ *
+ * @return the IStatus indicating whether the execution succeeded.
+ *
+ * OK
+ * severity indicates that the execute operation was successful and that the
+ * operation has been added to the history. Listeners will receive
+ * notifications about the operation's success (DONE
) and
+ * about the operation being added to the history (OPERATION_ADDED
).
+ * CANCEL
severity indicates that the user cancelled the
+ * operation and that the operation was not added to the history.
+ * ERROR
severity indicates that the operation did not
+ * successfully execute and that it was not added to the history. Any other
+ * severity code is not specifically interpreted by the history, and the
+ * operation will not be added to the history. For all severities other than
+ * OK
, listeners will receive the
+ * OPERATION_NOT_OK
notification instead of the
+ * DONE
notification if the execution was approved and
+ * attempted.
+ * null
if there is no
+ * operation available. There is no guarantee that the returned
+ * operation is valid for redo.
+ */
+ IUndoableOperation getRedoOperation(IUndoContext context);
+
+ /**
+ * ABOUT_TO_EXECUTE
,
+ * ABOUT_TO_UNDO
, ABOUT_TO_REDO
).
+ * Notifications for any other execute or add while this operation is open
+ * will not occur. Instead, those operations will be added to the current
+ * operation.
+ * EXECUTE
, UNDO
, or
+ * REDO
. This determines what notifications are
+ * sent.
+ */
+ void openOperation(ICompositeOperation operation, int mode);
+
+ /**
+ * null
if there is no
+ * operation available. There is no guarantee that the available
+ * operation is valid for the undo.
+ */
+ IUndoableOperation getUndoOperation(IUndoContext context);
+
+ /**
+ * null
if no progress monitor is provided.
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ * @return the IStatus indicating whether the redo succeeded.
+ *
+ * OK
+ * severity indicates that the redo operation was successful and (since
+ * release 3.2), that the operation will be placed in the undo history.
+ * (Prior to 3.2, a successfully redone operation would not be placed on the
+ * undo history if it could not be undone. Since 3.2, this is relaxed, and
+ * all successfully redone operations are placed in the undo history.)
+ * Listeners will receive the REDONE
notification.
+ * CANCEL
, ERROR
,
+ * INFO
, etc.) are not specifically interpreted by the
+ * history. The operation will remain in the history and the returned status
+ * is simply passed back to the caller. For all severities other than
+ * OK
, listeners will receive the
+ * OPERATION_NOT_OK
notification instead of the
+ * REDONE
notification if the redo was approved and
+ * attempted.
+ * null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not null
,
+ * it should minimally contain an adapter for the
+ * dwt.widgets.Shell.class.
+ *
+ * @return the IStatus indicating whether the redo succeeded.
+ *
+ * OK
+ * severity indicates that the redo operation was successful, and (since
+ * release 3.2), that the operation will be placed in the undo history.
+ * (Prior to 3.2, a successfully redone operation would not be placed on the
+ * undo history if it could not be undone. Since 3.2, this is relaxed, and
+ * all successfully redone operations are placed in the undo history.)
+ * Listeners will receive the REDONE
notification.
+ * CANCEL
, ERROR
,
+ * INFO
, etc.) are not specifically interpreted by the
+ * history. The operation will remain in the history and the returned status
+ * is simply passed back to the caller. For all severities other than OK
,
+ * listeners will receive the OPERATION_NOT_OK
notification
+ * instead of the REDONE
notification if the redo was
+ * approved and attempted.
+ * null
. If an attempt is made to remove an
+ * instance which is not already registered with this instance,
+ * this method has no effect.
+ */
+ void removeOperationApprover(IOperationApprover approver);
+
+ /**
+ * null
. If an attempt is made to remove an
+ * instance which is not already registered with this instance,
+ * this method has no effect.
+ */
+ void removeOperationHistoryListener(IOperationHistoryListener listener);
+
+ /**
+ * null
if no progress monitor is provided.
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ *
+ * @return the IStatus indicating whether the undo succeeded.
+ *
+ * OK
+ * severity indicates that the undo operation was successful, and (since
+ * release 3.2), that the operation will be placed on the redo history.
+ * (Prior to 3.2, a successfully undone operation would not be placed on the
+ * redo history if it could not be redone. Since 3.2, this is relaxed, and
+ * all successfully undone operations are placed in the redo history.)
+ * Listeners will receive the UNDONE
notification.
+ * CANCEL
, ERROR
,
+ * INFO
, etc.) are not specifically interpreted by the
+ * history. The operation will remain in the history and the returned status
+ * is simply passed back to the caller. For all severities other than
+ * OK
, listeners will receive the
+ * OPERATION_NOT_OK
notification instead of the
+ * UNDONE
notification if the undo was approved and
+ * attempted.
+ * null
if no progress monitor is provided
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ *
+ * @return the IStatus indicating whether the undo succeeded.
+ *
+ * OK
+ * severity indicates that the undo operation was successful, and (since
+ * release 3.2), that the operation will be placed on the redo history.
+ * (Prior to 3.2, a successfully undone operation would not be placed on the
+ * redo history if it could not be redone. Since 3.2, this is relaxed, and
+ * all successfully undone operations are placed in the redo history.)
+ * Listeners will receive the UNDONE
notification.
+ * CANCEL
, ERROR
,
+ * INFO
, etc.) are not specifically interpreted by the
+ * history. The operation will remain in the history and the returned status
+ * is simply passed back to the caller. For all severities other than
+ * OK
, listeners will receive the
+ * OPERATION_NOT_OK
notification instead of the
+ * UNDONE
notification if the undo was approved and
+ * attempted.
+ * true
if the receiving context can be considered a
+ * match for the specified context, and false
if it
+ * cannot.
+ */
+ public bool matches(IUndoContext context);
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/IUndoableOperation.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/IUndoableOperation.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 true
if the operation can be executed;
+ * false
otherwise.
+ */
+ bool canExecute();
+
+ /**
+ * true
if the operation can be redone;
+ * false
otherwise.
+ */
+ bool canRedo();
+
+ /**
+ * true
if the operation can be undone;
+ * false
otherwise.
+ */
+ bool canUndo();
+
+ /**
+ * Dispose of the operation. This method is used when the operation is no
+ * longer kept in the history. Implementers of this method typically
+ * unregister any listeners.
+ *
+ */
+ void dispose();
+
+ /**
+ * Execute the operation. This method should only be called the first time
+ * that an operation is executed.
+ *
+ * @param monitor
+ * the progress monitor (or null
) to use for
+ * reporting progress to the user.
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ *
+ * @return the IStatus of the execution. The status severity should be set
+ * to OK
if the operation was successful, and
+ * ERROR
if it was not. Any other status is assumed
+ * to represent an incompletion of the execution.
+ * @throws ExecutionException
+ * if an exception occurred during execution.
+ */
+ IStatus execute(IProgressMonitor monitor, IAdaptable info);
+
+ /**
+ * true
if the context is present, false
+ * if it is not.
+ */
+ bool hasContext(IUndoContext context);
+
+ /**
+ * Redo the operation. This method should only be called after an operation
+ * has been undone.
+ *
+ * @param monitor
+ * the progress monitor (or null
) to use for
+ * reporting progress to the user.
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ * @return the IStatus of the redo. The status severity should be set to
+ * OK
if the redo was successful, and
+ * ERROR
if it was not. Any other status is assumed
+ * to represent an incompletion of the redo.
+ * @throws ExecutionException
+ * if an exception occurred during redo.
+ */
+
+ IStatus redo(IProgressMonitor monitor, IAdaptable info);
+
+ /**
+ * Remove the specified context from the operation. This method has no
+ * effect if the context is not equal to another context in the context
+ * list. Note that determining whether a context is present when removing it
+ * is based on equality, not whether the context matches ({@link
+ * IUndoContext#matches(IUndoContext)}) another context.
+ *
+ * @param context
+ * the context to be removed
+ */
+ void removeContext(IUndoContext context);
+
+ /**
+ * Undo the operation. This method should only be called after an operation
+ * has been executed.
+ *
+ * @param monitor
+ * the progress monitor (or null
) to use for
+ * reporting progress to the user.
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ * @return the IStatus of the undo. The status severity should be set to
+ * OK
if the redo was successful, and
+ * ERROR
if it was not. Any other status is assumed
+ * to represent an incompletion of the undo.
+ * @throws ExecutionException
+ * if an exception occurred during undo.
+ */
+ IStatus undo(IProgressMonitor monitor, IAdaptable info);
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/LinearUndoEnforcer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/LinearUndoEnforcer.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ *
+ * @return the IStatus describing whether the redo violation is allowed. The
+ * redo will not proceed if the status severity is not
+ * OK
, and the caller requesting the redo will be
+ * returned the status that caused the rejection. Specific status
+ * severities will not be interpreted by the history.
+ */
+
+ protected abstract IStatus allowLinearRedoViolation(
+ IUndoableOperation operation, IUndoContext context,
+ IOperationHistory history, IAdaptable info);
+
+ /**
+ * Return a status indicating whether a linear undo violation is allowable.
+ * A linear undo violation is defined as a request to undo a particular
+ * operation even if it is not the most recently added operation to the undo
+ * history.
+ *
+ * @param operation
+ * the operation for which a linear undo violation has been
+ * detected.
+ * @param context
+ * the undo context in which the linear undo violation exists
+ * @param history
+ * the operation history containing the operation
+ * @param info
+ * the IAdaptable (or null
) provided by the
+ * caller in order to supply UI information for prompting the
+ * user if necessary. When this parameter is not
+ * null
, it should minimally contain an adapter
+ * for the dwt.widgets.Shell.class.
+ *
+ * @return the IStatus describing whether the undo violation is allowed. The
+ * undo will not proceed if the status severity is not
+ * OK
, and the caller requesting the undo will be
+ * returned the status that caused the rejection. Specific status
+ * severities will not be interpreted by the history.
+ */
+ protected abstract IStatus allowLinearUndoViolation(
+ IUndoableOperation operation, IUndoContext context,
+ IOperationHistory history, IAdaptable info);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.core.commands.operations.IOperationApprover#proceedRedoing(dwtx.core.commands.operations.IUndoableOperation,
+ * dwtx.core.commands.operations.IOperationHistory,
+ * dwtx.core.runtime.IAdaptable)
+ */
+ public final IStatus proceedRedoing(IUndoableOperation operation,
+ IOperationHistory history, IAdaptable info) {
+ IUndoContext[] contexts = operation.getContexts();
+ for (int i = 0; i < contexts.length; i++) {
+ IUndoContext context = contexts[i];
+ if (history.getRedoOperation(context) !is operation) {
+ IStatus status = allowLinearRedoViolation(operation, context,
+ history, info);
+ if (!status.isOK()) {
+ return status;
+ }
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.core.commands.operations.IOperationApprover#proceedUndoing(dwtx.core.commands.operations.IUndoableOperation,
+ * dwtx.core.commands.operations.IOperationHistory,
+ * dwtx.core.runtime.IAdaptable)
+ */
+
+ public final IStatus proceedUndoing(IUndoableOperation operation,
+ IOperationHistory history, IAdaptable info) {
+ IUndoContext[] contexts = operation.getContexts();
+ for (int i = 0; i < contexts.length; i++) {
+ IUndoContext context = contexts[i];
+ if (history.getUndoOperation(context) !is operation) {
+ IStatus status = allowLinearUndoViolation(operation, context,
+ history, info);
+ if (!status.isOK()) {
+ return status;
+ }
+ }
+ }
+ return Status.OK_STATUS;
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/ObjectUndoContext.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/ObjectUndoContext.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 null
if not
+ * applicable
+ */
+ public this(int severity, String pluginId, int code, String message, Exception exception) {
+ super(severity, pluginId, code, message, exception);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/operations/TriggeredOperations.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/operations/TriggeredOperations.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,465 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 true
if the receiving context can be considered a
+ * match for the specified context, and false
if it
+ * cannot.
+ */
+ public bool matches(IUndoContext context) {
+ return context is this;
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/commands/util/Tracing.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/commands/util/Tracing.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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
+ * BINDINGS >> There are 4 deletion markers
+ *
+ *
+ * @param component
+ * The component for which this tracing applies; may be
+ * null
+ * @param message
+ * The message to print to standard out; may be null
.
+ */
+ public static final void printTrace(String component,
+ String message) {
+ StringBuffer buffer = new StringBuffer();
+ if (component.length !is 0) {
+ buffer.append(component);
+ }
+ if ((component.length !is 0) && (message.length !is 0)) {
+ buffer.append(SEPARATOR);
+ }
+ if (message.length !is 0) {
+ buffer.append(message);
+ }
+ Trace.formatln( "{}", buffer.toString());
+ }
+
+ /**
+ * This class is not intended to be instantiated.
+ */
+ private this() {
+ // Do nothing.
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/internal/commands/operations/GlobalUndoContext.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/internal/commands/operations/GlobalUndoContext.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 null
.
+ *
+ * @param object
+ * The object for which the type should be checked.
+ * @param c
+ * The class that the object must be; fails if the class is
+ * null
.
+ * @param allowNull
+ * Whether the object being null
will not cause a
+ * failure.
+ */
+ public static final void assertInstance(final Object object, final Class c,
+ final bool allowNull) {
+ if (object is null && allowNull) {
+ return;
+ }
+
+ if (object is null || c is null) {
+ throw new NullPointerException();
+ } else if (!c.isInstance(object)) {
+ throw new IllegalArgumentException();
+ }
+ }
+++/
+ /**
+ * Compares two bool values. false
is considered to be
+ * less than true
.
+ *
+ * @param left
+ * The left value to compare.
+ * @param right
+ * The right value to compare.
+ * @return -1
if left
is false
+ * and right
is true
;0
+ * if they are equal; 1
if left
is
+ * true
and right
is
+ * false
+ */
+ public static final int compare(bool left, bool right) {
+ return left is false ? (right is true ? -1 : 0) : (right is true ? 0
+ : 1);
+ }
+
+ /**
+ * Compares two comparable objects, but with protection against
+ * null
.
+ *
+ * @param left
+ * The left value to compare; may be null
.
+ * @param right
+ * The right value to compare; may be null
.
+ * @return -1
if left
is null
+ * and right
is not null
;
+ * 0
if they are both null
;
+ * 1
if left
is not null
+ * and right
is null
. Otherwise, the
+ * result of left.compareTo(right)
.
+ */
+ public static final int compare(Comparable left,
+ Comparable right) {
+ if (left is null && right is null) {
+ return 0;
+ } else if (left is null) {
+ return -1;
+ } else if (right is null) {
+ return 1;
+ } else {
+ return left.compareTo( cast(Object)right);
+ }
+ }
+
+ /**
+ * Compares two integer values. This method fails if the distance between
+ * left
and right
is greater than
+ * Integer.MAX_VALUE
.
+ *
+ * @param left
+ * The left value to compare.
+ * @param right
+ * The right value to compare.
+ * @return left - right
+ */
+ public static final int compare(int left, int right) {
+ return left - right;
+ }
+
+ /**
+ * Compares two objects that are not otherwise comparable. If neither object
+ * is null
, then the string representation of each object is
+ * used.
+ *
+ * @param left
+ * The left value to compare. The string representation of this
+ * value must not be null
.
+ * @param right
+ * The right value to compare. The string representation of this
+ * value must not be null
.
+ * @return -1
if left
is null
+ * and right
is not null
;
+ * 0
if they are both null
;
+ * 1
if left
is not null
+ * and right
is null
. Otherwise, the
+ * result of
+ * left.toString().compareTo(right.toString())
.
+ */
+ public static final int compare(Object left, Object right) {
+ if (left is null && right is null) {
+ return 0;
+ } else if (left is null) {
+ return -1;
+ } else if (right is null) {
+ return 1;
+ } else {
+ return left.toString() < (right.toString());
+ }
+ }
+ public static final int compare(Object[] left, Object[] right) {
+ if (left.length !is right.length ) {
+ return left.length < right.length;
+ }
+ for( int i = 0; i < left.length; i++ ){
+ int res = left[i].opCmp(right[i]);
+ if( res !is 0 ){
+ return res;
+ }
+ }
+ return 0;
+ }
+ public static final int compare(String left, String right) {
+ return left < right;
+ }
+
+ /**
+ * Decides whether two booleans are equal.
+ *
+ * @param left
+ * The first bool to compare; may be null
.
+ * @param right
+ * The second bool to compare; may be null
.
+ * @return true
if the booleans are equal; false
+ * otherwise.
+ */
+ public static bool equals(bool left, bool right) {
+ return left is right;
+ }
+
+ /**
+ * Decides whether two objects are equal -- defending against
+ * null
.
+ *
+ * @param left
+ * The first object to compare; may be null
.
+ * @param right
+ * The second object to compare; may be null
.
+ * @return true
if the objects are equals; false
+ * otherwise.
+ */
+ public static bool equals(Object left, Object right) {
+ return left is null ? right is null : ((right !is null) && (left
+ .opEquals(right)) !is 0 );
+ }
+ public static bool equals(String left, String right) {
+ return left == right;
+ }
+ public static bool equals(String[] left, String[] right) {
+ if( left.length !is right.length ){
+ return false;
+ }
+ for( int i = 0; i < left.length; i++ ){
+ if( !equals( left[i], right[i] )){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Tests whether two arrays of objects are equal to each other. The arrays
+ * must not be null
, but their elements may be
+ * null
.
+ *
+ * @param leftArray
+ * The left array to compare; may be null
, and
+ * may be empty and may contain null
elements.
+ * @param rightArray
+ * The right array to compare; may be null
, and
+ * may be empty and may contain null
elements.
+ * @return true
if the arrays are equal length and the
+ * elements at the same position are equal; false
+ * otherwise.
+ */
+ public static bool equals(Object[] leftArray,
+ Object[] rightArray) {
+ if (leftArray is null) {
+ return (rightArray is null);
+ } else if (rightArray is null) {
+ return false;
+ }
+
+ if (leftArray.length !is rightArray.length) {
+ return false;
+ }
+
+ for (int i = 0; i < leftArray.length; i++) {
+ Object left = leftArray[i];
+ Object right = rightArray[i];
+ bool equal = (left is null) ? (right is null) : (left
+ .opEquals(right) !is 0);
+ if (!equal) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Computes the hash code for an integer.
+ *
+ * @param i
+ * The integer for which a hash code should be computed.
+ * @return i
.
+ */
+ public static final hash_t toHash(int i) {
+ return i;
+ }
+
+ /**
+ * Computes the hash code for an object, but with defense against
+ * null
.
+ *
+ * @param object
+ * The object for which a hash code is needed; may be
+ * null
.
+ * @return The hash code for object
; or 0
if
+ * object
is null
.
+ */
+ public static final hash_t toHash( Object object) {
+ return object !is null ? object.toHash() : 0;
+ }
+ public static final hash_t toHash( char[] str) {
+ return str !is null ? dwt.dwthelper.utils.toHash( str ) : 0;
+ }
+/++
+
+ /**
+ * Makes a type-safe copy of the given map. This method should be used when
+ * a map is crossing an API boundary (i.e., from a hostile plug-in into
+ * internal code, or vice versa).
+ *
+ * @param map
+ * The map which should be copied; must not be null
.
+ * @param keyClass
+ * The class that all the keys must be; must not be
+ * null
.
+ * @param valueClass
+ * The class that all the values must be; must not be
+ * null
.
+ * @param allowNullKeys
+ * Whether null
keys should be allowed.
+ * @param allowNullValues
+ * Whether null
values should be allowed.
+ * @return A copy of the map; may be empty, but never null
.
+ */
+ public static final Map safeCopy(final Map map, final Class keyClass,
+ final Class valueClass, final bool allowNullKeys,
+ final bool allowNullValues) {
+ if (map is null || keyClass is null || valueClass is null) {
+ throw new NullPointerException();
+ }
+
+ final Map copy = Collections.unmodifiableMap(new HashMap(map));
+ final Iterator iterator = copy.entrySet().iterator();
+
+ while (iterator.hasNext()) {
+ final Map.Entry entry = (Map.Entry) iterator.next();
+ assertInstance(entry.getKey(), keyClass, allowNullKeys);
+ assertInstance(entry.getValue(), valueClass, allowNullValues);
+ }
+
+ return map;
+ }
+
+ /**
+ * Makes a type-safe copy of the given set. This method should be used when
+ * a set is crossing an API boundary (i.e., from a hostile plug-in into
+ * internal code, or vice versa).
+ *
+ * @param set
+ * The set which should be copied; must not be null
.
+ * @param c
+ * The class that all the values must be; must not be
+ * null
.
+ * @return A copy of the set; may be empty, but never null
.
+ * None of its element will be null
.
+ */
+ public static final Set safeCopy(final Set set, final Class c) {
+ return safeCopy(set, c, false);
+ }
+
+ /**
+ * Makes a type-safe copy of the given set. This method should be used when
+ * a set is crossing an API boundary (i.e., from a hostile plug-in into
+ * internal code, or vice versa).
+ *
+ * @param set
+ * The set which should be copied; must not be null
.
+ * @param c
+ * The class that all the values must be; must not be
+ * null
.
+ * @param allowNullElements
+ * Whether null values should be allowed.
+ * @return A copy of the set; may be empty, but never null
.
+ */
+ public static final Set safeCopy(final Set set, final Class c,
+ final bool allowNullElements) {
+ if (set is null || c is null) {
+ throw new NullPointerException();
+ }
+
+ final Set copy = Collections.unmodifiableSet(new HashSet(set));
+ final Iterator iterator = copy.iterator();
+
+ while (iterator.hasNext()) {
+ assertInstance(iterator.next(), c, allowNullElements);
+ }
+
+ return set;
+ }
+++/
+ /**
+ * The utility class is meant to just provide static members.
+ */
+ private this() {
+ // Should not be called.
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/internal/runtime/IRuntimeConstants.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/internal/runtime/IRuntimeConstants.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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 dwtx.core.runtime
")
+ * of the Core Runtime (pseudo-) plug-in.
+ */
+ public static const String PI_RUNTIME = "dwtx.core.runtime"; //$NON-NLS-1$
+
+ /**
+ * Name of this bundle.
+ */
+ public static const String PI_COMMON = "dwtx.equinox.common"; //$NON-NLS-1$
+
+ /**
+ * Status code constant (value 2) indicating an error occurred while running a plug-in.
+ */
+ public static const int PLUGIN_ERROR = 2;
+
+ /**
+ * Status code constant (value 5) indicating the platform could not write
+ * some of its metadata.
+ */
+ public static const int FAILED_WRITE_METADATA = 5;
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/internal/runtime/LocalizationUtils.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/internal/runtime/LocalizationUtils.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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 Assert
is useful for for embedding runtime sanity checks
+ * in code. The predicate methods all test a condition and throw some
+ * type of unchecked exception if the condition does not hold.
+ * true
, an IllegalArgumentException
+ * is thrown.
+ *
+ * @param expression the outcode of the check
+ * @return true
if the check passes (does not return
+ * if the check fails)
+ * @exception IllegalArgumentException if the legality test failed
+ */
+ public static bool isLegal(bool expression) {
+ return isLegal(expression, ""); //$NON-NLS-1$
+ }
+
+ /** Asserts that an argument is legal. If the given bool is
+ * not true
, an IllegalArgumentException
+ * is thrown.
+ * The given message is included in that exception, to aid debugging.
+ *
+ * @param expression the outcode of the check
+ * @param message the message to include in the exception
+ * @return true
if the check passes (does not return
+ * if the check fails)
+ * @exception IllegalArgumentException if the legality test failed
+ */
+ public static bool isLegal(bool expression, String message) {
+ if (!expression)
+ throw new IllegalArgumentException(message);
+ return expression;
+ }
+
+ /** Asserts that the given object is not null
. If this
+ * is not the case, some kind of unchecked exception is thrown.
+ *
+ * @param object the value to test
+ */
+ public static void isNotNull(Object object) {
+ isNotNull(object, ""); //$NON-NLS-1$
+ }
+
+ /** Asserts that the given object is not null
. If this
+ * is not the case, some kind of unchecked exception is thrown.
+ * The given message is included in that exception, to aid debugging.
+ *
+ * @param object the value to test
+ * @param message the message to include in the exception
+ */
+ public static void isNotNull(Object object, String message) {
+ if (object is null)
+ throw new AssertionFailedException("null argument:" ~ message); //$NON-NLS-1$
+ }
+
+ /** Asserts that the given bool is true
. If this
+ * is not the case, some kind of unchecked exception is thrown.
+ *
+ * @param expression the outcode of the check
+ * @return true
if the check passes (does not return
+ * if the check fails)
+ */
+ public static bool isTrue(bool expression) {
+ return isTrue(expression, ""); //$NON-NLS-1$
+ }
+
+ /** Asserts that the given bool is true
. If this
+ * is not the case, some kind of unchecked exception is thrown.
+ * The given message is included in that exception, to aid debugging.
+ *
+ * @param expression the outcode of the check
+ * @param message the message to include in the exception
+ * @return true
if the check passes (does not return
+ * if the check fails)
+ */
+ public static bool isTrue(bool expression, String message) {
+ if (!expression)
+ throw new AssertionFailedException("assertion failed: " ~ message); //$NON-NLS-1$
+ return expression;
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/AssertionFailedException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/AssertionFailedException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 AssertionFailedException
is a runtime exception thrown
+ * by some of the methods in Assert
.
+ *
+ * IAdaptable a = [some adaptable];
+ * IFoo x = (IFoo)a.getAdapter(IFoo.class);
+ * if (x !is null)
+ * [do IFoo things with x]
+ *
+ * PlatformObject
.
+ * null
if
+ * no such object can be found.
+ *
+ * @param adapter the adapter class to look up
+ * @return a object castable to the given class,
+ * or null
if this object does not
+ * have an adapter for the given class
+ */
+ public Object getAdapter(ClassInfo adapter);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/IAdapterFactory.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/IAdapterFactory.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 IAdaptable
+ * interface. Adapter factories are registered with an
+ * adapter manager.
+ * null
if
+ * no such object can be found.
+ *
+ * @param adaptableObject the adaptable object being queried
+ * (usually an instance of IAdaptable
)
+ * @param adapterType the type of adapter to look up
+ * @return a object castable to the given adapter type,
+ * or null
if this adapter factory
+ * does not have an adapter of the given type for the
+ * given object
+ */
+ public Object getAdapter(Object adaptableObject, ClassInfo adapterType);
+
+ /**
+ * Returns the collection of adapter types handled by this
+ * factory.
+ * getAdapter
requests.
+ * IAdaptable
+ * interface) funnel IAdaptable.getAdapter
invocations to their
+ * adapter manager's IAdapterManger.getAdapter
method. The
+ * adapter manager then forwards this request unmodified to the IAdapterFactory.getAdapter
+ * method on one of the registered adapter factories.
+ * registerAdapters
+ * method. Alternatively, they can be registered declaratively using the
+ * dwtx.core.runtime.adapters
extension point. Factories registered
+ * with this extension point will not be able to provide adapters until their
+ * corresponding plugin has been activated.
+ * com.example.acme.Sticky
on resources in the workspace.
+ *
+ * IAdapterFactory pr = new IAdapterFactory() {
+ * public Class[] getAdapterList() {
+ * return new Class[] { com.example.acme.Sticky.class };
+ * }
+ * public Object getAdapter(Object adaptableObject, Class adapterType) {
+ * IResource res = (IResource) adaptableObject;
+ * QualifiedName key = new QualifiedName("com.example.acme", "sticky-note");
+ * try {
+ * com.example.acme.Sticky v = (com.example.acme.Sticky) res.getSessionProperty(key);
+ * if (v is null) {
+ * v = new com.example.acme.Sticky();
+ * res.setSessionProperty(key, v);
+ * }
+ * } catch (CoreException e) {
+ * // unable to access session property - ignore
+ * }
+ * return v;
+ * }
+ * }
+ * Platform.getAdapterManager().registerAdapters(pr, IResource.class);
+ *
+ *
+ * adaptableClass
+ * via this manager. Converting means that subsequent calls to getAdapter()
+ * or loadAdapter()
could result in an adapted object.
+ * getAdapter
with the same type as an argument
+ * will return a non-null result. If the factory's plug-in has not yet been
+ * loaded, or if the factory itself returns null
, then
+ * getAdapter
will still return null
.
+ * adaptableClass
via this manager. An empty array
+ * is returned if there are none.
+ * @since 3.1
+ */
+ public String[] computeAdapterTypes(ClassInfo adaptableClass);
+
+ /**
+ * Returns the class search order for a given class. The search order from a
+ * class with the definition
+ * class X extends Y implements A, B
+ * is as follows:
+ *
+ *
+ *
+ * @param clazz the class for which to return the class order.
+ * @return the class search order for the given class. The returned
+ * search order will minimally contain the target class.
+ * @since 3.1
+ */
+ public ClassInfo[] computeClassOrder(ClassInfo clazz);
+
+ /**
+ * Returns an object which is an instance of the given class associated
+ * with the given object. Returns Object
+ * getInterfaces
(in the example, A and its
+ * superinterfaces then B and its superinterfaces) null
if no such object can
+ * be found.
+ * null
.
+ *
+ * @param adaptable the adaptable object being queried (usually an instance
+ * of IAdaptable
)
+ * @param adapterType the type of adapter to look up
+ * @return an object castable to the given adapter type, or null
+ * if the given adaptable object does not have an available adapter of the
+ * given type
+ */
+ public Object getAdapter(Object adaptable, ClassInfo adapterType);
+
+ /**
+ * Returns an object which is an instance of the given class name associated
+ * with the given object. Returns null
if no such object can
+ * be found.
+ * null
.
+ * If activation of the plug-in providing the factory is required, use the
+ * loadAdapter
method instead.
+ *
+ * @param adaptable the adaptable object being queried (usually an instance
+ * of IAdaptable
)
+ * @param adapterTypeName the fully qualified name of the type of adapter to look up
+ * @return an object castable to the given adapter type, or null
+ * if the given adaptable object does not have an available adapter of the
+ * given type
+ * @since 3.0
+ */
+ public Object getAdapter(Object adaptable, String adapterTypeName);
+
+ /**
+ * Returns whether there is an adapter factory registered that may be able
+ * to convert adaptable
to an object of type adapterTypeName
.
+ * true
does not guarantee that
+ * a subsequent call to getAdapter
with the same arguments
+ * will return a non-null result. If the factory's plug-in has not yet been
+ * loaded, or if the factory itself returns null
, then
+ * getAdapter
will still return null
.
+ *
+ * @param adaptable the adaptable object being queried (usually an instance
+ * of IAdaptable
)
+ * @param adapterTypeName the fully qualified class name of an adapter to
+ * look up
+ * @return true
if there is an adapter factory that claims
+ * it can convert adaptable
to an object of type adapterType
,
+ * and false
otherwise.
+ * @since 3.0
+ */
+ public bool hasAdapter(Object adaptable, String adapterTypeName);
+
+ /**
+ * Returns a status of an adapter factory registered that may be able
+ * to convert adaptable
to an object of type adapterTypeName
.
+ *
+ *
IAdaptable
)
+ * @param adapterTypeName the fully qualified class name of an adapter to
+ * look up
+ * @return a status of the adapter
+ * @since dwtx.equinox.common 3.3
+ */
+ public int queryAdapter(Object adaptable, String adapterTypeName);
+
+ /**
+ * Returns an object that is an instance of the given class name associated
+ * with the given object. Returns null
if no such object can
+ * be found.
+ * getAdapter
methods, this method
+ * will cause the plug-in that contributes the adapter factory to be loaded
+ * if necessary. As such, this method should be used judiciously, in order
+ * to avoid unnecessary plug-in activations. Most clients should avoid
+ * activation by using getAdapter
instead.
+ *
+ * @param adaptable the adaptable object being queried (usually an instance
+ * of IAdaptable
)
+ * @param adapterTypeName the fully qualified name of the type of adapter to look up
+ * @return an object castable to the given adapter type, or null
+ * if the given adaptable object does not have an available adapter of the
+ * given type
+ * @since 3.0
+ */
+ public Object loadAdapter(Object adaptable, String adapterTypeName);
+
+ /**
+ * Registers the given adapter factory as extending objects of the given
+ * type.
+ * unregisterAdapters(IAdapterFactory,Class)
+ * on all classes against which it had been explicitly registered. Does
+ * nothing if the given factory is not currently registered.
+ *
+ * @param factory the adapter factory to remove
+ * @see #registerAdapters(IAdapterFactory, Class)
+ */
+ public void unregisterAdapters(IAdapterFactory factory);
+
+ /**
+ * Removes the given adapter factory from the list of factories registered
+ * as extending the given class. Does nothing if the given factory and type
+ * combination is not registered.
+ *
+ * @param factory the adapter factory to remove
+ * @param adaptable one of the types against which the given factory is
+ * registered
+ * @see #registerAdapters(IAdapterFactory, Class)
+ */
+ public void unregisterAdapters(IAdapterFactory factory, ClassInfo adaptable);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/ILogListener.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/ILogListener.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 null
for a device id.
+ * //Server/Volume/My/Path
. When a new path
+ * is constructed all double-slashes are removed except those
+ * appearing at the beginning of the path.
+ * true
if the paths are equivalent,
+ * and false
if they are not
+ */
+ public int opEquals(Object obj);
+
+ /**
+ * Returns the device id for this path, or null
if this
+ * path has no device id. Note that the result will end in ':'.
+ *
+ * @return the device id, or null
+ * @see #setDevice(String)
+ */
+ public String getDevice();
+
+ /**
+ * Returns the file extension portion of this path,
+ * or null
if there is none.
+ * null
+ */
+ public String getFileExtension();
+
+ /**
+ * Returns whether this path has a trailing separator.
+ * true
if this path has a trailing
+ * separator, and false
otherwise
+ * @see #addTrailingSeparator()
+ * @see #removeTrailingSeparator()
+ */
+ public bool hasTrailingSeparator();
+
+ /**
+ * Returns whether this path is an absolute path (ignoring
+ * any device id).
+ * /
or C:/
,
+ * is considered absolute. UNC paths are always absolute.
+ * true
if this path is an absolute path,
+ * and false
otherwise
+ */
+ public bool isAbsolute();
+
+ /**
+ * Returns whether this path has no segments and is not
+ * a root path.
+ *
+ * @return true
if this path is empty,
+ * and false
otherwise
+ */
+ public bool isEmpty();
+
+ /**
+ * Returns whether this path is a prefix of the given path.
+ * To be a prefix, this path's segments must
+ * appear in the argument path in the same order,
+ * and their device ids must match.
+ * true
if this path is a prefix of the given path,
+ * and false
otherwise
+ */
+ public bool isPrefixOf(IPath anotherPath);
+
+ /**
+ * Returns whether this path is a root path.
+ * /
or C:/
.
+ * The separator is considered a leading separator, not a trailing one.
+ * true
if this path is a root path,
+ * and false
otherwise
+ */
+ public bool isRoot();
+
+ /**
+ * Returns a bool value indicating whether or not this path
+ * is considered to be in UNC form. Return false if this path
+ * has a device set or if the first 2 characters of the path string
+ * are not Path.SEPARATOR
.
+ *
+ * @return bool indicating if this path is UNC
+ */
+ public bool isUNC();
+
+ /**
+ * Returns whether the given string is syntactically correct as
+ * a path. The device id is the prefix up to and including the device
+ * separator for the local file system; the path proper is everything to
+ * the right of it, or the entire string if there is no device separator.
+ * When the platform location is a file system with no meaningful device
+ * separator, the entire string is treated as the path proper.
+ * The device id is not checked for validity; the path proper is correct
+ * if each of the segments in its canonicalized form is valid.
+ *
+ * @param path the path to check
+ * @return true
if the given string is a valid path,
+ * and false
otherwise
+ * @see #isValidSegment(String)
+ */
+ public bool isValidPath(String path);
+
+ /**
+ * Returns whether the given string is valid as a segment in
+ * a path. The rules for valid segments are as follows:
+ *
+ *
+ *
+ * @param segment the path segment to check
+ * @return true
if the given path segment is valid,
+ * and false
otherwise
+ */
+ public bool isValidSegment(String segment);
+
+ /**
+ * Returns the last segment of this path, or
+ * null
if it does not have any segments.
+ *
+ * @return the last segment of this path, or null
+ */
+ public String lastSegment();
+
+ /**
+ * Returns an absolute path with the segments and device id of this path.
+ * Absolute paths start with a path separator. If this path is absolute,
+ * it is simply returned.
+ *
+ * @return the new path
+ */
+ public IPath makeAbsolute();
+
+ /**
+ * Returns a relative path with the segments and device id of this path.
+ * Absolute paths start with a path separator and relative paths do not.
+ * If this path is relative, it is simply returned.
+ *
+ * @return the new path
+ */
+ public IPath makeRelative();
+
+ /**
+ * Return a new path which is the equivalent of this path converted to UNC
+ * form (if the given bool is true) or this path not as a UNC path (if the given
+ * bool is false). If UNC, the returned path will not have a device and the
+ * first 2 characters of the path string will be Path.SEPARATOR
. If not UNC, the
+ * first 2 characters of the returned path string will not be Path.SEPARATOR
.
+ *
+ * @param toUNC true if converting to UNC, false otherwise
+ * @return the new path, either in UNC form or not depending on the bool parameter
+ */
+ public IPath makeUNC(bool toUNC);
+
+ /**
+ * Returns a count of the number of segments which match in
+ * this path and the given path (device ids are ignored),
+ * comparing in increasing segment number order.
+ *
+ * @param anotherPath the other path
+ * @return the number of matching segments
+ */
+ public int matchingFirstSegments(IPath anotherPath);
+
+ /**
+ * Returns a new path which is the same as this path but with
+ * the file extension removed. If this path does not have an
+ * extension, this path is returned.
+ * null
if the path does not have such a segment.
+ *
+ * @param index the 0-based segment index
+ * @return the specified segment, or null
+ */
+ public String segment(int index);
+
+ /**
+ * Returns the number of segments in this path.
+ * null
.
+ * null
+ * @return a new path
+ * @see #getDevice()
+ */
+ public IPath setDevice(String device);
+
+ /**
+ * Returns a java.io.File
corresponding to this path.
+ *
+ * @return the file corresponding to this path
+ */
+ public tango.io.FilePath.FilePath toFile();
+
+ /**
+ * Returns a string representation of this path which uses the
+ * platform-dependent path separator defined by java.io.File
.
+ * This method is like toString()
except that the
+ * latter always uses the same separator (/
) regardless of platform.
+ * java.io.File(String)
.
+ * Path#fromPortableString(String)
+ * constructor to produce the exact same path on any platform.
+ * Path#fromPortableString(String)
.
+ *
+ * "/foo/bar.txt"
+ * "bar.txt"
+ * "/foo/"
+ * "foo/"
+ * ""
+ * "/"
+ * "C:/foo/bar.txt"
+ * "C:bar.txt"
+ * "C:/foo/"
+ * "C:foo/"
+ * "C:"
+ * "C:/"
+ *
+ * This string is suitable for passing to Path(String)
.
+ * IProgressMonitor
interface is implemented
+ * by objects that monitor the progress of an activity; the methods
+ * in this interface are invoked by code that performs the activity.
+ * beginTask(String, int)
+ *
notification is reported, followed by any number and mixture of
+ * progress reports (worked()
) and subtask notifications
+ * (subTask(String)
). When the task is eventually completed, a
+ * done()
notification is reported. After the done()
+ * notification, the progress monitor cannot be reused; i.e.,
+ * beginTask(String, int)
cannot be called again after the call to
+ * done()
.
+ * setCanceled
method. Operations taking a progress
+ * monitor are expected to poll the monitor (using isCanceled
)
+ * periodically and abort at their earliest convenience. Operation can however
+ * choose to ignore cancelation requests.
+ * UNKNOWN
+ * the implementation is free to indicate progress in a way which
+ * doesn't require the total number of work units in advance.
+ */
+ public void beginTask(String name, int totalWork);
+
+ /**
+ * Notifies that the work is done; that is, either the main task is completed
+ * or the user canceled it. This method may be called more than once
+ * (implementations should be prepared to handle this case).
+ */
+ public void done();
+
+ /**
+ * Internal method to handle scaling correctly. This method
+ * must not be called by a client. Clients should
+ * always use the method worked(int).
+ *
+ * @param work the amount of work done
+ */
+ public void internalWorked(double work);
+
+ /**
+ * Returns whether cancelation of current operation has been requested.
+ * Long-running operations should poll to see if cancelation
+ * has been requested.
+ *
+ * @return true
if cancellation has been requested,
+ * and false
otherwise
+ * @see #setCanceled(bool)
+ */
+ public bool isCanceled();
+
+ /**
+ * Sets the cancel state to the given value.
+ *
+ * @param value true
indicates that cancelation has
+ * been requested (but not necessarily acknowledged);
+ * false
clears this flag
+ * @see #isCanceled()
+ */
+ public void setCanceled(bool value);
+
+ /**
+ * Sets the task name to the given value. This method is used to
+ * restore the task label after a nested operation was executed.
+ * Normally there is no need for clients to call this method.
+ *
+ * @param name the name (or description) of the main task
+ * @see #beginTask(java.lang.String, int)
+ */
+ public void setTaskName(String name);
+
+ /**
+ * Notifies that a subtask of the main task is beginning.
+ * Subtasks are optional; the main task might not have subtasks.
+ *
+ * @param name the name (or description) of the subtask
+ */
+ public void subTask(String name);
+
+ /**
+ * Notifies that a given number of work unit of the main task
+ * has been completed. Note that this amount represents an
+ * installment, as opposed to a cumulative amount of work done
+ * to date.
+ *
+ * @param work a non-negative number of work units just completed
+ */
+ public void worked(int work);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/IProgressMonitorWithBlocking.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/IProgressMonitorWithBlocking.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2006 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 - Initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit setBlocked
whenever it knows that it
+ * must wait for a lock that is currently held by another thread. The operation
+ * should continue to check for and respond to cancelation requests while
+ * blocked. When the operation is no longer blocked, it must call clearBlocked
+ * to clear the blocked state.
+ * setBlocked
, it must
+ * eventually call clearBlocked
before the operation
+ * completes.
+ * IJobStatus
indicating the job that is currently blocking
+ * the caller. If this blocking job is not known, this method will return a plain
+ * informational IStatus
object.
+ * null
if this
+ * information is not available.
+ * @see #clearBlocked()
+ * @see dwtx.core.runtime.jobs.IJobStatus
+ */
+ public void setBlocked(IStatus reason);
+
+ /**
+ * Clears the blocked state of the running operation. If a running
+ * operation ever calls setBlocked
, it must eventually call
+ * clearBlocked
before the operation completes.
+ *
+ * @see #setBlocked(IStatus)
+ */
+ public void clearBlocked();
+
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/ISafeRunnable.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/ISafeRunnable.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 run
+ * method. The processing done here should be specific to the
+ * particular usecase for this runnable. Generalized exception
+ * processing (e.g., logging in the platform's log) is done by the
+ * Platform's run mechanism.
+ *
+ * @param exception an exception which occurred during processing
+ * the body of this runnable (i.e., in run()
)
+ * @see Platform#run(ISafeRunnable)
+ */
+ public void handleException(Exception exception);
+
+ /**
+ * Runs this runnable. Any exceptions thrown from this method will
+ * be passed to this runnable's handleException
+ * method.
+ *
+ * @exception Exception if a problem occurred while running this method.
+ * The exception will be processed by handleException
+ * @see Platform#run(ISafeRunnable)
+ */
+ public void run();
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/IStatus.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/IStatus.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 CoreException
s carry a status object to indicate
+ * what went wrong. Status objects are also returned by methods needing
+ * to provide details of failures (e.g., validation methods).
+ *
+ *
+ * Some status objects, known as multi-statuses, have other status objects
+ * as children.
+ *
+ * The class Status
is the standard public implementation
+ * of status objects; the subclass MultiStatus
is the
+ * implements multi-status objects.
+ *
+ * This interface can be used without OSGi running. + *
+ * @see MultiStatus + * @see Status + */ +public interface IStatus { + + /** Status severity constant (value 0) indicating this status represents the nominal case. + * This constant is also used as the status code representing the nominal case. + * @see #getSeverity() + * @see #isOK() + */ + public static const int OK = 0; + + /** Status type severity (bit mask, value 1) indicating this status is informational only. + * @see #getSeverity() + * @see #matches(int) + */ + public static const int INFO = 0x01; + + /** Status type severity (bit mask, value 2) indicating this status represents a warning. + * @see #getSeverity() + * @see #matches(int) + */ + public static const int WARNING = 0x02; + + /** Status type severity (bit mask, value 4) indicating this status represents an error. + * @see #getSeverity() + * @see #matches(int) + */ + public static const int ERROR = 0x04; + + /** Status type severity (bit mask, value 8) indicating this status represents a + * cancelation + * @see #getSeverity() + * @see #matches(int) + * @since 3.0 + */ + public static const int CANCEL = 0x08; + + /** + * Returns a list of status object immediately contained in this + * multi-status, or an empty list if this is not a multi-status. + * + * @return an array of status objects + * @see #isMultiStatus() + */ + public IStatus[] getChildren(); + + /** + * Returns the plug-in-specific status code describing the outcome. + * + * @return plug-in-specific status code + */ + public int getCode(); + + /** + * Returns the relevant low-level exception, ornull
if none.
+ * For example, when an operation fails because of a network communications
+ * failure, this might return the java.io.IOException
+ * describing the exact nature of that failure.
+ *
+ * @return the relevant low-level exception, or null
if none
+ */
+ public Exception getException();
+
+ /**
+ * Returns the message describing the outcome.
+ * The message is localized to the current locale.
+ *
+ * @return a localized message
+ */
+ public String getMessage();
+
+ /**
+ * Returns the unique identifier of the plug-in associated with this status
+ * (this is the plug-in that defines the meaning of the status code).
+ *
+ * @return the unique identifier of the relevant plug-in
+ */
+ public String getPlugin();
+
+ /**
+ * Returns the severity. The severities are as follows (in
+ * descending order):
+ * CANCEL
- cancelation occurredERROR
- a serious error (most severe)WARNING
- a warning (less severe)INFO
- an informational ("fyi") message (least severe)OK
- everything is just fine
+ * The severity of a multi-status is defined to be the maximum
+ * severity of any of its children, or OK
if it has
+ * no children.
+ *
OK
, ERROR
,
+ * INFO
, WARNING
, or CANCEL
+ * @see #matches(int)
+ */
+ public int getSeverity();
+
+ /**
+ * Returns whether this status is a multi-status.
+ * A multi-status describes the outcome of an operation
+ * involving multiple operands.
+ *
+ * The severity of a multi-status is derived from the severities
+ * of its children; a multi-status with no children is
+ * OK
by definition.
+ * A multi-status carries a plug-in identifier, a status code,
+ * a message, and an optional exception. Clients may treat
+ * multi-status objects in a multi-status unaware way.
+ *
true
for a multi-status,
+ * false
otherwise
+ * @see #getChildren()
+ */
+ public bool isMultiStatus();
+
+ /**
+ * Returns whether this status indicates everything is okay
+ * (neither info, warning, nor error).
+ *
+ * @return true
if this status has severity
+ * OK
, and false
otherwise
+ */
+ public bool isOK();
+
+ /**
+ * Returns whether the severity of this status matches the given
+ * severity mask. Note that a status with severity OK
+ * will never match; use isOK
instead to detect
+ * a status with a severity of OK
.
+ *
+ * @param severityMask a mask formed by bitwise or'ing severity mask
+ * constants (ERROR
, WARNING
,
+ * INFO
, CANCEL
)
+ * @return true
if there is at least one match,
+ * false
if there are no matches
+ * @see #getSeverity()
+ * @see #CANCEL
+ * @see #ERROR
+ * @see #WARNING
+ * @see #INFO
+ */
+ public bool matches(int severityMask);
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/ListenerList.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/ListenerList.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ * Use the getListeners
method when notifying listeners. The recommended
+ * code sequence for notifying all registered listeners of say,
+ * FooListener.eventHappened
, is:
+ *
+ *
+ * Object[] listeners = myListenerList.getListeners(); + * for (int i = 0; i < listeners.length; ++i) { + * ((FooListener) listeners[i]).eventHappened(event); + * } + *+ * + *
+ * This class can be used without OSGi running. + *
+ * @since dwtx.equinox.common 3.2 + */ +public class ListenerList { + + /** + * The empty array singleton instance. + */ + private static const Object[] EmptyArray; + + /** + * Mode constant (value 0) indicating that listeners should be considered + * the same if they are equal. + */ + public static const int EQUALITY = 0; + + /** + * Mode constant (value 1) indicating that listeners should be considered + * the same if they are identical. + */ + public static const int IDENTITY = 1; + + /** + * Indicates the comparison mode used to determine if two + * listeners are equivalent + */ + private final bool identity; + + /** + * The list of listeners. Initially empty but initialized + * to an array of size capacity the first time a listener is added. + * Maintains invariant: listeners !is null + */ + private Object[] listeners; + + /** + * Creates a listener list in which listeners are compared using equality. + */ + public this() { + this(EQUALITY); + } + + /** + * Creates a listener list using the provided comparison mode. + * + * @param mode The mode used to determine if listeners are the same. + */ + public this(int mode) { + if (mode !is EQUALITY && mode !is IDENTITY) + throw new IllegalArgumentException( null ); + this.identity = mode is IDENTITY; + } + + /** + * Adds a listener to this list. This method has no effect if the same + * listener is already registered. + * + * @param listener the non-null
listener to add
+ */
+ public synchronized void add(Object listener) {
+ // This method is synchronized to protect against multiple threads adding
+ // or removing listeners concurrently. This does not block concurrent readers.
+ if (listener is null)
+ throw new IllegalArgumentException( null );
+ // check for duplicates
+ final int oldSize = listeners.length;
+ for (int i = 0; i < oldSize; ++i) {
+ Object listener2 = listeners[i];
+ if (identity ? listener is listener2 : listener.opEquals(listener2))
+ return;
+ }
+ // Thread safety: create new array to avoid affecting concurrent readers
+ Object[] newListeners = new Object[oldSize + 1];
+ System.arraycopy(listeners, 0, newListeners, 0, oldSize);
+ newListeners[oldSize] = listener;
+ //atomic assignment
+ this.listeners = newListeners;
+ }
+
+ /**
+ * Returns an array containing all the registered listeners.
+ * The resulting array is unaffected by subsequent adds or removes.
+ * If there are no listeners registered, the result is an empty array.
+ * Use this method when notifying listeners, so that any modifications
+ * to the listener list during the notification will have no effect on
+ * the notification itself.
+ *
+ * Note: Callers of this method must not modify the returned array.
+ *
+ * @return the list of registered listeners
+ */
+ public Object[] getListeners() {
+ return listeners;
+ }
+
+ /**
+ * Returns whether this listener list is empty.
+ *
+ * @return
+ * This class can be used without OSGi running.
+ *
+ * This implementation supports cancelation. The default
+ * implementations of the other methods do nothing.
+ *
+ * This class can be used without OSGi running.
+ *
+ * This class can be used without OSGi running.
+ *
+ * This class is not intended to be subclassed by clients but
+ * may be instantiated.
+ *
+ * This class can be used without OSGi running.
+ *
+ * This class is not intended to be subclassed by clients but
+ * may be instantiated.
+ *
+ * In its canonical form, a path does not have any
+ * "." segments, and parent references ("..") are collapsed
+ * where possible.
+ *
+ * This class can be used without OSGi running.
+ *
+ * Clients may subclass.
+ *
+ * This class can be used without OSGi running.
+ *
+ * This class is not intended to be subclassed by clients.
+ *
+ * Clients may instantiate.
+ *
+ * Qualified names are equal if and only if they have the same
+ * qualified parts and local parts.
+ * Qualified names are not equal to objects other than qualified names.
+ *
+ * This class can be used without OSGi running.
+ *
+ * This class can be used without OSGi running.
+ * A progress monitor that uses a given amount of work ticks from a parent monitor. This is intended as a
+ * safer, easier-to-use alternative to SubProgressMonitor. The main benefits of SubMonitor over
+ * SubProgressMonitor are: USAGE: When implementing a method that accepts an IProgressMonitor: DEFAULT BEHAVIOR: When writing JavaDoc for a method that accepts an IProgressMonitor, you should assume the
+ * following default behavior unless the method's JavaDoc says otherwise: BEST PRACTISES: We recommend that newly-written methods follow the given contract: If you wish to follow these conventions, you may copy and paste the following text into your method's JavaDoc: Example: Recommended usage This example demonstrates how the recommended usage of It is never necessary to call done() on a monitor obtained from Example: Default usage You will often need to implement a method that does not explicitly stipulate that calling done() is the responsibility
+ * of the caller. In this case, you should use the following pattern: Example: Branches This example demonstrates how to smoothly report progress in situations where some of the work is optional. Please beware of the following anti-pattern: Example: Loops This example demonstrates how to report progress in a loop. Example: Infinite progress This example demonstrates how to report logarithmic progress in situations where the number of ticks
+ * cannot be easily computed in advance.
+ * This class can be used without OSGi running.
+ * Converts an unknown (possibly null) IProgressMonitor into a SubMonitor. It is
+ * not necessary to call done() on the result, but the caller is responsible for calling
+ * done() on the argument. Calls beginTask on the argument. This method should generally be called at the beginning of a method that accepts
+ * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor. Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
+ * with the given number of ticks. It is not necessary to call done() on the result,
+ * but the caller is responsible for calling done() on the argument. Calls beginTask
+ * on the argument. This method should generally be called at the beginning of a method that accepts
+ * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor. Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
+ * with the given number of ticks. It is not necessary to call done() on the result,
+ * but the caller is responsible for calling done() on the argument. Calls beginTask
+ * on the argument. This method should generally be called at the beginning of a method that accepts
+ * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor. Sets the work remaining for this SubMonitor instance. This is the total number
+ * of ticks that may be reported by all subsequent calls to worked(int), newChild(int), etc.
+ * This may be called many times for the same SubMonitor instance. When this method
+ * is called, the remaining space on the progress monitor is redistributed into the given
+ * number of ticks. It doesn't matter how much progress has already been reported with this SubMonitor
+ * instance. If you call setWorkRemaining(100), you will be able to report 100 more ticks of
+ * work before the progress meter reaches 100%. This method is equivalent calling setWorkRemaining(...) on the reciever. Unless
+ * the SUPPRESS_BEGINTASK flag is set, this will also be equivalent to calling
+ * setTaskName(...) on the parent. Creates a sub progress monitor that will consume the given number of ticks from the
+ * receiver. It is not necessary to call Each SubMonitor only has one active child at a time. Each time newChild() is called, the
+ * result becomes the new active child and any unused progress from the previously-active child is
+ * consumed. This is property makes it unnecessary to call done() on a SubMonitor instance, since child
+ * monitors are automatically cleaned up the next time the parent is touched. Creates a sub progress monitor that will consume the given number of ticks from the
+ * receiver. It is not necessary to call Each SubMonitor only has one active child at a time. Each time newChild() is called, the
+ * result becomes the new active child and any unused progress from the previously-active child is
+ * consumed. This is property makes it unnecessary to call done() on a SubMonitor instance, since child
+ * monitors are automatically cleaned up the next time the parent is touched.
+ * This class can be used without OSGi running.
+ *
+ * This class may be instantiated or subclassed by clients.
+ * true
if there are no registered listeners, and
+ * false
otherwise
+ */
+ public bool isEmpty() {
+ return listeners.length is 0;
+ }
+
+ /**
+ * Removes a listener from this list. Has no effect if the same
+ * listener was not already registered.
+ *
+ * @param listener the non-null
listener to remove
+ */
+ public synchronized void remove(Object listener) {
+ // This method is synchronized to protect against multiple threads adding
+ // or removing listeners concurrently. This does not block concurrent readers.
+ if (listener is null)
+ throw new IllegalArgumentException( null );
+ int oldSize = listeners.length;
+ for (int i = 0; i < oldSize; ++i) {
+ Object listener2 = listeners[i];
+ if (identity ? listener is listener2 : listener.opEquals(listener2)) {
+ if (oldSize is 1) {
+ listeners = EmptyArray;
+ } else {
+ // Thread safety: create new array to avoid affecting concurrent readers
+ Object[] newListeners = new Object[oldSize - 1];
+ System.arraycopy(listeners, 0, newListeners, 0, i);
+ System.arraycopy(listeners, i + 1, newListeners, i, oldSize - i - 1);
+ //atomic assignment to field
+ this.listeners = newListeners;
+ }
+ return;
+ }
+ }
+ }
+
+ /**
+ * Returns the number of registered listeners.
+ *
+ * @return the number of registered listeners
+ */
+ public int size() {
+ return listeners.length;
+ }
+
+ /**
+ * Removes all listeners from this list.
+ */
+ public synchronized void clear() {
+ listeners = EmptyArray;
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/MultiStatus.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/MultiStatus.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 null
if not
+ * applicable
+ */
+ public this(String pluginId, int code, IStatus[] newChildren, String message, Exception exception) {
+ this(pluginId, code, message, exception);
+ Assert.isLegal(newChildren !is null);
+ int maxSeverity = getSeverity();
+ for (int i = 0; i < newChildren.length; i++) {
+ Assert.isLegal(newChildren[i] !is null);
+ int severity = newChildren[i].getSeverity();
+ if (severity > maxSeverity)
+ maxSeverity = severity;
+ }
+ this.children = new IStatus[newChildren.length];
+ setSeverity(maxSeverity);
+ SimpleType!(IStatus).arraycopy(newChildren, 0, this.children, 0, newChildren.length);
+ }
+
+ /**
+ * Creates and returns a new multi-status object with no children.
+ *
+ * @param pluginId the unique identifier of the relevant plug-in
+ * @param code the plug-in-specific status code
+ * @param message a human-readable message, localized to the
+ * current locale
+ * @param exception a low-level exception, or null
if not
+ * applicable
+ */
+ public this(String pluginId, int code, String message, Exception exception) {
+ super(OK, pluginId, code, message, exception);
+ children = new IStatus[0];
+ }
+
+ /**
+ * Adds the given status to this multi-status.
+ *
+ * @param status the new child status
+ */
+ public void add(IStatus status) {
+ Assert.isLegal(status !is null);
+ IStatus[] result = new IStatus[children.length + 1];
+ SimpleType!(IStatus).arraycopy(children, 0, result, 0, children.length);
+ result[result.length - 1] = status;
+ children = result;
+ int newSev = status.getSeverity();
+ if (newSev > getSeverity()) {
+ setSeverity(newSev);
+ }
+ }
+
+ /**
+ * Adds all of the children of the given status to this multi-status.
+ * Does nothing if the given status has no children (which includes
+ * the case where it is not a multi-status).
+ *
+ * @param status the status whose children are to be added to this one
+ */
+ public void addAll(IStatus status) {
+ Assert.isLegal(status !is null);
+ IStatus[] statuses = status.getChildren();
+ for (int i = 0; i < statuses.length; i++) {
+ add(statuses[i]);
+ }
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public IStatus[] getChildren() {
+ return children;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public bool isMultiStatus() {
+ return true;
+ }
+
+ /**
+ * Merges the given status into this multi-status.
+ * Equivalent to add(status)
if the
+ * given status is not a multi-status.
+ * Equivalent to addAll(status)
if the
+ * given status is a multi-status.
+ *
+ * @param status the status to merge into this one
+ * @see #add(IStatus)
+ * @see #addAll(IStatus)
+ */
+ public void merge(IStatus status) {
+ Assert.isLegal(status !is null);
+ if (!status.isMultiStatus()) {
+ add(status);
+ } else {
+ addAll(status);
+ }
+ }
+
+ /**
+ * Returns a string representation of the status, suitable
+ * for debugging purposes only.
+ */
+ public String toString() {
+ tango.text.Text.Text!(char) buf = new tango.text.Text.Text!(char);
+ buf.append(super.toString());
+ buf.append(" children=["); //$NON-NLS-1$
+ for (int i = 0; i < children.length; i++) {
+ if (i !is 0) {
+ buf.append(" "); //$NON-NLS-1$
+ }
+ buf.append( (cast(Object)children[i]).toString());
+ }
+ buf.append("]"); //$NON-NLS-1$
+ return buf.toString();
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/NullProgressMonitor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/NullProgressMonitor.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 setCanceled
.
+ * Subclasses which override this method should
+ * override setCanceled
as well.
+ *
+ * @see IProgressMonitor#isCanceled()
+ * @see IProgressMonitor#setCanceled(bool)
+ */
+ public bool isCanceled() {
+ return cancelled;
+ }
+
+ /**
+ * This implementation sets the value of an internal state variable.
+ * Subclasses which override this method should override
+ * isCanceled
as well.
+ *
+ * @see IProgressMonitor#isCanceled()
+ * @see IProgressMonitor#setCanceled(bool)
+ */
+ public void setCanceled(bool cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ /**
+ * This implementation does nothing.
+ * Subclasses may override this method to do something
+ * with the name of the task.
+ *
+ * @see IProgressMonitor#setTaskName(String)
+ */
+ public void setTaskName(String name) {
+ // do nothing
+ }
+
+ /**
+ * This implementation does nothing.
+ * Subclasses may override this method to do interesting
+ * processing when a subtask begins.
+ *
+ * @see IProgressMonitor#subTask(String)
+ */
+ public void subTask(String name) {
+ // do nothing
+ }
+
+ /**
+ * This implementation does nothing.
+ * Subclasses may override this method to do interesting
+ * processing when some work has been completed.
+ *
+ * @see IProgressMonitor#worked(int)
+ */
+ public void worked(int work) {
+ // do nothing
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/OperationCanceledException.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/OperationCanceledException.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 IPath
interface.
+ * Paths are always maintained in canonicalized form. That is, parent
+ * references (i.e., ../../
) and duplicate separators are
+ * resolved. For example,
+ * new Path("/a/b").append("../foo/bar")
+ * will yield the path
+ * /a/foo/bar
+ * "/"
). */
+ private static const String ROOT_STRING = "/"; //$NON-NLS-1$
+
+ /** Constant value containing the root path with no device. */
+ public static const Path ROOT;
+
+ /** Constant value indicating if the current platform is Windows */
+ version(Windows){
+ private static const bool WINDOWS = true;
+ }
+ else {
+ private static const bool WINDOWS = false;
+ }
+
+ static this(){
+ EMPTY = new Path(EMPTY_STRING);
+ ROOT = new Path(ROOT_STRING);
+ }
+
+ /** The device id string. May be null if there is no device. */
+ private String device = null;
+
+ //Private implementation note: the segments and separators
+ //arrays are never modified, so that they can be shared between
+ //path instances
+
+ /** The path segments */
+ private String[] segments_;
+
+ /** flags indicating separators (has leading, is UNC, has trailing) */
+ private int separators;
+
+ /**
+ * Constructs a new path from the given string path.
+ * The string path must represent a valid file system path
+ * on the local file system.
+ * The path is canonicalized and double slashes are removed
+ * except at the beginning. (to handle UNC paths). All forward
+ * slashes ('/') are treated as segment delimiters, and any
+ * segment and device delimiters for the local file system are
+ * also respected.
+ *
+ * @param pathString the portable string path
+ * @see IPath#toPortableString()
+ * @since 3.1
+ */
+ public static IPath fromOSString(String pathString) {
+ return new Path(pathString);
+ }
+
+ /**
+ * Constructs a new path from the given path string.
+ * The path string must have been produced by a previous
+ * call to IPath.toPortableString
.
+ *
+ * @param pathString the portable path string
+ * @see IPath#toPortableString()
+ * @since 3.1
+ */
+ public static IPath fromPortableString(String pathString) {
+ int firstMatch = pathString.indexOf(DEVICE_SEPARATOR) +1;
+ //no extra work required if no device characters
+ if (firstMatch <= 0)
+ return (new Path()).initialize(null, pathString);
+ //if we find a single colon, then the path has a device
+ String devicePart = null;
+ int pathLength = pathString.length;
+ if (firstMatch is pathLength || pathString.charAt(firstMatch) !is DEVICE_SEPARATOR) {
+ devicePart = pathString.substring(0, firstMatch);
+ pathString = pathString.substring(firstMatch, pathLength);
+ }
+ //optimize for no colon literals
+ if (pathString.indexOf(DEVICE_SEPARATOR) is -1)
+ return (new Path()).initialize(devicePart, pathString);
+ //contract colon literals
+ char[] chars = pathString/+.toCharArray()+/;
+ int readOffset = 0, writeOffset = 0, length = chars.length;
+ while (readOffset < length) {
+ if (chars[readOffset] is DEVICE_SEPARATOR)
+ if (++readOffset >= length)
+ break;
+ chars[writeOffset++] = chars[readOffset++];
+ }
+ return (new Path()).initialize(devicePart, chars[ 0 .. writeOffset] );
+ }
+
+ /* (Intentionally not included in javadoc)
+ * Private constructor.
+ */
+ private this() {
+ // not allowed
+ }
+
+ /**
+ * Constructs a new path from the given string path.
+ * The string path must represent a valid file system path
+ * on the local file system.
+ * The path is canonicalized and double slashes are removed
+ * except at the beginning. (to handle UNC paths). All forward
+ * slashes ('/') are treated as segment delimiters, and any
+ * segment and device delimiters for the local file system are
+ * also respected (such as colon (':') and backslash ('\') on some file systems).
+ *
+ * @param fullPath the string path
+ * @see #isValidPath(String)
+ */
+ public this(String fullPath) {
+ String devicePart = null;
+ if (WINDOWS) {
+ //convert backslash to forward slash
+ fullPath = fullPath.indexOf('\\') is -1 ? fullPath : fullPath.replace('\\', SEPARATOR);
+ //extract device
+ int i = fullPath.indexOf(DEVICE_SEPARATOR);
+ if (i !is -1) {
+ //remove leading slash from device part to handle output of URL.getFile()
+ int start = fullPath.charAt(0) is SEPARATOR ? 1 : 0;
+ devicePart = fullPath.substring(start, i + 1);
+ fullPath = fullPath.substring(i + 1, fullPath.length);
+ }
+ }
+ initialize(devicePart, fullPath);
+ }
+
+ /**
+ * Constructs a new path from the given device id and string path.
+ * The given string path must be valid.
+ * The path is canonicalized and double slashes are removed except
+ * at the beginning (to handle UNC paths). All forward
+ * slashes ('/') are treated as segment delimiters, and any
+ * segment delimiters for the local file system are
+ * also respected (such as backslash ('\') on some file systems).
+ *
+ * @param device the device id
+ * @param path the string path
+ * @see #isValidPath(String)
+ * @see #setDevice(String)
+ */
+ public this(String device, String path) {
+ if (WINDOWS) {
+ //convert backslash to forward slash
+ path = path.indexOf('\\') is -1 ? path : path.replace('\\', SEPARATOR);
+ }
+ initialize(device, path);
+ }
+
+ /* (Intentionally not included in javadoc)
+ * Private constructor.
+ */
+ private this(String device, String[] segments_, int _separators) {
+ // no segment validations are done for performance reasons
+ this.segments_ = segments_;
+ this.device = device;
+ //hash code is cached in all but the bottom three bits of the separators field
+ this.separators = (computeHashCode() << 3) | (_separators & ALL_SEPARATORS);
+ }
+
+ /* (Intentionally not included in javadoc)
+ * @see IPath#addFileExtension
+ */
+ public IPath addFileExtension(String extension) {
+ if (isRoot() || isEmpty() || hasTrailingSeparator())
+ return this;
+ int len = segments_.length;
+ String[] newSegments = new String[len];
+ System.arraycopy(segments_, 0, newSegments, 0, len - 1);
+ newSegments[len - 1] = segments_[len - 1] ~ '.' ~ extension;
+ return new Path(device, newSegments, separators);
+ }
+
+ /* (Intentionally not included in javadoc)
+ * @see IPath#addTrailingSeparator
+ */
+ public IPath addTrailingSeparator() {
+ if (hasTrailingSeparator() || isRoot()) {
+ return this;
+ }
+ //XXX workaround, see 1GIGQ9V
+ if (isEmpty()) {
+ return new Path(device, segments_, HAS_LEADING);
+ }
+ return new Path(device, segments_, separators | HAS_TRAILING);
+ }
+
+ /* (Intentionally not included in javadoc)
+ * @see IPath#append(IPath)
+ */
+ public IPath append(IPath tail) {
+ //optimize some easy cases
+ if (tail is null || tail.segmentCount() is 0)
+ return this;
+ //these call chains look expensive, but in most cases they are no-ops
+ if (this.isEmpty())
+ return tail.setDevice(device).makeRelative().makeUNC(isUNC());
+ if (this.isRoot())
+ return tail.setDevice(device).makeAbsolute().makeUNC(isUNC());
+
+ //concatenate the two segment arrays
+ int myLen = segments_.length;
+ int tailLen = tail.segmentCount();
+ String[] newSegments = new String[myLen + tailLen];
+ System.arraycopy(segments_, 0, newSegments, 0, myLen);
+ for (int i = 0; i < tailLen; i++) {
+ newSegments[myLen + i] = tail.segment(i);
+ }
+ //use my leading separators and the tail's trailing separator
+ Path result = new Path(device, newSegments, (separators & (HAS_LEADING | IS_UNC)) | (tail.hasTrailingSeparator() ? HAS_TRAILING : 0));
+ String tailFirstSegment = newSegments[myLen];
+ if (tailFirstSegment.equals("..") || tailFirstSegment.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$
+ result.canonicalize();
+ }
+ return result;
+ }
+
+ /* (Intentionally not included in javadoc)
+ * @see IPath#append(java.lang.String)
+ */
+ public IPath append(String tail) {
+ //optimize addition of a single segment
+ if (tail.indexOf(SEPARATOR) is -1 && tail.indexOf("\\") is -1 && tail.indexOf(DEVICE_SEPARATOR) is -1) { //$NON-NLS-1$
+ int tailLength = tail.length;
+ if (tailLength < 3) {
+ //some special cases
+ if (tailLength is 0 || ".".equals(tail)) { //$NON-NLS-1$
+ return this;
+ }
+ if ("..".equals(tail)) //$NON-NLS-1$
+ return removeLastSegments(1);
+ }
+ //just add the segment
+ int myLen = segments_.length;
+ String[] newSegments = new String[myLen + 1];
+ System.arraycopy(segments_, 0, newSegments, 0, myLen);
+ newSegments[myLen] = tail;
+ return new Path(device, newSegments, separators & ~HAS_TRAILING);
+ }
+ //go with easy implementation
+ return append(new Path(tail));
+ }
+
+ /**
+ * Destructively converts this path to its canonical form.
+ * IProgressMonitor
+ * and IProgressMonitorWithBlocking
methods to the wrapped progress monitor.
+ * IProgressMonitor
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitor#beginTask(String, int)
+ */
+ public void beginTask(String name, int totalWork) {
+ progressMonitor.beginTask(name, totalWork);
+ }
+
+ /**
+ * This implementation of a IProgressMonitorWithBlocking
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitorWithBlocking#clearBlocked()
+ * @since 3.0
+ */
+ public void clearBlocked() {
+ if ( auto mon = cast(IProgressMonitorWithBlocking)progressMonitor )
+ mon.clearBlocked();
+ }
+
+ /**
+ * This implementation of a IProgressMonitor
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitor#done()
+ */
+ public void done() {
+ progressMonitor.done();
+ }
+
+ /**
+ * Returns the wrapped progress monitor.
+ *
+ * @return the wrapped progress monitor
+ */
+ public IProgressMonitor getWrappedProgressMonitor() {
+ return progressMonitor;
+ }
+
+ /**
+ * This implementation of a IProgressMonitor
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitor#internalWorked(double)
+ */
+ public void internalWorked(double work) {
+ progressMonitor.internalWorked(work);
+ }
+
+ /**
+ * This implementation of a IProgressMonitor
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitor#isCanceled()
+ */
+ public bool isCanceled() {
+ return progressMonitor.isCanceled();
+ }
+
+ /**
+ * This implementation of a IProgressMonitorWithBlocking
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitorWithBlocking#setBlocked(IStatus)
+ * @since 3.0
+ */
+ public void setBlocked(IStatus reason) {
+ if ( auto mon = cast(IProgressMonitorWithBlocking)progressMonitor)
+ mon.setBlocked(reason);
+ }
+
+ /**
+ * This implementation of a IProgressMonitor
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitor#setCanceled(bool)
+ */
+ public void setCanceled(bool b) {
+ progressMonitor.setCanceled(b);
+ }
+
+ /**
+ * This implementation of a IProgressMonitor
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitor#setTaskName(String)
+ */
+ public void setTaskName(String name) {
+ progressMonitor.setTaskName(name);
+ }
+
+ /**
+ * This implementation of a IProgressMonitor
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitor#subTask(String)
+ */
+ public void subTask(String name) {
+ progressMonitor.subTask(name);
+ }
+
+ /**
+ * This implementation of a IProgressMonitor
+ * method forwards to the wrapped progress monitor.
+ * Clients may override this method to do additional
+ * processing.
+ *
+ * @see IProgressMonitor#worked(int)
+ */
+ public void worked(int work) {
+ progressMonitor.worked(work);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/QualifiedName.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/QualifiedName.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 null
if
+ * the default name space is being used. The empty string is not
+ * a valid local name.
+ * null
). */
+ /*package*/
+ String qualifier = null;
+
+ /** Local name part. */
+ /*package*/
+ String localName = null;
+
+ /**
+ * Creates and returns a new qualified name with the given qualifier
+ * and local name. The local name must not be the empty string.
+ * The qualifier may be null
.
+ * null
+ * @param localName the local name string
+ */
+ public this(String qualifier, String localName) {
+ Assert.isLegal(localName !is null && localName.length !is 0);
+ this.qualifier = qualifier;
+ this.localName = localName;
+ }
+
+ /**
+ * Returns whether this qualified name is equivalent to the given object.
+ * true
if these are equivalent qualified
+ * names, and false
otherwise
+ */
+ public override int opEquals(Object obj) {
+ if (obj is this) {
+ return true;
+ }
+ if (!(cast(QualifiedName)obj )) {
+ return false;
+ }
+ QualifiedName qName = cast(QualifiedName) obj;
+ /* There may or may not be a qualifier */
+ if (qualifier is null && qName.getQualifier() !is null) {
+ return false;
+ }
+ if (qualifier !is null && !qualifier.equals(qName.getQualifier())) {
+ return false;
+ }
+ return localName.equals(qName.getLocalName());
+ }
+
+ /**
+ * Returns the local part of this name.
+ *
+ * @return the local name string
+ */
+ public String getLocalName() {
+ return localName;
+ }
+
+ /**
+ * Returns the qualifier part for this qualified name, or null
+ * if none.
+ *
+ * @return the qualifier string, or null
+ */
+ public String getQualifier() {
+ return qualifier;
+ }
+
+ /* (Intentionally omitted from javadoc)
+ * Implements the method Object.hashCode
.
+ *
+ * Returns the hash code for this qualified name.
+ */
+ public override hash_t toHash() {
+ return (qualifier is null ? 0 : .toHash(qualifier)) + .toHash(localName);
+ }
+
+ /**
+ * Converts this qualified name into a string, suitable for
+ * debug purposes only.
+ */
+ public override String toString() {
+ return (getQualifier() is null ? "" : getQualifier() ~ ':') ~ getLocalName(); //$NON-NLS-1$
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/SafeRunner.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/SafeRunner.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 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
+ *
+ */
+ private int severity = OK;
+
+ /** Unique identifier of plug-in.
+ */
+ private String pluginId;
+
+ /** Plug-in-specific status code.
+ */
+ private int code;
+
+ /** Message, localized to the current locale.
+ */
+ private String message;
+
+ /** Wrapped exception, or CANCEL
ERROR
WARNING
INFO
OK
(0)null
if none.
+ */
+ private Exception exception = null;
+
+ /** Constant to avoid generating garbage.
+ */
+ private static const IStatus[] theEmptyStatusArray = null;
+
+ /**
+ * Creates a new status object. The created status has no children.
+ *
+ * @param severity the severity; one of OK
, ERROR
,
+ * INFO
, WARNING
, or CANCEL
+ * @param pluginId the unique identifier of the relevant plug-in
+ * @param code the plug-in-specific status code, or OK
+ * @param message a human-readable message, localized to the
+ * current locale
+ * @param exception a low-level exception, or null
if not
+ * applicable
+ */
+ public this(int severity, String pluginId, int code, String message, Exception exception) {
+ setSeverity(severity);
+ setPlugin(pluginId);
+ setCode(code);
+ setMessage(message);
+ setException(exception);
+ }
+
+ /**
+ * Simplified constructor of a new status object; assumes that code is OK
.
+ * The created status has no children.
+ *
+ * @param severity the severity; one of OK
, ERROR
,
+ * INFO
, WARNING
, or CANCEL
+ * @param pluginId the unique identifier of the relevant plug-in
+ * @param message a human-readable message, localized to the
+ * current locale
+ * @param exception a low-level exception, or null
if not
+ * applicable
+ *
+ * @since dwtx.equinox.common 3.3
+ */
+ public this(int severity, String pluginId, String message, Exception exception) {
+ setSeverity(severity);
+ setPlugin(pluginId);
+ setMessage(message);
+ setException(exception);
+ setCode(OK);
+ }
+
+ /**
+ * Simplified constructor of a new status object; assumes that code is OK
and
+ * exception is null
. The created status has no children.
+ *
+ * @param severity the severity; one of OK
, ERROR
,
+ * INFO
, WARNING
, or CANCEL
+ * @param pluginId the unique identifier of the relevant plug-in
+ * @param message a human-readable message, localized to the
+ * current locale
+ *
+ * @since dwtx.equinox.common 3.3
+ */
+ public this(int severity, String pluginId, String message) {
+ setSeverity(severity);
+ setPlugin(pluginId);
+ setMessage(message);
+ setCode(OK);
+ setException(null);
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public IStatus[] getChildren() {
+ return theEmptyStatusArray;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public int getCode() {
+ return code;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public Exception getException() {
+ return exception;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public String getPlugin() {
+ return pluginId;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public int getSeverity() {
+ return severity;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public bool isMultiStatus() {
+ return false;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public bool isOK() {
+ return severity is OK;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the corresponding method on IStatus
.
+ */
+ public bool matches(int severityMask) {
+ return (severity & severityMask) !is 0;
+ }
+
+ /**
+ * Sets the status code.
+ *
+ * @param code the plug-in-specific status code, or OK
+ */
+ protected void setCode(int code) {
+ this.code = code;
+ }
+
+ /**
+ * Sets the exception.
+ *
+ * @param exception a low-level exception, or null
if not
+ * applicable
+ */
+ protected void setException(Exception exception) {
+ this.exception = exception;
+ }
+
+ /**
+ * Sets the message. If null is passed, message is set to an empty
+ * string.
+ *
+ * @param message a human-readable message, localized to the
+ * current locale
+ */
+ protected void setMessage(String message) {
+ if (message is null)
+ this.message = ""; //$NON-NLS-1$
+ else
+ this.message = message;
+ }
+
+ /**
+ * Sets the plug-in id.
+ *
+ * @param pluginId the unique identifier of the relevant plug-in
+ */
+ protected void setPlugin(String pluginId) {
+ Assert.isLegal(pluginId !is null && pluginId.length > 0);
+ this.pluginId = pluginId;
+ }
+
+ /**
+ * Sets the severity.
+ *
+ * @param severity the severity; one of OK
, ERROR
,
+ * INFO
, WARNING
, or CANCEL
+ */
+ protected void setSeverity(int severity) {
+ Assert.isLegal(severity is OK || severity is ERROR || severity is WARNING || severity is INFO || severity is CANCEL);
+ this.severity = severity;
+ }
+
+ /**
+ * Returns a string representation of the status, suitable
+ * for debugging purposes only.
+ */
+ public String toString() {
+ String sev;
+ if (severity is OK) {
+ sev="OK"; //$NON-NLS-1$
+ } else if (severity is ERROR) {
+ sev="ERROR"; //$NON-NLS-1$
+ } else if (severity is WARNING) {
+ sev="WARNING"; //$NON-NLS-1$
+ } else if (severity is INFO) {
+ sev="INFO"; //$NON-NLS-1$
+ } else if (severity is CANCEL) {
+ sev="CANCEL"; //$NON-NLS-1$
+ } else {
+ sev=Format( "severity={}", severity);
+ }
+ return Format("Status {}: {} code={} {} {}", sev, pluginId, code, message, exception.toString );
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/SubMonitor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/SubMonitor.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,787 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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:
+ * Stefan Xenos - initial API and implementation
+ * Stefan Xenos - bug 174539 - add a 1-argument convert(...) method
+ * Stefan Xenos - bug 174040 - SubMonitor#convert doesn't always set task name
+ * Port to the D programming language:
+ * Frank Benoit
+ *
+ *
+ *
+ *
+ *
+ * SubMonitor.convert(...).
to convert the IProgressMonitor
+ * into a SubMonitor. SubMonitor.newChild(...)
whenever you need to call another method that
+ * accepts an IProgressMonitor.
+ *
+ *
+ *
+ *
+ * @param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
+ * to call done() on the given monitor. Accepts
+ *
+ *
+ * null
, indicating that no progress should be
+ * reported and that the operation cannot be cancelled.SubMonitor
makes it unnecessary to call
+ * IProgressMonitor.done() in most situations.convert
or progress.newChild()
.
+ * In this example, there is no guarantee that monitor
is an instance of SubMonitor
, making it
+ * necessary to call monitor.done()
. The JavaDoc contract makes this the responsibility of the caller.
+ * // param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
+ * // to call done() on the given monitor. Accepts
+ *
+ *
+ *
+ * null
, indicating that no progress should be
+ * // reported and that the operation cannot be cancelled.
+ * //
+ * void doSomething(IProgressMonitor monitor) {
+ * // Convert the given monitor into a progress instance
+ * SubMonitor progress = SubMonitor.convert(monitor, 100);
+ *
+ * // Use 30% of the progress to do some work
+ * doSomeWork(progress.newChild(30));
+ *
+ * // Advance the monitor by another 30%
+ * progress.worked(30);
+ *
+ * // Use the remaining 40% of the progress to do some more work
+ * doSomeWork(progress.newChild(40));
+ * }
+ *
+ * // param monitor the progress monitor to use for reporting progress to the user, or
+ *
+ *
+ * null
indicating
+ * // that no progress should be reported and the operation cannot be cancelled.
+ * //
+ * void doSomething(IProgressMonitor monitor) {
+ * // Convert the given monitor into a progress instance
+ * SubMonitor progress = SubMonitor.convert(monitor, 100);
+ * try {
+ * // Use 30% of the progress to do some work
+ * doSomeWork(progress.newChild(30));
+ *
+ * // Advance the monitor by another 30%
+ * progress.worked(30);
+ *
+ * // Use the remaining 40% of the progress to do some more work
+ * doSomeWork(progress.newChild(40));
+ *
+ * } finally {
+ * if (monitor !is null) {
+ * monitor.done();
+ * }
+ * }
+ * }
+ *
+ * void doSomething(IProgressMonitor monitor) {
+ * SubMonitor progress = SubMonitor.convert(monitor, 100);
+ *
+ * if (condition) {
+ * // Use 50% of the progress to do some work
+ * doSomeWork(progress.newChild(50));
+ * }
+ *
+ * // Don't report any work, but ensure that we have 50 ticks remaining on the progress monitor.
+ * // If we already consumed 50 ticks in the above branch, this is a no-op. Otherwise, the remaining
+ * // space in the monitor is redistributed into 50 ticks.
+ *
+ * progress.setWorkRemaining(50);
+ *
+ * // Use the remainder of the progress monitor to do the rest of the work
+ * doSomeWork(progress.newChild(50));
+ * }
+ *
+ *
+ *
+ * if (condition) {
+ * // Use 50% of the progress to do some work
+ * doSomeWork(progress.newChild(50));
+ * } else {
+ * // Bad: Causes the progress monitor to appear to start at 50%, wasting half of the
+ * // space in the monitor.
+ * progress.worked(50);
+ * }
+ *
+ *
+ *
+ *
+ *
+ * void doSomething(IProgressMonitor monitor, Collection someCollection) {
+ * SubMonitor progress = SubMonitor.convert(monitor, 100);
+ *
+ * // Create a new progress monitor that uses 70% of the total progress and will allocate one tick
+ * // for each element of the given collection.
+ * SubMonitor loopProgress = progress.newChild(70).setWorkRemaining(someCollection.size());
+ *
+ * for (Iterator iter = someCollection.iterator(); iter.hasNext();) {
+ * Object next = iter.next();
+ *
+ * doWorkOnElement(next, loopProgress.newChild(1));
+ * }
+ *
+ * // Use the remaining 30% of the progress monitor to do some work outside the loop
+ * doSomeWork(progress.newChild(30));
+ * }
+ *
+ *
+ *
+ *
+ *
+ * void doSomething(IProgressMonitor monitor, LinkedListNode node) {
+ * SubMonitor progress = SubMonitor.convert(monitor, 100);
+ *
+ * while (node !is null) {
+ * // Regardless of the amount of progress reported so far,
+ * // use 5% of the space remaining in the monitor to process the next node.
+ * progress.setWorkRemaining(100);
+ *
+ * doWorkOnElement(node, progress.newChild(5));
+ *
+ * node = node.next;
+ * }
+ * }
+ *
+ *
+ * NullProgressMonitor
.
+ * @return a SubMonitor instance that adapts the argument
+ */
+ public static SubMonitor convert(IProgressMonitor monitor) {
+ return convert(monitor, "", 0); //$NON-NLS-1$
+ }
+
+ /**
+ * NullProgressMonitor
.
+ * @param work number of ticks that will be available in the resulting monitor
+ * @return a SubMonitor instance that adapts the argument
+ */
+ public static SubMonitor convert(IProgressMonitor monitor, int work) {
+ return convert(monitor, "", work); //$NON-NLS-1$
+ }
+
+ /**
+ * beginTask
or done
on the
+ * result. However, the resulting progress monitor will not report any work after the first
+ * call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
+ * or setWorkRemaining.
+ *
+ * @param totalWork number of ticks to consume from the reciever
+ * @return new sub progress monitor that may be used in place of a new SubMonitor
+ */
+ public SubMonitor newChild(int totalWork) {
+ return newChild(totalWork, SUPPRESS_BEGINTASK);
+ }
+
+ /**
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ * // Example 1: Typical usage of newChild
+ * void myMethod(IProgressMonitor parent) {
+ * SubMonitor progress = SubMonitor.convert(parent, 100);
+ * doSomething(progress.newChild(50));
+ * doSomethingElse(progress.newChild(50));
+ * }
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ * // Example 2: Demonstrates the function of active children. Creating children
+ * // is sufficient to smoothly report progress, even if worked(...) and done()
+ * // are never called.
+ * void myMethod(IProgressMonitor parent) {
+ * SubMonitor progress = SubMonitor.convert(parent, 100);
+ *
+ * for (int i = 0; i < 100; i++) {
+ * // Creating the next child monitor will clean up the previous one,
+ * // causing progress to be reported smoothly even if we don't do anything
+ * // with the monitors we create
+ * progress.newChild(1);
+ * }
+ * }
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ * // Example 3: Demonstrates a common anti-pattern
+ * void wrongMethod(IProgressMonitor parent) {
+ * SubMonitor progress = SubMonitor.convert(parent, 100);
+ *
+ * // WRONG WAY: Won't have the intended effect, as only one of these progress
+ * // monitors may be active at a time and the other will report no progress.
+ * callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
+ * }
+ *
+ * void rightMethod(IProgressMonitor parent) {
+ * SubMonitor progress = SubMonitor.convert(parent, 100);
+ *
+ * // RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
+ * Object someValue = computeValue(progress.newChild(50));
+ * callMethod(progress.newChild(50), someValue);
+ * }
+ *
beginTask
or done
on the
+ * result. However, the resulting progress monitor will not report any work after the first
+ * call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
+ * or setWorkRemaining.
+ *
+ * @param totalWork number of ticks to consume from the reciever
+ * @return new sub progress monitor that may be used in place of a new SubMonitor
+ */
+ public SubMonitor newChild(int totalWork, int suppressFlags) {
+ double totalWorkDouble = (totalWork > 0) ? totalWork : 0.0;
+ totalWorkDouble = Math.min(totalWorkDouble, totalForChildren - usedForChildren);
+ cleanupActiveChild();
+
+ // Compute the flags for the child. We want the net effect to be as though the child is
+ // delegating to its parent, even though it is actually talking directly to the root.
+ // This means that we need to compute the flags such that - even if a label isn't
+ // suppressed by the child - if that same label would have been suppressed when the
+ // child delegated to its parent, the child must explicitly suppress the label.
+ int childFlags = SUPPRESS_NONE;
+
+ if ((flags & SUPPRESS_SETTASKNAME) !is 0) {
+ // If the parent was ignoring labels passed to setTaskName, then the child will ignore
+ // labels passed to either beginTask or setTaskName - since both delegate to setTaskName
+ // on the parent
+ childFlags |= SUPPRESS_SETTASKNAME | SUPPRESS_BEGINTASK;
+ }
+
+ if ((flags & SUPPRESS_SUBTASK) !is 0) {
+ // If the parent was suppressing labels passed to subTask, so will the child.
+ childFlags |= SUPPRESS_SUBTASK;
+ }
+
+ // Note: the SUPPRESS_BEGINTASK flag does not affect the child since there
+ // is no method on the child that would delegate to beginTask on the parent.
+ childFlags |= suppressFlags;
+
+ SubMonitor result = new SubMonitor(root, consume(totalWorkDouble), 0, childFlags);
+ lastSubMonitor = result;
+ return result;
+ }
+
+ private void cleanupActiveChild() {
+ if (lastSubMonitor is null)
+ return;
+
+ IProgressMonitor child = lastSubMonitor;
+ lastSubMonitor = null;
+ child.done();
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
+ */
+ public void clearBlocked() {
+ root.clearBlocked();
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.core.runtime.IProgressMonitorWithBlocking#setBlocked(dwtx.core.runtime.IStatus)
+ */
+ public void setBlocked(IStatus reason) {
+ root.setBlocked(reason);
+ }
+
+ protected static bool eq(String o1, String o2) {
+ if (o1.length is 0)
+ return (o2.length is 0);
+ if (o2.length is 0)
+ return false;
+ return o1.equals(o2);
+ }
+}
diff -r a012107a911c -r 6518c18a01f7 dwtx/core/runtime/SubProgressMonitor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/runtime/SubProgressMonitor.d Wed Mar 26 00:57:19 2008 +0100
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * ////////////////////////////////////////////////////////////////////////////
+ * // Example 1: Typical usage of newChild
+ * void myMethod(IProgressMonitor parent) {
+ * SubMonitor progress = SubMonitor.convert(parent, 100);
+ * doSomething(progress.newChild(50));
+ * doSomethingElse(progress.newChild(50));
+ * }
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ * // Example 2: Demonstrates the function of active children. Creating children
+ * // is sufficient to smoothly report progress, even if worked(...) and done()
+ * // are never called.
+ * void myMethod(IProgressMonitor parent) {
+ * SubMonitor progress = SubMonitor.convert(parent, 100);
+ *
+ * for (int i = 0; i < 100; i++) {
+ * // Creating the next child monitor will clean up the previous one,
+ * // causing progress to be reported smoothly even if we don't do anything
+ * // with the monitors we create
+ * progress.newChild(1);
+ * }
+ * }
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ * // Example 3: Demonstrates a common anti-pattern
+ * void wrongMethod(IProgressMonitor parent) {
+ * SubMonitor progress = SubMonitor.convert(parent, 100);
+ *
+ * // WRONG WAY: Won't have the intended effect, as only one of these progress
+ * // monitors may be active at a time and the other will report no progress.
+ * callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
+ * }
+ *
+ * void rightMethod(IProgressMonitor parent) {
+ * SubMonitor progress = SubMonitor.convert(parent, 100);
+ *
+ * // RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
+ * Object someValue = computeValue(progress.newChild(50));
+ * callMethod(progress.newChild(50), someValue);
+ * }
+ *
+ * try {
+ * pm.beginTask("Main Task", 100);
+ * doSomeWork(pm, 30);
+ * SubProgressMonitor subMonitor= new SubProgressMonitor(pm, 40);
+ * try {
+ * subMonitor.beginTask("", 300);
+ * doSomeWork(subMonitor, 300);
+ * } finally {
+ * subMonitor.done();
+ * }
+ * doSomeWork(pm, 30);
+ * } finally {
+ * pm.done();
+ * }
+ *
+ * subTask
+ * should not have any effect.
+ *
+ * @see #SubProgressMonitor(IProgressMonitor,int,int)
+ */
+ public static const int SUPPRESS_SUBTASK_LABEL = 1 << 1;
+ /**
+ * Style constant indicating that the main task label
+ * should be prepended to the subtask label.
+ *
+ * @see #SubProgressMonitor(IProgressMonitor,int,int)
+ */
+ public static const int PREPEND_MAIN_LABEL_TO_SUBTASK = 1 << 2;
+
+ private int parentTicks = 0;
+ private double sentToParent = 0.0;
+ private double scale = 0.0;
+ private int nestedBeginTasks = 0;
+ private bool usedUp = false;
+ private bool hasSubTask = false;
+ private int style;
+ private String mainTaskLabel;
+
+ /**
+ * Creates a new sub-progress monitor for the given monitor. The sub
+ * progress monitor uses the given number of work ticks from its
+ * parent monitor.
+ *
+ * @param monitor the parent progress monitor
+ * @param ticks the number of work ticks allocated from the
+ * parent monitor
+ */
+ public this(IProgressMonitor monitor, int ticks) {
+ this(monitor, ticks, 0);
+ }
+
+ /**
+ * Creates a new sub-progress monitor for the given monitor. The sub
+ * progress monitor uses the given number of work ticks from its
+ * parent monitor.
+ *
+ * @param monitor the parent progress monitor
+ * @param ticks the number of work ticks allocated from the
+ * parent monitor
+ * @param style one of
+ *
+ *
+ * @see #SUPPRESS_SUBTASK_LABEL
+ * @see #PREPEND_MAIN_LABEL_TO_SUBTASK
+ */
+ public this(IProgressMonitor monitor, int ticks, int style) {
+ super(monitor);
+ this.parentTicks = (ticks > 0) ? ticks : 0;
+ this.style = style;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the method SUPPRESS_SUBTASK_LABEL
PREPEND_MAIN_LABEL_TO_SUBTASK
IProgressMonitor.beginTask
.
+ *
+ * Starts a new main task. Since this progress monitor is a sub
+ * progress monitor, the given name will NOT be used to update
+ * the progress bar's main task label. That means the given
+ * string will be ignored. If style PREPEND_MAIN_LABEL_TO_SUBTASK
+ *
is specified, then the given string will be prepended to
+ * every string passed to
subTask(String)
.
+ */
+ public void beginTask(String name, int totalWork) {
+ nestedBeginTasks++;
+ // Ignore nested begin task calls.
+ if (nestedBeginTasks > 1) {
+ return;
+ }
+ // be safe: if the argument would cause math errors (zero or
+ // negative), just use 0 as the scale. This disables progress for
+ // this submonitor.
+ scale = totalWork <= 0 ? 0 : cast(double) parentTicks / cast(double) totalWork;
+ if ((style & PREPEND_MAIN_LABEL_TO_SUBTASK) !is 0) {
+ mainTaskLabel = name;
+ }
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the method IProgressMonitor.done
.
+ */
+ public void done() {
+ // Ignore if more done calls than beginTask calls or if we are still
+ // in some nested beginTasks
+ if (nestedBeginTasks is 0 || --nestedBeginTasks > 0)
+ return;
+ // Send any remaining ticks and clear out the subtask text
+ double remaining = parentTicks - sentToParent;
+ if (remaining > 0)
+ super.internalWorked(remaining);
+ //clear the sub task if there was one
+ if (hasSubTask)
+ subTask(""); //$NON-NLS-1$
+ sentToParent = 0;
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the internal method IProgressMonitor.internalWorked
.
+ */
+ public void internalWorked(double work) {
+ if (usedUp || nestedBeginTasks !is 1) {
+ return;
+ }
+
+ double realWork = (work > 0.0) ? scale * work : 0.0;
+ super.internalWorked(realWork);
+ sentToParent += realWork;
+ if (sentToParent >= parentTicks) {
+ usedUp = true;
+ }
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the method IProgressMonitor.subTask
.
+ */
+ public void subTask(String name) {
+ if ((style & SUPPRESS_SUBTASK_LABEL) !is 0) {
+ return;
+ }
+ hasSubTask = true;
+ String label = name;
+ if ((style & PREPEND_MAIN_LABEL_TO_SUBTASK) !is 0 && mainTaskLabel !is null && mainTaskLabel.length > 0) {
+ label = mainTaskLabel ~ ' ' ~ label;
+ }
+ super.subTask(label);
+ }
+
+ /* (Intentionally not javadoc'd)
+ * Implements the method IProgressMonitor.worked
.
+ */
+ public void worked(int work) {
+ internalWorked(work);
+ }
+}