Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Webster2010-03-02 20:12:32 +0000
committerPaul Webster2010-03-02 20:12:32 +0000
commit37848358f0b5f81a9ae0bbe264c50357e788f2f5 (patch)
tree14bf8a1dc13f855d77af2276935f10de7403ace1 /bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/KeyBindingService.java
parent11d46d6c88e8383d7970bf26aff954047343bbb9 (diff)
downloadeclipse.platform.ui-37848358f0b5f81a9ae0bbe264c50357e788f2f5.tar.gz
eclipse.platform.ui-37848358f0b5f81a9ae0bbe264c50357e788f2f5.tar.xz
eclipse.platform.ui-37848358f0b5f81a9ae0bbe264c50357e788f2f5.zip
Bug 299385 - [UI] clean up errors in compatibility workbenchI20100406-2156
Changes to support the extended compat layer
Diffstat (limited to 'bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/KeyBindingService.java')
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/KeyBindingService.java636
1 files changed, 636 insertions, 0 deletions
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/KeyBindingService.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/KeyBindingService.java
new file mode 100644
index 00000000000..ff06d8aad82
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/KeyBindingService.java
@@ -0,0 +1,636 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 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
+ *******************************************************************************/
+package org.eclipse.ui.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.ui.IKeyBindingService;
+import org.eclipse.ui.INestableKeyBindingService;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.IWorkbenchSite;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ActionHandler;
+import org.eclipse.ui.commands.HandlerSubmission;
+import org.eclipse.ui.commands.IHandler;
+import org.eclipse.ui.commands.Priority;
+import org.eclipse.ui.contexts.EnabledSubmission;
+import org.eclipse.ui.internal.actions.CommandAction;
+import org.eclipse.ui.internal.handlers.CommandLegacyActionWrapper;
+
+/**
+ * This service provides a nestable implementation of a key binding service.
+ * This class is provided for backwards compatibility only, and might be removed
+ * in the future. All of the functionality is the class can be duplicated by
+ * using the commands and contexts API.
+ *
+ * @since 2.0
+ */
+public final class KeyBindingService implements INestableKeyBindingService {
+
+ /**
+ * The currently active nested service, if any. If there are no nested
+ * services or none of them are active, then this value is <code>null</code>.
+ */
+ private IKeyBindingService activeService = null;
+
+ /**
+ * Whether this key binding service has been disposed. A disposed key
+ * binding service should not be used again.
+ */
+ private boolean disposed;
+
+ /**
+ * The set of context identifiers enabled in this key binding service (not
+ * counting any nested services). This set may be empty, but it is never
+ * <code>null</code>.
+ */
+ private Set enabledContextIds = Collections.EMPTY_SET;
+
+ /**
+ * The list of context submissions indicating the enabled state of the
+ * context. This does not include those from nested services. This list may
+ * be empty, but it is never <code>null</code>.
+ */
+ private List enabledSubmissions = new ArrayList();
+
+ /**
+ * The map of handler submissions, sorted by command identifiers. This does
+ * not include those from nested services. This map may be empty, but it is
+ * never <code>null</code>.
+ */
+ private Map handlerSubmissionsByCommandId = new HashMap();
+
+ /**
+ * The context submissions from the currently active nested service. This
+ * value is <code>null</code> if there is no currently active nested
+ * service.
+ */
+ private List nestedEnabledSubmissions = null;
+
+ /**
+ * The handler submissions from the currently active nested service. This
+ * value is <code>null</code> if there is no currently active handler
+ * service.
+ */
+ private List nestedHandlerSubmissions = null;
+
+ /**
+ * The map of workbench part sites to nested key binding services. This map
+ * may be empty, but is never <code>null</code>.
+ */
+ private final Map nestedServices = new HashMap();
+
+ /**
+ * The parent for this key binding service; <code>null</code> if there is
+ * no parent. If there is a parent, then this means that it should not do a
+ * "live" update of its contexts or handlers, but should make a call to the
+ * parent instead.
+ */
+ private final KeyBindingService parent;
+
+ /**
+ * The site within the workbench at which this service is provided. This
+ * value should not be <code>null</code>.
+ */
+ private IWorkbenchPartSite workbenchPartSite;
+
+ /**
+ * Constructs a new instance of <code>KeyBindingService</code> on a given
+ * workbench site. This instance is not nested.
+ *
+ * @param workbenchPartSite
+ * The site for which this service will be responsible; should
+ * not be <code>null</code>.
+ */
+ public KeyBindingService(IWorkbenchPartSite workbenchPartSite) {
+ this(workbenchPartSite, null);
+ }
+
+ /**
+ * Constructs a new instance of <code>KeyBindingService</code> on a given
+ * workbench site.
+ *
+ * @param workbenchPartSite
+ * The site for which this service will be responsible; should
+ * not be <code>null</code>.
+ * @param parent
+ * The parent key binding service, if any; <code>null</code> if
+ * none.
+ */
+ KeyBindingService(IWorkbenchPartSite workbenchPartSite,
+ KeyBindingService parent) {
+ this.workbenchPartSite = workbenchPartSite;
+ this.parent = parent;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.INestableKeyBindingService#activateKeyBindingService(org.eclipse.ui.IWorkbenchSite)
+ */
+ public boolean activateKeyBindingService(IWorkbenchSite nestedSite) {
+ if (disposed) {
+ return false;
+ }
+
+ // Check if we should do a deactivation.
+ if (nestedSite == null) {
+ // We should do a deactivation, if there is one active.
+ if (activeService == null) {
+ // There is no active service. Do no work.
+ return false;
+ }
+ // Deactivate the currently active nested service.
+ deactivateNestedService();
+ return true;
+ }
+
+ // Attempt to activate a service.
+ final IKeyBindingService service = (IKeyBindingService) nestedServices
+ .get(nestedSite);
+
+ if (service == activeService) {
+ // The service is already active, or already null
+ return false;
+ }
+
+ deactivateNestedService();
+ if (service!=null) {
+ activateNestedService(service);
+ }
+ return true;
+ }
+
+ /**
+ * Activates the given service without worrying about the currently active
+ * service. This goes through the work of adding all of the nested context
+ * ids as enabled submissions.
+ *
+ * @param service
+ * The service to become active; if <code>null</code>, then
+ * the reference to the active service is set to
+ * <code>null</code> but nothing else happens.
+ */
+ private final void activateNestedService(final IKeyBindingService service) {
+ if (disposed) {
+ return;
+ }
+
+ /*
+ * If I have a parent, and I'm the active service, then deactivate so
+ * that I can make changes.
+ */
+ boolean active = false;
+ boolean haveParent = (parent != null);
+ if (haveParent) {
+ active = (parent.activeService == this);
+ if (active) {
+ parent.deactivateNestedService();
+ }
+ }
+
+ // Update the active service.
+ activeService = service;
+
+ // Check to see that the service isn't null.
+ if (service == null) {
+ return;
+ }
+
+ if (haveParent) {
+ if (active) {
+ parent.activateNestedService(this);
+ }
+
+ } else if (activeService instanceof KeyBindingService) {
+ // I have no parent, so I can make the changes myself.
+ final KeyBindingService nestedService = (KeyBindingService) activeService;
+
+ // Update the contexts.
+ nestedEnabledSubmissions = nestedService.getEnabledSubmissions();
+ normalizeSites(nestedEnabledSubmissions);
+ PlatformUI.getWorkbench().getContextSupport().addEnabledSubmissions(
+ nestedEnabledSubmissions);
+
+ // Update the handlers.
+ nestedHandlerSubmissions = nestedService.getHandlerSubmissions();
+ normalizeSites(nestedHandlerSubmissions);
+ PlatformUI.getWorkbench().getCommandSupport().addHandlerSubmissions(
+ nestedHandlerSubmissions);
+ }
+ }
+
+ /**
+ * Deactives the currently active service. This nulls out the reference, and
+ * removes all the enabled submissions for the nested service.
+ */
+ private final void deactivateNestedService() {
+ if (disposed) {
+ return;
+ }
+
+ // Don't do anything if there is no active service.
+ if (activeService == null) {
+ return;
+ }
+
+ // Check to see if there is a parent.
+ boolean active = false;
+ if (parent != null) {
+ // Check if I'm the active service.
+ if (parent.activeService == this) {
+ active = true;
+ // Deactivate myself so I can make changes.
+ parent.deactivateNestedService();
+ }
+
+ } else if (activeService instanceof KeyBindingService) {
+ // Remove all the nested context ids.
+ PlatformUI.getWorkbench().getContextSupport()
+ .removeEnabledSubmissions(nestedEnabledSubmissions);
+
+ /*
+ * Remove all of the nested handler submissions. The handlers here
+ * weren't created by this instance (but by the nest instance), and
+ * hence can't be disposed here.
+ */
+ PlatformUI.getWorkbench().getCommandSupport()
+ .removeHandlerSubmissions(nestedHandlerSubmissions);
+
+ }
+
+ // Clear our reference to the active service.
+ activeService = null;
+
+ // If necessary, let my parent know that changes have occurred.
+ if (active) {
+ parent.activateNestedService(this);
+ }
+ }
+
+ /**
+ * Disposes this key binding service. This clears out all of the submissions
+ * held by this service, and its nested services.
+ */
+ public void dispose() {
+ if (!disposed) {
+ deactivateNestedService();
+ disposed = true;
+
+ PlatformUI.getWorkbench()
+ .getContextSupport()
+ .removeEnabledSubmissions(new ArrayList(enabledSubmissions));
+ enabledSubmissions.clear();
+
+ /*
+ * Each removed handler submission, must dispose its corresponding
+ * handler -- as these handlers only exist inside of this class.
+ */
+ final List submissions = new ArrayList(
+ handlerSubmissionsByCommandId.values());
+ final Iterator submissionItr = submissions.iterator();
+ while (submissionItr.hasNext()) {
+ ((HandlerSubmission) submissionItr.next()).getHandler()
+ .dispose();
+ }
+ PlatformUI.getWorkbench().getCommandSupport()
+ .removeHandlerSubmissions(submissions);
+ handlerSubmissionsByCommandId.clear();
+
+ for (Iterator iterator = nestedServices.values().iterator(); iterator
+ .hasNext();) {
+ KeyBindingService keyBindingService = (KeyBindingService) iterator
+ .next();
+ keyBindingService.dispose();
+ }
+
+ nestedEnabledSubmissions = null;
+ nestedHandlerSubmissions = null;
+ nestedServices.clear();
+ }
+ }
+
+ /**
+ * Gets a copy of all the enabled submissions in the nesting chain.
+ *
+ * @return All of the nested enabled submissions -- including the ones from
+ * this service. This list may be empty, but is never
+ * <code>null</code>.
+ */
+ private final List getEnabledSubmissions() {
+ if (disposed) {
+ return null;
+ }
+
+ final List submissions = new ArrayList(enabledSubmissions);
+ if (activeService instanceof KeyBindingService) {
+ final KeyBindingService nestedService = (KeyBindingService) activeService;
+ submissions.addAll(nestedService.getEnabledSubmissions());
+ }
+ return submissions;
+ }
+
+ /**
+ * Gets a copy of all the handler submissions in the nesting chain.
+ *
+ * @return All of the nested handler submissions -- including the ones from
+ * this service. This list may be empty, but is never
+ * <code>null</code>.
+ */
+ private final List getHandlerSubmissions() {
+ if (disposed) {
+ return null;
+ }
+
+ final List submissions = new ArrayList(handlerSubmissionsByCommandId
+ .values());
+ if (activeService instanceof KeyBindingService) {
+ final KeyBindingService nestedService = (KeyBindingService) activeService;
+ submissions.addAll(nestedService.getHandlerSubmissions());
+ }
+ return submissions;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.INestableKeyBindingService#getKeyBindingService(org.eclipse.ui.IWorkbenchSite)
+ */
+ public IKeyBindingService getKeyBindingService(IWorkbenchSite nestedSite) {
+ if (disposed) {
+ return null;
+ }
+
+ if (nestedSite == null) {
+ return null;
+ }
+
+ IKeyBindingService service = (IKeyBindingService) nestedServices
+ .get(nestedSite);
+ if (service == null) {
+ // TODO the INestedKeyBindingService API should be based on
+ // IWorkbenchPartSite..
+ if (nestedSite instanceof IWorkbenchPartSite) {
+ service = new KeyBindingService(
+ (IWorkbenchPartSite) nestedSite, this);
+ } else {
+ service = new KeyBindingService(null, this);
+ }
+
+ nestedServices.put(nestedSite, service);
+ }
+
+ return service;
+ }
+
+ public String[] getScopes() {
+ if (disposed) {
+ return null;
+ }
+
+ // Get the nested scopes, if any.
+ final String[] nestedScopes;
+ if (activeService == null) {
+ nestedScopes = null;
+ } else {
+ nestedScopes = activeService.getScopes();
+ }
+
+ // Build the list of active scopes
+ final Set activeScopes = new HashSet();
+ activeScopes.addAll(enabledContextIds);
+ if (nestedScopes != null) {
+ for (int i = 0; i < nestedScopes.length; i++) {
+ activeScopes.add(nestedScopes[i]);
+ }
+ }
+
+ return (String[]) activeScopes.toArray(new String[activeScopes.size()]);
+ }
+
+ /**
+ * Replaces the active workbench site with this service's active workbench
+ * site. This ensures that the context manager will recognize the context as
+ * active. Note: this method modifies the list in place; it is
+ * <em>destructive</em>.
+ *
+ * @param submissionsToModify
+ * The submissions list to modify; must not be <code>null</code>,
+ * but may be empty.
+ */
+ private final void normalizeSites(final List submissionsToModify) {
+ if (disposed) {
+ return;
+ }
+
+ final int size = submissionsToModify.size();
+ for (int i = 0; i < size; i++) {
+ final Object submission = submissionsToModify.get(i);
+ final Object replacementSubmission;
+
+ if (submission instanceof EnabledSubmission) {
+ final EnabledSubmission enabledSubmission = (EnabledSubmission) submission;
+ if (!workbenchPartSite.equals(enabledSubmission
+ .getActiveWorkbenchPartSite())) {
+ replacementSubmission = new EnabledSubmission(null,
+ enabledSubmission.getActiveShell(),
+ workbenchPartSite, enabledSubmission.getContextId());
+ } else {
+ replacementSubmission = enabledSubmission;
+ }
+
+ } else if (submission instanceof HandlerSubmission) {
+ final HandlerSubmission handlerSubmission = (HandlerSubmission) submission;
+ if (!workbenchPartSite.equals(handlerSubmission
+ .getActiveWorkbenchPartSite())) {
+ replacementSubmission = new HandlerSubmission(null,
+ handlerSubmission.getActiveShell(),
+ workbenchPartSite,
+ handlerSubmission.getCommandId(), handlerSubmission
+ .getHandler(), handlerSubmission
+ .getPriority());
+ } else {
+ replacementSubmission = handlerSubmission;
+ }
+
+ } else {
+ replacementSubmission = submission;
+ }
+
+ submissionsToModify.set(i, replacementSubmission);
+ }
+
+ }
+
+ public void registerAction(IAction action) {
+ if (disposed) {
+ return;
+ }
+
+ if (action instanceof CommandLegacyActionWrapper) {
+ // this is a registration of a fake action for an already
+ // registered handler
+ WorkbenchPlugin
+ .log("Cannot register a CommandLegacyActionWrapper back into the system"); //$NON-NLS-1$
+ return;
+ }
+
+ if (action instanceof CommandAction) {
+ // we unfortunately had to allow these out into the wild, but they
+ // still must not feed back into the system
+ return;
+ }
+
+ unregisterAction(action);
+ String commandId = action.getActionDefinitionId();
+ if (commandId != null) {
+ /*
+ * If I have a parent and I'm active, de-activate myself while
+ * making changes.
+ */
+ boolean active = false;
+ if ((parent != null) && (parent.activeService == this)) {
+ active = true;
+ parent.deactivateNestedService();
+ }
+
+ // Create the new submission
+ IHandler handler = new ActionHandler(action);
+ HandlerSubmission handlerSubmission = new HandlerSubmission(null,
+ workbenchPartSite.getShell(), workbenchPartSite, commandId,
+ handler, Priority.MEDIUM);
+ handlerSubmissionsByCommandId.put(commandId, handlerSubmission);
+
+ // Either submit the new handler myself, or simply re-activate.
+ if (parent != null) {
+ if (active) {
+ parent.activateNestedService(this);
+ }
+ } else {
+ PlatformUI.getWorkbench().getCommandSupport()
+ .addHandlerSubmission(handlerSubmission);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.INestableKeyBindingService#removeKeyBindingService(org.eclipse.ui.IWorkbenchSite)
+ */
+ public boolean removeKeyBindingService(IWorkbenchSite nestedSite) {
+ if (disposed) {
+ return false;
+ }
+
+ final IKeyBindingService service = (IKeyBindingService) nestedServices
+ .remove(nestedSite);
+ if (service == null) {
+ return false;
+ }
+
+ if (service.equals(activeService)) {
+ deactivateNestedService();
+ }
+
+ return true;
+ }
+
+ public void setScopes(String[] scopes) {
+ if (disposed) {
+ return;
+ }
+
+ // Either deactivate myself, or remove the previous submissions myself.
+ boolean active = false;
+ if ((parent != null) && (parent.activeService == this)) {
+ active = true;
+ parent.deactivateNestedService();
+ } else {
+ PlatformUI.getWorkbench().getContextSupport()
+ .removeEnabledSubmissions(enabledSubmissions);
+ }
+ enabledSubmissions.clear();
+
+ // Determine the new list of submissions.
+ enabledContextIds = new HashSet(Arrays.asList(scopes));
+ for (Iterator iterator = enabledContextIds.iterator(); iterator
+ .hasNext();) {
+ String contextId = (String) iterator.next();
+ enabledSubmissions.add(new EnabledSubmission(null, null,
+ workbenchPartSite, contextId));
+ }
+
+ // Submit the new contexts myself, or simply re-active myself.
+ if (parent != null) {
+ if (active) {
+ parent.activateNestedService(this);
+ }
+ } else {
+ PlatformUI.getWorkbench().getContextSupport().addEnabledSubmissions(
+ enabledSubmissions);
+ }
+ }
+
+ public void unregisterAction(IAction action) {
+ if (disposed) {
+ return;
+ }
+
+ if (action instanceof CommandLegacyActionWrapper) {
+ // this is a registration of a fake action for an already
+ // registered handler
+ WorkbenchPlugin
+ .log("Cannot unregister a CommandLegacyActionWrapper out of the system"); //$NON-NLS-1$
+ return;
+ }
+
+ String commandId = action.getActionDefinitionId();
+
+ if (commandId != null) {
+ // Deactivate this service while making changes.
+ boolean active = false;
+ if ((parent != null) && (parent.activeService == this)) {
+ active = true;
+ parent.deactivateNestedService();
+ }
+
+ // Remove the current submission, if any.
+ HandlerSubmission handlerSubmission = (HandlerSubmission) handlerSubmissionsByCommandId
+ .remove(commandId);
+
+ /*
+ * Either activate this service again, or remove the submission
+ * myself.
+ */
+ if (parent != null) {
+ if (active) {
+ parent.activateNestedService(this);
+ }
+ } else {
+ if (handlerSubmission != null) {
+ PlatformUI.getWorkbench().getCommandSupport()
+ .removeHandlerSubmission(handlerSubmission);
+ handlerSubmission.getHandler().dispose();
+ }
+ }
+ }
+ }
+}

Back to the top