| /******************************************************************************* |
| * 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; |
| } |
| } |