blob: 6928f293642b63c856810579dc2c52b1287b9ff5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 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.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.ContributionManager;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISourceProvider;
import org.eclipse.ui.ISources;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.internal.services.IWorkbenchLocationService;
import org.eclipse.ui.internal.services.WorkbenchSourceProvider;
import org.eclipse.ui.internal.util.Util;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.menus.IMenuService;
import org.eclipse.ui.menus.IWorkbenchContribution;
import org.eclipse.ui.menus.MenuUtil;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.part.ShowInContext;
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.ui.services.ISourceProviderService;
import org.eclipse.ui.views.IViewDescriptor;
import org.eclipse.ui.views.IViewRegistry;
/**
* A <code>ShowInMenu</code> is used to populate a menu manager with Show In
* actions. The items to show are determined from the active perspective and
* active part.
*/
public class ShowInMenu extends ContributionItem implements
IWorkbenchContribution {
// RAP [rh] Cannot reference NLS message from static field
// private static final String NO_TARGETS_MSG = WorkbenchMessages.Workbench_showInNoTargets;
private final String NO_TARGETS_MSG = WorkbenchMessages.get().Workbench_showInNoTargets;
private IWorkbenchWindow window;
private Map actions = new HashMap(21);
private boolean dirty = true;
private IMenuListener menuListener = new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
manager.markDirty();
dirty = true;
}
};
private IServiceLocator locator;
private MenuManager currentManager;
public ShowInMenu() {
}
/**
* Creates a Show In menu.
*
* @param window
* the window containing the menu
* @param id
* The ID for this contribution
*/
public ShowInMenu(IWorkbenchWindow window, String id) {
super(id);
this.window = window;
}
public boolean isDirty() {
return dirty;
}
/**
* Overridden to always return true and force dynamic menu building.
*/
public boolean isDynamic() {
return true;
}
public void fill(Menu menu, int index) {
if (getParent() instanceof MenuManager) {
((MenuManager) getParent()).addMenuListener(menuListener);
}
if (!dirty) {
return;
}
if (currentManager!=null && currentManager.getSize() > 0) {
IMenuService service = (IMenuService) locator
.getService(IMenuService.class);
service.releaseContributions(currentManager);
currentManager.removeAll();
}
currentManager = new MenuManager();
fillMenu(currentManager);
IContributionItem[] items = currentManager.getItems();
if (items.length == 0) {
MenuItem item = new MenuItem(menu, SWT.NONE, index++);
item.setText(NO_TARGETS_MSG);
item.setEnabled(false);
} else {
for (int i = 0; i < items.length; i++) {
if (items[i].isVisible()) {
items[i].fill(menu, index++);
}
}
}
dirty = false;
}
/**
* Fills the menu with Show In actions.
*/
private void fillMenu(IMenuManager innerMgr) {
// Remove all.
innerMgr.removeAll();
IWorkbenchPart sourcePart = getSourcePart();
if (sourcePart == null) {
return;
}
ShowInContext context = getContext(sourcePart);
if (context == null) {
return;
}
if (context.getInput() == null
&& (context.getSelection() == null || context.getSelection()
.isEmpty())) {
return;
}
IViewDescriptor[] viewDescs = getViewDescriptors(sourcePart);
for (int i = 0; i < viewDescs.length; ++i) {
IContributionItem cci = getContributionItem(viewDescs[i]);
if (cci != null) {
innerMgr.add(cci);
}
}
if (innerMgr instanceof MenuManager) {
ISourceProviderService sps = (ISourceProviderService) locator
.getService(ISourceProviderService.class);
ISourceProvider sp = sps
.getSourceProvider(ISources.SHOW_IN_SELECTION);
if (sp instanceof WorkbenchSourceProvider) {
((WorkbenchSourceProvider) sp).checkActivePart(true);
}
IMenuService service = (IMenuService) locator
.getService(IMenuService.class);
service.populateContributionManager((ContributionManager) innerMgr,
MenuUtil.SHOW_IN_MENU_ID);
}
}
/**
* Return the appropriate command contribution item for the parameter.
* @param viewDescriptor
* @return the show in command contribution item
*/
private IContributionItem getContributionItem(IViewDescriptor viewDescriptor) {
CommandContributionItemParameter parm = new CommandContributionItemParameter(
locator, viewDescriptor.getId(), IWorkbenchCommandConstants.NAVIGATE_SHOW_IN,
CommandContributionItem.STYLE_PUSH);
HashMap targetId = new HashMap();
targetId.put(IWorkbenchCommandConstants.NAVIGATE_SHOW_IN_PARM_TARGET,
viewDescriptor.getId());
parm.parameters = targetId;
parm.label = viewDescriptor.getLabel();
if (parm.label.length() > 0) {
parm.mnemonic = parm.label.substring(0, 1);
}
parm.icon = viewDescriptor.getImageDescriptor();
return new CommandContributionItem(parm);
}
/**
* Returns the Show In... target part ids for the given source part. Merges
* the contributions from the current perspective and the source part.
*/
private ArrayList getShowInPartIds(IWorkbenchPart sourcePart) {
ArrayList targetIds = new ArrayList();
WorkbenchPage page = (WorkbenchPage) getWindow().getActivePage();
if (page != null) {
targetIds.addAll(page.getShowInPartIds());
}
IShowInTargetList targetList = getShowInTargetList(sourcePart);
if (targetList != null) {
String[] partIds = targetList.getShowInTargetIds();
if (partIds != null) {
for (int i = 0; i < partIds.length; ++i) {
if (!targetIds.contains(partIds[i])) {
targetIds.add(partIds[i]);
}
}
}
}
page.sortShowInPartIds(targetIds);
return targetIds;
}
/**
* Returns the source part, or <code>null</code> if there is no applicable
* source part
* <p>
* This implementation returns the current part in the window. Subclasses
* may extend or reimplement.
*
* @return the source part or <code>null</code>
*/
private IWorkbenchPart getSourcePart() {
IWorkbenchWindow window = getWindow();
if(window == null) return null;
IWorkbenchPage page = window.getActivePage();
if (page != null) {
return page.getActivePart();
}
return null;
}
/**
* Returns the <code>IShowInSource</code> provided by the source part, or
* <code>null</code> if it does not provide one.
*
* @param sourcePart
* the source part
* @return an <code>IShowInSource</code> or <code>null</code>
*/
private IShowInSource getShowInSource(IWorkbenchPart sourcePart) {
return (IShowInSource) Util.getAdapter(sourcePart, IShowInSource.class);
}
/**
* Returns the <code>IShowInTargetList</code> for the given source part,
* or <code>null</code> if it does not provide one.
*
* @param sourcePart
* the source part
* @return the <code>IShowInTargetList</code> or <code>null</code>
*/
private IShowInTargetList getShowInTargetList(IWorkbenchPart sourcePart) {
return (IShowInTargetList) Util.getAdapter(sourcePart,
IShowInTargetList.class);
}
/**
* Returns the <code>ShowInContext</code> to show in the selected target,
* or <code>null</code> if there is no valid context to show.
* <p>
* This implementation obtains the context from the
* <code>IShowInSource</code> of the source part (if provided), or, if the
* source part is an editor, it creates the context from the editor's input
* and selection.
* <p>
* Subclasses may extend or reimplement.
*
* @return the <code>ShowInContext</code> to show or <code>null</code>
*/
private ShowInContext getContext(IWorkbenchPart sourcePart) {
IShowInSource source = getShowInSource(sourcePart);
if (source != null) {
ShowInContext context = source.getShowInContext();
if (context != null) {
return context;
}
} else if (sourcePart instanceof IEditorPart) {
Object input = ((IEditorPart) sourcePart).getEditorInput();
ISelectionProvider sp = sourcePart.getSite().getSelectionProvider();
ISelection sel = sp == null ? null : sp.getSelection();
return new ShowInContext(input, sel);
}
return null;
}
/**
* Returns the view descriptors to show in the dialog.
*/
private IViewDescriptor[] getViewDescriptors(IWorkbenchPart sourcePart) {
String srcId = sourcePart.getSite().getId();
ArrayList ids = getShowInPartIds(sourcePart);
ArrayList descs = new ArrayList();
IViewRegistry reg = WorkbenchPlugin.getDefault().getViewRegistry();
for (Iterator i = ids.iterator(); i.hasNext();) {
String id = (String) i.next();
if (!id.equals(srcId)) {
IViewDescriptor desc = reg.find(id);
if (desc != null) {
descs.add(desc);
}
}
}
return (IViewDescriptor[]) descs.toArray(new IViewDescriptor[descs
.size()]);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.menus.IWorkbenchContribution#initialize(org.eclipse.ui.services.IServiceLocator)
*/
public void initialize(IServiceLocator serviceLocator) {
locator = serviceLocator;
}
protected IWorkbenchWindow getWindow() {
if(locator == null) return null;
IWorkbenchLocationService wls = (IWorkbenchLocationService) locator
.getService(IWorkbenchLocationService.class);
if (window == null) {
window = wls.getWorkbenchWindow();
}
if (window == null) {
IWorkbench wb = wls.getWorkbench();
if (wb != null) {
window = wb.getActiveWorkbenchWindow();
}
}
return window;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.ContributionItem#dispose()
*/
public void dispose() {
if (currentManager != null && currentManager.getSize() > 0) {
IMenuService service = (IMenuService) locator
.getService(IMenuService.class);
if (service != null) {
service.releaseContributions(currentManager);
}
currentManager.removeAll();
currentManager = null;
}
if (getParent() instanceof MenuManager) {
((MenuManager) getParent()).removeMenuListener(menuListener);
}
actions.clear();
window=null;
locator=null;
}
}