org.eclipse.ui.internal.PopupMenuExtender Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of workbench Show documentation
Show all versions of workbench Show documentation
This plug-in contains the bulk of the Workbench implementation, and depends on JFace, SWT, and Core Runtime. It cannot be used independently from org.eclipse.ui. Workbench client plug-ins should not depend directly on this plug-in.
The newest version!
/*******************************************************************************
* 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
* Dan Rubel ([email protected]) - accessor to get menu id
*******************************************************************************/
package org.eclipse.ui.internal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionDelta;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IRegistryChangeEvent;
import org.eclipse.core.runtime.IRegistryChangeListener;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.ContributionManager;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener2;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.SubMenuManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.internal.menus.WindowMenuService;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.menus.IMenuService;
import org.eclipse.ui.menus.MenuUtil;
/**
* This class extends a single popup menu
*/
public class PopupMenuExtender implements IMenuListener2,
IRegistryChangeListener {
/**
* The bit in bitSet
that stores whether the static actions
* have been read from the registry.
*/
private static final int STATIC_ACTION_READ = 1;
/**
* The bit in bitSet
that stores whether the editor input
* should be included for the sake of object contributions.
*/
private static final int INCLUDE_EDITOR_INPUT = 1 << 1;
private final MenuManager menu;
private SubMenuManager menuWrapper;
private final ISelectionProvider selProvider;
private final IWorkbenchPart part;
private Map staticActionBuilders = null;
/**
* The boolean properties maintained by this extender. A bit set is used to
* save memory.
*/
private int bitSet = 0;
private ArrayList contributionCache = new ArrayList();
/**
* Construct a new menu extender.
*
* @param id
* the menu id
* @param menu
* the menu to extend
* @param prov
* the selection provider
* @param part
* the part to extend
*/
public PopupMenuExtender(String id, MenuManager menu,
ISelectionProvider prov, IWorkbenchPart part) {
this(id, menu, prov, part, true);
}
/**
* Construct a new menu extender.
*
* @param id
* the menu id
* @param menu
* the menu to extend
* @param prov
* the selection provider
* @param part
* the part to extend
* @param includeEditorInput
* Whether the editor input should be included when adding object
* contributions to this context menu.
*/
public PopupMenuExtender(final String id, final MenuManager menu,
final ISelectionProvider prov, final IWorkbenchPart part,
final boolean includeEditorInput) {
super();
this.menu = menu;
this.selProvider = prov;
this.part = part;
if (includeEditorInput) {
bitSet |= INCLUDE_EDITOR_INPUT;
}
menu.addMenuListener(this);
if (!menu.getRemoveAllWhenShown()) {
menuWrapper = new SubMenuManager(menu);
menuWrapper.setVisible(true);
}
readStaticActionsFor(id);
Platform.getExtensionRegistry().addRegistryChangeListener(this);
}
// getMenuId() added by Dan Rubel ([email protected])
/**
* Return the menu identifiers for this extender.
*
* @return The set of all identifiers that represent this extender.
*/
public Set getMenuIds() {
if (staticActionBuilders == null) {
return Collections.EMPTY_SET;
}
return staticActionBuilders.keySet();
}
/**
*
* Adds another menu identifier to this extender. An extender can represent
* many menu identifiers. These identifiers should represent the same menu
* manager, selection provider and part. Duplicate identifiers are
* automatically ignored.
*
*
* For example, it is necessary to filter out duplicate identifiers for
* CompilationUnitEditor
instances, as these define both
* "#CompilationUnitEditorContext"
and
* "org.eclipse.jdt.ui.CompilationUnitEditor.EditorContext"
* as menu identifier for the same pop-up menu. We don't want to contribute
* duplicate items in this case.
*
*
* @param menuId
* The menu identifier to add to this extender; should not be
* null
.
*/
public final void addMenuId(final String menuId) {
bitSet &= ~STATIC_ACTION_READ;
readStaticActionsFor(menuId);
}
/**
* Determines whether this extender would be the same as another extender
* created with the given values. Two extenders are equivalent if they have
* the same menu manager, selection provider and part (i.e., if the menu
* they represent is about to show, they would populate it with duplicate
* values).
*
* @param menuManager
* The menu manager with which to compare; may be
* null
.
* @param selectionProvider
* The selection provider with which to compare; may be
* null
.
* @param part
* The part with which to compare; may be null
.
* @return true
if the menu manager, selection provider and
* part are all the same.
*/
public final boolean matches(final MenuManager menuManager,
final ISelectionProvider selectionProvider,
final IWorkbenchPart part) {
return (this.menu == menuManager)
&& (this.selProvider == selectionProvider)
&& (this.part == part);
}
/**
* Contributes items registered for the currently active editor.
*/
private void addEditorActions(IMenuManager mgr) {
ISelectionProvider activeEditor = new ISelectionProvider() {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void addSelectionChangedListener(
ISelectionChangedListener listener) {
throw new UnsupportedOperationException(
"This ISelectionProvider is static, and cannot be modified."); //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
*/
public ISelection getSelection() {
if (part instanceof IEditorPart) {
final IEditorPart editorPart = (IEditorPart) part;
return new StructuredSelection(new Object[] { editorPart
.getEditorInput() });
}
return new StructuredSelection(new Object[0]);
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
*/
public void removeSelectionChangedListener(
ISelectionChangedListener listener) {
throw new UnsupportedOperationException(
"This ISelectionProvider is static, and cannot be modified."); //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
*/
public void setSelection(ISelection selection) {
throw new UnsupportedOperationException(
"This ISelectionProvider is static, and cannot be modified."); //$NON-NLS-1$
}
};
if (ObjectActionContributorManager.getManager()
.contributeObjectActions(part, mgr, activeEditor)) {
mgr.add(new Separator());
}
}
/**
* Contributes items registered for the object type(s) in
* the current selection.
*/
private void addObjectActions(IMenuManager mgr) {
if (selProvider != null) {
if (ObjectActionContributorManager.getManager()
.contributeObjectActions(part, mgr, selProvider)) {
mgr.add(new Separator());
}
}
}
/**
* Disposes all of the static actions.
*/
private final void clearStaticActions() {
bitSet &= ~STATIC_ACTION_READ;
if (staticActionBuilders != null) {
final Iterator staticActionBuilderItr = staticActionBuilders
.values().iterator();
while (staticActionBuilderItr.hasNext()) {
final Object staticActionBuilder = staticActionBuilderItr
.next();
if (staticActionBuilder instanceof ViewerActionBuilder) {
((ViewerActionBuilder) staticActionBuilder).dispose();
}
}
}
}
/**
* Adds static items to the context menu.
*/
private void addStaticActions(IMenuManager mgr) {
if (staticActionBuilders != null) {
final Iterator staticActionBuilderItr = staticActionBuilders
.values().iterator();
while (staticActionBuilderItr.hasNext()) {
final ViewerActionBuilder staticActionBuilder = (ViewerActionBuilder) staticActionBuilderItr
.next();
staticActionBuilder.contribute(mgr, null, true);
}
}
}
/**
* Notifies the listener that the menu is about to be shown.
*/
public void menuAboutToShow(IMenuManager mgr) {
IMenuManager originalManager = mgr;
// Add this menu as a visible menu.
final IWorkbenchPartSite site = part.getSite();
if (site != null) {
final IWorkbench workbench = site.getWorkbenchWindow()
.getWorkbench();
if (workbench instanceof Workbench) {
final Workbench realWorkbench = (Workbench) workbench;
ISelection input = null;
if ((bitSet & INCLUDE_EDITOR_INPUT) != 0) {
if (part instanceof IEditorPart) {
final IEditorPart editorPart = (IEditorPart) part;
input = new StructuredSelection(
new Object[] { editorPart.getEditorInput() });
}
}
ISelection s = (selProvider == null ? null : selProvider
.getSelection());
realWorkbench.addShowingMenus(getMenuIds(), s, input);
}
}
readStaticActions();
// test for additions removed to comply with menu contributions
if (menuWrapper != null) {
mgr = menuWrapper;
menuWrapper.removeAll();
}
addMenuContributions(originalManager);
if ((bitSet & INCLUDE_EDITOR_INPUT) != 0) {
addEditorActions(mgr);
}
addObjectActions(mgr);
addStaticActions(mgr);
cleanUpContributionCache();
}
private boolean contributionsPopulated = false;
private void addMenuContributions(IMenuManager mgr) {
final IMenuService menuService = (IMenuService) part.getSite()
.getService(IMenuService.class);
if (menuService == null) {
return;
}
if ((mgr.getRemoveAllWhenShown() || !contributionsPopulated)
&& mgr instanceof ContributionManager) {
ContributionManager manager = (ContributionManager) mgr;
contributionsPopulated = true;
menuService
.populateContributionManager(manager, MenuUtil.ANY_POPUP);
Iterator i = getMenuIds().iterator();
WindowMenuService realService = (WindowMenuService) menuService;
while (i.hasNext()) {
String id = "popup:" + i.next(); //$NON-NLS-1$
realService.populateContributionManager(manager, id, false);
}
}
}
/**
* Notifies the listener that the menu is about to be hidden.
*/
public final void menuAboutToHide(final IMenuManager mgr) {
gatherContributions(mgr);
// Remove this menu as a visible menu.
final IWorkbenchPartSite site = part.getSite();
if (site != null) {
final IWorkbench workbench = site.getWorkbenchWindow().getWorkbench();
if (workbench instanceof Workbench) {
// try delaying this until after the selection event
// has been fired.
// This is less threatening if the popup: menu
// contributions aren't tied to the evaluation service
workbench.getDisplay().asyncExec(new Runnable() {
public void run() {
final Workbench realWorkbench = (Workbench) workbench;
realWorkbench.removeShowingMenus(getMenuIds(), null, null);
}
});
}
}
}
/**
* @param mgr
*/
private void gatherContributions(final IMenuManager mgr) {
final IContributionItem[] items = mgr.getItems();
for (int i = 0; i < items.length; i++) {
if (items[i] instanceof PluginActionContributionItem) {
contributionCache.add(items[i]);
} else if (items[i] instanceof IMenuManager) {
gatherContributions(((IMenuManager)items[i]));
}
}
}
private void cleanUpContributionCache() {
PluginActionContributionItem[] items = (PluginActionContributionItem[]) contributionCache
.toArray(new PluginActionContributionItem[contributionCache.size()]);
contributionCache.clear();
for (int i = 0; i < items.length; i++) {
items[i].dispose();
}
}
/**
* Read all of the static items for the content menu.
*/
private final void readStaticActions() {
if (staticActionBuilders != null) {
final Iterator menuIdItr = staticActionBuilders.keySet().iterator();
while (menuIdItr.hasNext()) {
final String menuId = (String) menuIdItr.next();
readStaticActionsFor(menuId);
}
}
}
/**
* Read static items for a particular menu id, into the context menu.
*/
private void readStaticActionsFor(final String menuId) {
if ((bitSet & STATIC_ACTION_READ) != 0) {
return;
}
bitSet |= STATIC_ACTION_READ;
// If no menu id provided, then there is no contributions
// to add. Fix for bug #33140.
if ((menuId == null) || (menuId.length() < 1)) {
return;
}
if (staticActionBuilders == null) {
staticActionBuilders = new HashMap();
}
Object object = staticActionBuilders.get(menuId);
if (!(object instanceof ViewerActionBuilder)) {
object = new ViewerActionBuilder();
staticActionBuilders.put(menuId, object);
}
final ViewerActionBuilder staticActionBuilder = (ViewerActionBuilder) object;
staticActionBuilder.readViewerContributions(menuId, selProvider, part);
}
/**
* Dispose of the menu extender. Should only be called when the part
* is disposed.
*/
public void dispose() {
clearStaticActions();
final IMenuService menuService = (IMenuService) part.getSite()
.getService(IMenuService.class);
if (menuService != null) {
menuService.releaseContributions(menu);
}
Platform.getExtensionRegistry().removeRegistryChangeListener(this);
menu.removeMenuListener(this);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.IRegistryChangeListener#registryChanged(org.eclipse.core.runtime.IRegistryChangeEvent)
*/
public void registryChanged(final IRegistryChangeEvent event) {
Display display = Display.getDefault();
if (part != null) {
display = part.getSite().getPage().getWorkbenchWindow().getWorkbench().getDisplay();
}
//check the delta to see if there are any viewer contribution changes. if so, null our builder to cause reparsing on the next menu show
IExtensionDelta [] deltas = event.getExtensionDeltas();
for (int i = 0; i < deltas.length; i++) {
IExtensionDelta delta = deltas[i];
IExtensionPoint extensionPoint = delta.getExtensionPoint();
if (extensionPoint.getNamespace().equals(
WorkbenchPlugin.PI_WORKBENCH)
&& extensionPoint.getSimpleIdentifier().equals(
IWorkbenchRegistryConstants.PL_POPUP_MENU)) {
boolean clearPopups = false;
IConfigurationElement [] elements = delta.getExtension().getConfigurationElements();
for (int j = 0; j < elements.length; j++) {
IConfigurationElement element = elements[j];
if (element.getName().equals(IWorkbenchRegistryConstants.TAG_VIEWER_CONTRIBUTION)) {
clearPopups = true;
break;
}
}
if (clearPopups) {
display.syncExec(new Runnable() {
public void run() {
clearStaticActions();
}
});
}
}
}
}
public MenuManager getManager() {
return menu;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy