blob: c1adbea268d5ea07ae10232ac3bf0a70c4ab8db9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 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
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 440810, 444070, 472654
* Simon Scholz <simon.scholz@vogella.com> - Bug 451214
*******************************************************************************/
package org.eclipse.ui.internal;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.e4.core.commands.ExpressionContext;
import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.commands.MCommand;
import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl;
import org.eclipse.jface.action.ContributionItem;
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.resource.ImageDescriptor;
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.commands.ICommandImageService;
import org.eclipse.ui.internal.services.IWorkbenchLocationService;
import org.eclipse.ui.internal.services.WorkbenchSourceProvider;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
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 {
private static final String NO_TARGETS_MSG = WorkbenchMessages.Workbench_showInNoTargets;
private IWorkbenchWindow window;
private boolean dirty = true;
private IMenuListener menuListener = 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;
}
@Override
public boolean isDirty() {
return dirty;
}
/**
* Overridden to always return true and force dynamic menu building.
*/
@Override
public boolean isDynamic() {
return true;
}
@Override
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);
int itemCount = menu.getItemCount();
IContributionItem[] items = currentManager.getItems();
if (items.length == 0) {
MenuItem item = new MenuItem(menu, SWT.NONE, index == -1 ? itemCount : index);
item.setText(NO_TARGETS_MSG);
item.setEnabled(false);
} else {
for (IContributionItem item : items) {
if (item.isVisible()) {
if (index == -1) {
item.fill(menu, -1);
} else {
item.fill(menu, index);
int newItemCount = menu.getItemCount();
index += newItemCount - itemCount;
itemCount = newItemCount;
}
}
}
}
dirty = false;
}
/**
* Fills the menu with Show In actions.
*/
private void fillMenu(IMenuManager innerMgr) {
IWorkbenchPage page = locator.getService(IWorkbenchPage.class);
if (page == null) {
return;
}
WorkbenchPartReference r = (WorkbenchPartReference) page.getActivePartReference();
if (page != null && r != null && r.getModel() != null) {
((WorkbenchPage) page).updateShowInSources(r.getModel());
}
// Remove all.
innerMgr.removeAll();
IWorkbenchPart sourcePart = getSourcePart();
ShowInContext context = getContext(sourcePart);
if (context == null) {
return;
}
if (context.getInput() == null
&& (context.getSelection() == null || context.getSelection()
.isEmpty())) {
return;
}
IViewDescriptor[] viewDescs = getViewDescriptors(sourcePart);
for (IViewDescriptor viewDesc : viewDescs) {
IContributionItem cci = getContributionItem(viewDesc);
if (cci != null) {
innerMgr.add(cci);
}
}
if (sourcePart != null && innerMgr instanceof MenuManager) {
ISourceProviderService sps = locator
.getService(ISourceProviderService.class);
ISourceProvider sp = sps
.getSourceProvider(ISources.SHOW_IN_SELECTION);
if (sp instanceof WorkbenchSourceProvider) {
((WorkbenchSourceProvider) sp).checkActivePart(true);
}
// add contributions targeting popup:org.eclipse.ui.menus.showInMenu
String location = MenuUtil.SHOW_IN_MENU_ID;
location = location.substring(location.indexOf(':') + 1);
WorkbenchWindow workbenchWindow = (WorkbenchWindow) getWindow();
MApplication application = workbenchWindow.getModel().getContext()
.get(MApplication.class);
MMenu menuModel = MenuFactoryImpl.eINSTANCE.createMenu();
final ArrayList<MMenuContribution> toContribute = new ArrayList<>();
final ArrayList<MMenuElement> menuContributionsToRemove = new ArrayList<>();
ExpressionContext eContext = new ExpressionContext(workbenchWindow.getModel()
.getContext());
ContributionsAnalyzer.gatherMenuContributions(menuModel,
application.getMenuContributions(), location, toContribute, eContext, true);
ContributionsAnalyzer.addMenuContributions(menuModel, toContribute,
menuContributionsToRemove);
ICommandImageService imgService = workbenchWindow.getService(ICommandImageService.class);
for (MMenuElement menuElement : menuModel.getChildren()) {
if (menuElement instanceof MHandledMenuItem) {
MCommand command = ((MHandledMenuItem) menuElement).getCommand();
String commandId = command.getElementId();
CommandContributionItemParameter ccip = new CommandContributionItemParameter(
workbenchWindow, commandId, commandId,
CommandContributionItem.STYLE_PUSH);
String label = menuElement.getLabel();
if (label != null && label.length() > 0) {
ccip.label = label;
String mnemonics = menuElement.getMnemonics();
if (mnemonics != null && mnemonics.length() == 1) {
ccip.mnemonic = mnemonics;
} else {
ccip.mnemonic = label.substring(0, 1);
}
}
String iconURI = menuElement.getIconURI();
try {
if (iconURI != null && !iconURI.isEmpty()) {
ccip.icon = ImageDescriptor.createFromURL(new URL(iconURI));
} else {
ccip.icon = imgService.getImageDescriptor(commandId);
}
} catch (MalformedURLException e) {
ccip.icon = imgService.getImageDescriptor(commandId);
}
innerMgr.add(new CommandContributionItem(ccip));
}
}
}
}
/**
* Return the appropriate command contribution item for the parameter.
* @param viewDescriptor
* @return the show in command contribution item
*/
protected IContributionItem getContributionItem(IViewDescriptor viewDescriptor) {
CommandContributionItemParameter parm = new CommandContributionItemParameter(
locator, viewDescriptor.getId(), IWorkbenchCommandConstants.NAVIGATE_SHOW_IN,
CommandContributionItem.STYLE_PUSH);
HashMap<String, String> 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<Object> getShowInPartIds(IWorkbenchPart sourcePart) {
ArrayList<Object> targetIds = new ArrayList<>();
WorkbenchPage page = (WorkbenchPage) getWindow().getActivePage();
if (page != null) {
String srcId = sourcePart == null ? null : sourcePart.getSite().getId();
ArrayList<?> pagePartIds = page.getShowInPartIds();
for (Object pagePartId : pagePartIds) {
// Don't add own view, except when explicitly requested with
// IShowInTargetList below
if (!pagePartId.equals(srcId)) {
targetIds.add(pagePartId);
}
}
}
IShowInTargetList targetList = Adapters.adapt(sourcePart, IShowInTargetList.class);
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>
*/
protected IWorkbenchPart getSourcePart() {
IWorkbenchWindow window = getWindow();
if (window == null)
return null;
IWorkbenchPage page = window.getActivePage();
return page != null ? page.getActivePart() : null;
}
/**
* 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>
*/
protected ShowInContext getContext(IWorkbenchPart sourcePart) {
if (sourcePart != null) {
IShowInSource source = Adapters.adapt(sourcePart, IShowInSource.class);
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) {
ArrayList<Object> ids = getShowInPartIds(sourcePart);
ArrayList<IViewDescriptor> descs = new ArrayList<>();
IViewRegistry reg = WorkbenchPlugin.getDefault().getViewRegistry();
for (Object object : ids) {
String id = (String) object;
IViewDescriptor desc = reg.find(id);
if (desc != null) {
descs.add(desc);
}
}
return descs.toArray(new IViewDescriptor[descs
.size()]);
}
@Override
public void initialize(IServiceLocator serviceLocator) {
locator = serviceLocator;
}
protected IWorkbenchWindow getWindow() {
if (locator == null)
return null;
IWorkbenchLocationService wls = 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;
}
@Override
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);
}
window=null;
locator=null;
}
}