All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.ui.SubActionBars Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Lars Vogel  - Bug 440810
 *******************************************************************************/
package org.eclipse.ui;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.common.EventManager;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionInfo;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.SubMenuManager;
import org.eclipse.jface.action.SubStatusLineManager;
import org.eclipse.jface.action.SubToolBarManager;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.EditorActionBars;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.actions.CommandAction;
import org.eclipse.ui.internal.handlers.CommandLegacyActionWrapper;
import org.eclipse.ui.internal.handlers.IActionCommandMappingService;
import org.eclipse.ui.internal.services.SourcePriorityNameMapping;
import org.eclipse.ui.services.IServiceLocator;

/**
 * Generic implementation of the IActionBars interface.
 */
public class SubActionBars extends EventManager implements IActionBars {

	/**
	 * The expression to use when contributing handlers through
	 * {@link #setGlobalActionHandler(String, IAction)}}. This ensures that handlers
	 * contributed through {@link SubActionBars} are given priority over handlers
	 * contributed to the {@link IHandlerService}.
	 */
	private static final Expression EXPRESSION = new Expression() {
		@Override
		public final EvaluationResult evaluate(final IEvaluationContext context) {
			return EvaluationResult.TRUE;
		}

		@Override
		public final void collectExpressionInfo(final ExpressionInfo info) {
			info.addVariableNameAccess(SourcePriorityNameMapping.LEGACY_LEGACY_NAME);
		}
	};

	/**
	 * Property constant for changes to action handlers.
	 */
	public static final String P_ACTION_HANDLERS = "org.eclipse.ui.internal.actionHandlers"; //$NON-NLS-1$

	private Map actionHandlers;

	private boolean actionHandlersChanged;

	/**
	 * A map of handler activations ({@link IHandlerActivation} indexed by action id
	 * ({@link String}) indexed by service locator ({@link IServiceLocator}). This
	 * value is null if there are no activations.
	 */
	private Map> activationsByActionIdByServiceLocator;

	private boolean active = false;

	private SubMenuManager menuMgr;

	private IActionBars parent;

	/**
	 * A service locator appropriate for this action bar. This value is never
	 * null. It must be capable of providing a {@link IHandlerService}.
	 */
	private IServiceLocator serviceLocator;

	private SubStatusLineManager statusLineMgr;

	private SubToolBarManager toolBarMgr;

	private Map actionIdByCommandId = new HashMap<>();

	/**
	 * Construct a new SubActionBars object. The service locator will
	 * simply be the service locator of the parent.
	 *
	 * @param parent The parent of this action bar; must not be null.
	 */
	public SubActionBars(final IActionBars parent) {
		this(parent, null);
	}

	/**
	 * Constructs a new instance of SubActionBars.
	 *
	 * @param parent         The parent of this action bar; must not be
	 *                       null.
	 * @param serviceLocator The service locator for this action bar; should not be
	 *                       null.
	 *
	 * @since 3.2
	 */
	public SubActionBars(final IActionBars parent, final IServiceLocator serviceLocator) {
		if (parent == null) {
			throw new NullPointerException("The parent cannot be null"); //$NON-NLS-1$
		}

		this.parent = parent;
		this.serviceLocator = serviceLocator;
	}

	/**
	 * Activate the contributions.
	 */
	public void activate() {
		activate(true);
	}

