| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.internal; |
| |
| import org.eclipse.core.expressions.Expression; |
| import org.eclipse.jface.action.ActionContributionItem; |
| import org.eclipse.jface.action.ContributionManager; |
| import org.eclipse.jface.action.GroupMarker; |
| import org.eclipse.jface.action.IContributionItem; |
| import org.eclipse.jface.action.IContributionManager; |
| import org.eclipse.jface.action.IContributionManagerOverrides; |
| import org.eclipse.jface.action.ICoolBarManager; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.IToolBarManager; |
| import org.eclipse.jface.action.SubContributionManager; |
| import org.eclipse.jface.action.SubCoolBarManager; |
| import org.eclipse.jface.action.SubMenuManager; |
| import org.eclipse.jface.action.SubStatusLineManager; |
| import org.eclipse.jface.action.SubToolBarManager; |
| import org.eclipse.jface.internal.provisional.action.IToolBarContributionItem; |
| import org.eclipse.jface.internal.provisional.action.ToolBarContributionItem2; |
| import org.eclipse.jface.internal.provisional.action.ToolBarManager2; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.ui.IActionBars2; |
| import org.eclipse.ui.IEditorActionBarContributor; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IWorkbenchActionConstants; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.SubActionBars2; |
| import org.eclipse.ui.actions.RetargetAction; |
| import org.eclipse.ui.internal.expressions.LegacyEditorActionBarExpression; |
| import org.eclipse.ui.internal.misc.Policy; |
| import org.eclipse.ui.services.IServiceLocator; |
| |
| /** |
| * The action bars for an editor. |
| */ |
| public class EditorActionBars extends SubActionBars2 { |
| |
| private class Overrides implements IContributionManagerOverrides { |
| |
| @Override |
| public Integer getAccelerator(IContributionItem item) { |
| return null; |
| } |
| |
| @Override |
| public String getAcceleratorText(IContributionItem item) { |
| return null; |
| } |
| |
| @Override |
| public Boolean getEnabled(IContributionItem item) { |
| if (((item instanceof ActionContributionItem) |
| && (((ActionContributionItem) item).getAction() instanceof RetargetAction)) || enabledAllowed) { |
| return null; |
| } |
| return Boolean.FALSE; |
| } |
| |
| @Override |
| public String getText(IContributionItem item) { |
| return null; |
| } |
| |
| @Override |
| public Boolean getVisible(IContributionItem item) { |
| return null; |
| } |
| } |
| |
| /** |
| * A switch controlling verbose debugging options surrounding the disposal of |
| * tool bar contribution items. There have been problems in the past with |
| * reusing disposed items, and leaking memory by failing to drop references to |
| * disposed items. |
| */ |
| private static final boolean DEBUG_TOOLBAR_DISPOSAL = Policy.DEBUG_TOOLBAR_DISPOSAL; |
| |
| private IToolBarManager coolItemToolBarMgr = null; |
| |
| private IEditorActionBarContributor editorContributor; |
| |
| private boolean enabledAllowed = false; |
| |
| private IEditorActionBarContributor extensionContributor; |
| |
| private int refCount; |
| |
| private IToolBarContributionItem toolBarContributionItem = null; |
| |
| private String type; |
| |
| private WorkbenchPage page; |
| |
| /** |
| * Constructs the EditorActionBars for an editor. |
| */ |
| public EditorActionBars(WorkbenchPage page, final IServiceLocator serviceLocator, String type) { |
| super((IActionBars2) page.getActionBars(), serviceLocator); |
| this.page = page; |
| this.type = type; |
| } |
| |
| public WorkbenchPage getPage() { |
| return page; |
| } |
| |
| /** |
| * Activate the contributions. |
| */ |
| @Override |
| public void activate(boolean forceVisibility) { |
| setActive(true, forceVisibility); |
| } |
| |
| /** |
| * Add one ref to the bars. |
| */ |
| public void addRef() { |
| ++refCount; |
| } |
| |
| @Override |
| protected SubMenuManager createSubMenuManager(IMenuManager parent) { |
| return new EditorMenuManager(parent); |
| } |
| |
| @Override |
| protected SubToolBarManager createSubToolBarManager(IToolBarManager parent) { |
| // return null, editor actions are managed by CoolItemToolBarManagers |
| return null; |
| } |
| |
| /** |
| * Deactivate the contributions. |
| */ |
| @Override |
| public void deactivate(boolean forceVisibility) { |
| setActive(false, forceVisibility); |
| } |
| |
| /** |
| * Dispose the contributions. |
| */ |
| @Override |
| public void dispose() { |
| if (editorContributor != null) { |
| editorContributor.dispose(); |
| } |
| if (extensionContributor != null) { |
| extensionContributor.dispose(); |
| } |
| |
| /* |
| * Dispose of the contribution item, but also make sure that no one else is |
| * holding on to it. In this case, go through the SubCoolBarManager to its |
| * parent (the real CoolBarManager), and replace the reference with a |
| * placeholder. |
| */ |
| if (toolBarContributionItem != null) { |
| // Create a placeholder and place it in the cool bar manager. |
| ICoolBarManager coolBarManager = getCoolBarManager(); |
| if (coolBarManager instanceof SubContributionManager) { |
| SubContributionManager subManager = (SubContributionManager) coolBarManager; |
| IContributionManager manager = subManager.getParent(); |
| if (manager instanceof CoolBarToTrimManager) { |
| CoolBarToTrimManager trimManager = (CoolBarToTrimManager) manager; |
| trimManager.remove(toolBarContributionItem); |
| } else if (manager instanceof ContributionManager) { |
| final IContributionItem replacementItem = new PlaceholderContributionItem(toolBarContributionItem); |
| boolean succeeded = ((ContributionManager) manager).replaceItem(replacementItem.getId(), |
| replacementItem); |
| if (!succeeded && DEBUG_TOOLBAR_DISPOSAL) { |
| System.out.println("FAILURE WHILE DISPOSING EditorActionBars"); //$NON-NLS-1$ |
| System.out.println( |
| "Could not replace " + replacementItem.getId() + " in the contribution manager."); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } else if (DEBUG_TOOLBAR_DISPOSAL) { |
| System.out.println("FAILURE WHILE DISPOSING EditorActionBars"); //$NON-NLS-1$ |
| System.out.println("The manager was not a ContributionManager."); //$NON-NLS-1$ |
| System.out.println("It was a " + manager.getClass().getName()); //$NON-NLS-1$ |
| } |
| } else if (DEBUG_TOOLBAR_DISPOSAL) { |
| System.out.println("FAILURE WHILE DISPOSING EditorActionBars"); //$NON-NLS-1$ |
| System.out.println("The coolBarManager was not a SubContributionManager"); //$NON-NLS-1$ |
| System.out.println("It was a " + coolBarManager.getClass().getName()); //$NON-NLS-1$ |
| } |
| |
| // Dispose of the replaced item. |
| toolBarContributionItem.dispose(); |
| } |
| toolBarContributionItem = null; |
| // Remove actions |
| if (coolItemToolBarMgr != null) { |
| coolItemToolBarMgr.removeAll(); |
| } |
| coolItemToolBarMgr = null; |
| editorHandlerExpression = null; |
| super.dispose(); |
| } |
| |
| /** |
| * Gets the editor contributor |
| */ |
| public IEditorActionBarContributor getEditorContributor() { |
| return editorContributor; |
| } |
| |
| /** |
| * Returns the editor type. |
| */ |
| public String getEditorType() { |
| return type; |
| } |
| |
| /** |
| * Gets the extension contributor |
| */ |
| public IEditorActionBarContributor getExtensionContributor() { |
| return extensionContributor; |
| } |
| |
| /** |
| * Returns the reference count. |
| */ |
| public int getRef() { |
| return refCount; |
| } |
| |
| /** |
| * Returns the tool bar manager. If items are added or removed from the manager |
| * be sure to call <code>updateActionBars</code>. Overridden to support |
| * CoolBars. |
| * |
| * @return the tool bar manager |
| */ |
| @Override |
| public IToolBarManager getToolBarManager() { |
| |
| // by pass the sub coolBar and use the real cool bar. |
| ICoolBarManager coolBarManager = getCastedParent().getCoolBarManager(); |
| if (coolBarManager == null) { |
| return null; |
| } |
| |
| // add the editor group if the app did not add it already, |
| // otherwise the references to it below will fail |
| if (coolBarManager.find(IWorkbenchActionConstants.GROUP_EDITOR) == null) { |
| coolBarManager.add(new GroupMarker(IWorkbenchActionConstants.GROUP_EDITOR)); |
| } |
| if (toolBarContributionItem == null) { |
| IContributionItem foundItem = coolBarManager.find(type); |
| if ((foundItem instanceof IToolBarContributionItem)) { |
| toolBarContributionItem = (IToolBarContributionItem) foundItem; |
| coolItemToolBarMgr = toolBarContributionItem.getToolBarManager(); |
| if (coolItemToolBarMgr == null) { |
| coolItemToolBarMgr = new ToolBarManager2(SWT.FLAT); |
| toolBarContributionItem = new ToolBarContributionItem2(coolItemToolBarMgr, type); |
| // Add editor item to group |
| coolBarManager.prependToGroup(IWorkbenchActionConstants.GROUP_EDITOR, toolBarContributionItem); |
| } |
| } else { |
| coolItemToolBarMgr = new ToolBarManager2(SWT.FLAT); |
| if ((coolBarManager instanceof ContributionManager) |
| && (foundItem instanceof PlaceholderContributionItem)) { |
| PlaceholderContributionItem placeholder = (PlaceholderContributionItem) foundItem; |
| toolBarContributionItem = createToolBarContributionItem(coolItemToolBarMgr, placeholder); |
| // Restore from a placeholder |
| ((ContributionManager) coolBarManager).replaceItem(type, toolBarContributionItem); |
| } else { |
| toolBarContributionItem = new ToolBarContributionItem2(coolItemToolBarMgr, type); |
| // Add editor item to group |
| coolBarManager.prependToGroup(IWorkbenchActionConstants.GROUP_EDITOR, toolBarContributionItem); |
| } |
| } |
| ((ContributionManager) coolItemToolBarMgr).setOverrides(new Overrides()); |
| toolBarContributionItem.setVisible(getActive()); |
| coolItemToolBarMgr.markDirty(); |
| } |
| |
| return coolItemToolBarMgr; |
| } |
| |
| /* |
| * Creates a new tool bar contribution item on the given manager -- using the |
| * stored data to initialize some of its properties. |
| */ |
| IToolBarContributionItem createToolBarContributionItem(final IToolBarManager manager, |
| PlaceholderContributionItem item) { |
| IToolBarContributionItem toolBarContributionItem = new ToolBarContributionItem2(manager, item.getId()); |
| toolBarContributionItem.setCurrentHeight(item.getHeight()); |
| toolBarContributionItem.setCurrentWidth(item.getWidth()); |
| toolBarContributionItem.setMinimumItemsToShow(item.getMinimumItemsToShow()); |
| toolBarContributionItem.setUseChevron(item.getUseChevron()); |
| return toolBarContributionItem; |
| } |
| |
| /** |
| * Returns whether the contribution list is visible. If the visibility is |
| * <code>true</code> then each item within the manager appears within the parent |
| * manager. Otherwise, the items are not visible. |
| * |
| * @return <code>true</code> if the manager is visible |
| */ |
| private boolean isVisible() { |
| if (toolBarContributionItem != null) { |
| return toolBarContributionItem.isVisible(); |
| } |
| return false; |
| } |
| |
| /** |
| * Sets the target part for the action bars. For views this is ignored because |
| * each view has its own action vector. For editors this is important because |
| * the action vector is shared by editors of the same type. |
| */ |
| @Override |
| public void partChanged(IWorkbenchPart part) { |
| super.partChanged(part); |
| if (part instanceof IEditorPart) { |
| IEditorPart editor = (IEditorPart) part; |
| if (editorContributor != null) { |
| editorContributor.setActiveEditor(editor); |
| } |
| if (extensionContributor != null) { |
| extensionContributor.setActiveEditor(editor); |
| } |
| } |
| } |
| |
| /** |
| * Remove one ref to the bars. |
| */ |
| public void removeRef() { |
| --refCount; |
| } |
| |
| /** |
| * Activate / Deactivate the contributions. |
| * |
| * Workaround for flashing when editor contributes many menu/tool contributions. |
| * In this case, the force visibility flag determines if the contributions |
| * should be actually made visible/hidden or just change the enablement state. |
| */ |
| private void setActive(boolean set, boolean forceVisibility) { |
| basicSetActive(set); |
| if (isSubMenuManagerCreated()) { |
| ((EditorMenuManager) getMenuManager()).setVisible(set, forceVisibility); |
| } |
| |
| if (isSubStatusLineManagerCreated()) { |
| ((SubStatusLineManager) getStatusLineManager()).setVisible(set); |
| } |
| |
| setVisible(set, forceVisibility); |
| } |
| |
| /** |
| * Sets the editor contributor |
| */ |
| public void setEditorContributor(IEditorActionBarContributor c) { |
| editorContributor = c; |
| } |
| |
| /** |
| * Sets the enablement ability of all the items contributed by the editor. |
| * |
| * @param enabledAllowed <code>true</code> if the items may enable |
| * @since 2.0 |
| */ |
| private void setEnabledAllowed(boolean enabledAllowed) { |
| if (this.enabledAllowed == enabledAllowed) { |
| return; |
| } |
| this.enabledAllowed = enabledAllowed; |
| if (coolItemToolBarMgr != null) { |
| for (IContributionItem item : coolItemToolBarMgr.getItems()) { |
| if (item != null) { |
| item.update(IContributionManagerOverrides.P_ENABLED); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Sets the extension contributor |
| */ |
| public void setExtensionContributor(IEditorActionBarContributor c) { |
| extensionContributor = c; |
| } |
| |
| /** |
| * Sets the visibility of the manager. If the visibility is <code>true</code> |
| * then each item within the manager appears within the parent manager. |
| * Otherwise, the items are not visible. |
| * |
| * @param visible the new visibility |
| */ |
| private void setVisible(boolean visible) { |
| if (toolBarContributionItem != null) { |
| toolBarContributionItem.setVisible(visible); |
| if (toolBarContributionItem.getParent() != null) { |
| toolBarContributionItem.getParent().markDirty(); |
| } |
| } |
| } |
| |
| /** |
| * Sets the visibility of the manager. If the visibility is <code>true</code> |
| * then each item within the manager appears within the parent manager. |
| * Otherwise, the items are not visible if force visibility is |
| * <code>true</code>, or grayed out if force visibility is <code>false</code> |
| * <p> |
| * This is a workaround for the layout flashing when editors contribute large |
| * amounts of items. |
| * </p> |
| * |
| * @param visible the new visibility |
| * @param forceVisibility <code>true</code> to change the visibility or |
| * <code>false</code> to change just the enablement |
| * state. This parameter is ignored if visible is |
| * <code>true</code>. |
| */ |
| private void setVisible(boolean visible, boolean forceVisibility) { |
| if (visible) { |
| setEnabledAllowed(true); |
| if (!isVisible()) { |
| setVisible(true); |
| } |
| } else if (forceVisibility) { |
| // Remove the editor tool bar items |
| setVisible(false); |
| } else { |
| // Disabled the tool bar items. |
| setEnabledAllowed(false); |
| } |
| |
| IActionBars2 castedParent = getCastedParent(); |
| if (castedParent == null) { |
| return; |
| } |
| ICoolBarManager coolBarManager = castedParent.getCoolBarManager(); |
| if ((coolItemToolBarMgr != null) && (coolBarManager != null)) { |
| for (IContributionItem item : coolItemToolBarMgr.getItems()) { |
| item.setVisible(visible || !forceVisibility); |
| coolItemToolBarMgr.markDirty(); |
| if (!coolBarManager.isDirty()) { |
| coolBarManager.markDirty(); |
| } |
| } |
| // Update the manager |
| coolItemToolBarMgr.update(false); |
| if (toolBarContributionItem != null) { |
| toolBarContributionItem.setVisible(visible || !forceVisibility); |
| } |
| if (getCoolBarManager() != null) { |
| ((SubCoolBarManager) getCoolBarManager()).setVisible(visible || !forceVisibility); |
| } |
| } |
| } |
| |
| private LegacyEditorActionBarExpression editorHandlerExpression = null; |
| |
| /** |
| * Returns the expression used for action handler activation. |
| * |
| * @return the expression used for action handler activation. |
| */ |
| public Expression getHandlerExpression() { |
| if (editorHandlerExpression == null) { |
| editorHandlerExpression = new LegacyEditorActionBarExpression(type); |
| } |
| return editorHandlerExpression; |
| } |
| } |