	/**
	 * Activate the contributions.
	 * 

* Workaround for toolbar layout flashing when editors contribute large amounts * of items. In this case we want to force the items to be visible/hidden only * when required, otherwise just change the enablement state. *

* * @param forceVisibility (is not used) */ public void activate(boolean forceVisibility) { setActive(true); } /** * Adds a property change listener. Has no effect if an identical listener is * already registered. * * @param listener a property change listener */ public void addPropertyChangeListener(IPropertyChangeListener listener) { addListenerObject(listener); } /** * Sets the active flag. Clients should not call this method directly unless * they are overriding the setActive() method. */ protected final void basicSetActive(boolean active) { this.active = active; } /** * Clear the global action handlers. */ @Override public void clearGlobalActionHandlers() { if (actionHandlers != null) { actionHandlers.clear(); actionHandlersChanged = true; } if (activationsByActionIdByServiceLocator != null) { // Clean up the activations. final Iterator>> activationItr = activationsByActionIdByServiceLocator .entrySet().iterator(); while (activationItr.hasNext()) { final Map.Entry> value = activationItr.next(); final IServiceLocator locator = value.getKey(); final IHandlerService service = locator.getService(IHandlerService.class); final Map activationsByActionId = value.getValue(); Collection activations = activationsByActionId.values(); if (service != null) { service.deactivateHandlers(activations); } for (Object activation : activations) { ((IHandlerActivation) activation).getHandler().dispose(); } } activationsByActionIdByServiceLocator.clear(); } } /** * Returns a new sub menu manager. * * @param parent the parent menu manager * @return the menu manager */ protected SubMenuManager createSubMenuManager(IMenuManager parent) { return new SubMenuManager(parent); } /** * Returns a new sub toolbar manager. * * @param parent the parent toolbar manager * @return the tool bar manager */ protected SubToolBarManager createSubToolBarManager(IToolBarManager parent) { return new SubToolBarManager(parent); } /** * Deactivate the contributions. */ public void deactivate() { deactivate(true); } /** * Deactivate the contributions. *

* Workaround for menubar/toolbar layout flashing when editors have many * contributions. In this case we want to force the contributions to be * visible/hidden only when required, otherwise just change the enablement * state. *

* * @param forceHide (not used) */ public void deactivate(boolean forceHide) { setActive(false); } /** * Dispose the contributions. */ public void dispose() { clearGlobalActionHandlers(); if (menuMgr != null) { menuMgr.dispose(); menuMgr.disposeManager(); } if (statusLineMgr != null) { statusLineMgr.disposeManager(); } if (toolBarMgr != null) { toolBarMgr.disposeManager(); } updateActionBars(); // Notify listeners and parent clearListeners(); } /** * Notifies any property change listeners if the global action handlers have * changed */ protected void fireActionHandlersChanged() { if (actionHandlersChanged) { // Doesn't actually pass the old and new values firePropertyChange(new PropertyChangeEvent(this, P_ACTION_HANDLERS, null, null)); actionHandlersChanged = false; } } /** * Notifies any property change listeners that a property has changed. Only * listeners registered at the time this method is called are notified. * * @param event the property change event * * @see IPropertyChangeListener#propertyChange */ protected void firePropertyChange(PropertyChangeEvent event) { Object[] listeners = getListeners(); for (Object listener : listeners) { ((IPropertyChangeListener) listener).propertyChange(event); } } /** * Return whether the manager is currently active or not. */ protected final boolean getActive() { return active; } /** * Get the handler for a window action. * * @param actionID an action ID declared in the registry * @return an action handler which implements the action ID, or * null if none is registered. */ @Override public IAction getGlobalActionHandler(String actionID) { if (actionHandlers == null) { return null; } return actionHandlers.get(actionID); } /** * Returns the complete list of active global action handlers. If there are no * global action handlers registered return null. * * @return a map with global action handlers */ public Map getGlobalActionHandlers() { return actionHandlers; } /** * Returns the abstract menu manager. If items are added or removed from the * manager be sure to call updateActionBars. * * @return the menu manager */ @Override public IMenuManager getMenuManager() { if (menuMgr == null) { menuMgr = createSubMenuManager(parent.getMenuManager()); menuMgr.setVisible(active); } return menuMgr; } /** * Return the parent action bar manager. */ protected final IActionBars getParent() { return parent; } /** * Answer the service locator for this action bar. * * @return an IServiceLocater or the parents if the receiver does * not have one * * @since 3.2 */ @Override public final IServiceLocator getServiceLocator() { if (serviceLocator != null) { return serviceLocator; } return parent.getServiceLocator(); } /** * Returns the status line manager. If items are added or removed from the * manager be sure to call updateActionBars. * * @return the status line manager */ @Override public IStatusLineManager getStatusLineManager() { if (statusLineMgr == null) { statusLineMgr = new SubStatusLineManager(parent.getStatusLineManager()); statusLineMgr.setVisible(active); } return statusLineMgr; } /** * Returns the tool bar manager. If items are added or removed from the manager * be sure to call updateActionBars. * * @return the tool bar manager */ @Override public IToolBarManager getToolBarManager() { if (toolBarMgr == null) { toolBarMgr = createSubToolBarManager(parent.getToolBarManager()); toolBarMgr.setVisible(active); } return toolBarMgr; } /** * Return whether the sub menu manager has been created yet. */ protected final boolean isSubMenuManagerCreated() { return menuMgr != null; } /** * Return whether the sub status line manager has been created yet. */ protected final boolean isSubStatusLineManagerCreated() { return statusLineMgr != null; } /** * Return whether the sub toolbar manager has been created yet. */ protected final boolean isSubToolBarManagerCreated() { return toolBarMgr != null; } /** * Notification that the target part for the action bars has changed. This * implementation does nothing. * * @param part the part to be notified. */ public void partChanged(IWorkbenchPart part) { } /** * Removes the given property change listener. Has no effect if an identical * listener is not registered. * * @param listener a property change listener */ public void removePropertyChangeListener(IPropertyChangeListener listener) { removeListenerObject(listener); } /** * Activate / deactivate the contributions. */ protected void setActive(boolean set) { active = set; if (menuMgr != null) { menuMgr.setVisible(set); } if (statusLineMgr != null) { statusLineMgr.setVisible(set); } if (toolBarMgr != null) { toolBarMgr.setVisible(set); } } /** * Add a handler for a window action. * * @param actionID an action ID declared in the registry * @param handler an action which implements the action ID. null * may be passed to deregister a handler. */ @Override public void setGlobalActionHandler(String actionID, IAction handler) { if (actionID == null) { /* * Bug 124061. It used to be invalid to pass null as an action id, but some * people still did it. Handle this case by trapping the exception and logging * it. */ WorkbenchPlugin.log("Cannot set the global action handler for a null action id"); //$NON-NLS-1$ return; } if (handler instanceof CommandLegacyActionWrapper) { // this is a registration of a fake action for an already // registered handler WorkbenchPlugin.log("Cannot feed a CommandLegacyActionWrapper back into the system"); //$NON-NLS-1$ return; } if (handler instanceof CommandAction) { // we unfortunately had to allow these out into the wild, but they // still must not feed back into the system return; } if (handler != null) { // Update the action handlers. if (actionHandlers == null) { actionHandlers = new HashMap<>(11); } actionHandlers.put(actionID, handler); // Add a mapping from this action id to the command id. if (serviceLocator != null) { String commandId = null; final IActionCommandMappingService mappingService = serviceLocator .getService(IActionCommandMappingService.class); if (mappingService != null) { commandId = mappingService.getCommandId(actionID); } if (commandId == null) { commandId = handler.getActionDefinitionId(); } // Update the handler activations. final IHandlerService service = serviceLocator.getService(IHandlerService.class); Map activationsByActionId = null; if (activationsByActionIdByServiceLocator == null) { activationsByActionIdByServiceLocator = new WeakHashMap<>(); activationsByActionId = new HashMap<>(); activationsByActionIdByServiceLocator.put(serviceLocator, activationsByActionId); } else { activationsByActionId = activationsByActionIdByServiceLocator.get(serviceLocator); if (activationsByActionId == null) { activationsByActionId = new HashMap<>(); activationsByActionIdByServiceLocator.put(serviceLocator, activationsByActionId); } else if (activationsByActionId.containsKey(actionID)) { final Object value = activationsByActionId.remove(actionID); if (value instanceof IHandlerActivation) { final IHandlerActivation activation = (IHandlerActivation) value; actionIdByCommandId.remove(activation.getCommandId()); if (service != null) { service.deactivateHandler(activation); } activation.getHandler().dispose(); } } else if (commandId != null && actionIdByCommandId.containsKey(commandId)) { final Object value = activationsByActionId.remove(actionIdByCommandId.remove(commandId)); if (value instanceof IHandlerActivation) { final IHandlerActivation activation = (IHandlerActivation) value; if (service != null) { service.deactivateHandler(activation); } activation.getHandler().dispose(); } } } if (commandId != null) { actionIdByCommandId.put(commandId, actionID); // Register this as a handler with the given definition id. // the expression gives the setGlobalActionHandler() a // priority. final IHandler actionHandler = new ActionHandler(handler); Expression handlerExpression = EXPRESSION; // XXX add new API in next release to avoid down-casting (bug 137091) if (this instanceof EditorActionBars) { handlerExpression = ((EditorActionBars) this).getHandlerExpression(); } if (service != null) { final IHandlerActivation activation = service.activateHandler(commandId, actionHandler, handlerExpression); activationsByActionId.put(actionID, activation); } } } } else { if (actionHandlers != null) { actionHandlers.remove(actionID); } // Remove the handler activation. if (serviceLocator != null) { final IHandlerService service = serviceLocator.getService(IHandlerService.class); if (activationsByActionIdByServiceLocator != null) { final Map activationsByActionId = activationsByActionIdByServiceLocator .get(serviceLocator); if ((activationsByActionId != null) && (activationsByActionId.containsKey(actionID))) { final Object value = activationsByActionId.remove(actionID); if (value instanceof IHandlerActivation) { final IHandlerActivation activation = (IHandlerActivation) value; actionIdByCommandId.remove(activation.getCommandId()); service.deactivateHandler(activation); activation.getHandler().dispose(); } } } } } actionHandlersChanged = true; } /** * Sets the service locator for this action bar. * * @param locator The new locator; must not be null. * * @since 3.2 */ protected final void setServiceLocator(final IServiceLocator locator) { if (locator == null) { throw new NullPointerException("The service locator cannot be null"); //$NON-NLS-1$ } this.serviceLocator = locator; } /** * Commits all UI changes. This should be called after additions or subtractions * have been made to a menu, status line, or toolbar. */ @Override public void updateActionBars() { parent.updateActionBars(); fireActionHandlersChanged(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy