/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG 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: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.e4.launcher.part; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.ParameterizedCommand; import org.eclipse.core.expressions.EvaluationResult; import org.eclipse.core.expressions.Expression; import org.eclipse.core.expressions.ExpressionConverter; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IAdapterManager; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.InvalidRegistryObjectException; import org.eclipse.core.runtime.Path; import org.eclipse.e4.core.commands.ECommandService; import org.eclipse.e4.core.commands.EHandlerService; import org.eclipse.e4.core.contexts.ContextFunction; import org.eclipse.e4.core.contexts.IContextFunction; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.di.annotations.CanExecute; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer; import org.eclipse.e4.ui.internal.workbench.RenderedElementUtil; import org.eclipse.e4.ui.internal.workbench.swt.Policy; import org.eclipse.e4.ui.internal.workbench.swt.WorkbenchSWTActivator; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.commands.MCommand; import org.eclipse.e4.ui.model.application.commands.impl.CommandsFactoryImpl; import org.eclipse.e4.ui.model.application.ui.MCoreExpression; import org.eclipse.e4.ui.model.application.ui.MExpression; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.model.application.ui.impl.UiFactoryImpl; import org.eclipse.e4.ui.model.application.ui.menu.ItemType; import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem; import org.eclipse.e4.ui.model.application.ui.menu.MDirectToolItem; import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem; import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem; import org.eclipse.e4.ui.model.application.ui.menu.MHandledToolItem; import org.eclipse.e4.ui.model.application.ui.menu.MMenu; import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement; import org.eclipse.e4.ui.model.application.ui.menu.MMenuItem; import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement; import org.eclipse.e4.ui.model.application.ui.menu.MToolItem; import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl; import org.eclipse.e4.ui.workbench.IPresentationEngine; import org.eclipse.e4.ui.workbench.renderers.swt.DirectContributionItem; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuCreator; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IActionDelegate; import org.eclipse.ui.ISelectionService; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowPulldownDelegate; import org.eclipse.ui.IWorkbenchWindowPulldownDelegate2; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandImageService; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.internal.ActionDescriptor; import org.eclipse.ui.internal.OpenPreferencesAction; import org.eclipse.ui.internal.PluginAction; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.internal.WorkbenchWindow; import org.eclipse.ui.internal.e4.compatibility.CompatibilityPart; import org.eclipse.ui.internal.handlers.ActionDelegateHandlerProxy; import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; import org.eclipse.ui.internal.util.Util; import org.eclipse.ui.menus.CommandContributionItem; import org.eclipse.ui.menus.CommandContributionItemParameter; /** * @since 6.1 */ public class MenuHelper { public static void trace(final String msg, final Throwable error) { WorkbenchSWTActivator.trace(Policy.MENUS, msg, error); } public static final String MAIN_MENU_ID = "org.eclipse.ui.main.menu"; //$NON-NLS-1$ private static Field urlField; /** * The private 'location' field that is defined in the FileImageDescriptor. * * @see #getLocation(ImageDescriptor) */ private static Field locationField; /** * The private 'name' field that is defined in the FileImageDescriptor. * * @see #getName(ImageDescriptor) */ private static Field nameField; public static String getActionSetCommandId(final IConfigurationElement element) { String id = MenuHelper.getDefinitionId(element); if (id != null) { return id; } id = MenuHelper.getId(element); String actionSetId = null; Object obj = element.getParent(); while (obj instanceof IConfigurationElement && actionSetId == null) { final IConfigurationElement parent = (IConfigurationElement) obj; final String parentName = parent.getName(); if (parentName.equals(IWorkbenchRegistryConstants.TAG_ACTION_SET) || parentName.equals(IWorkbenchRegistryConstants.TAG_VIEW_CONTRIBUTION) || parentName.equals(IWorkbenchRegistryConstants.TAG_EDITOR_CONTRIBUTION)) { actionSetId = MenuHelper.getId(parent); } obj = parent.getParent(); } return IWorkbenchRegistryConstants.AUTOGENERATED_PREFIX + actionSetId + '/' + id; } public static String getImageUrl(final ImageDescriptor imageDescriptor) { return getIconURI(imageDescriptor, null); } private static URL getUrl(final Class<?> idc, final ImageDescriptor imageDescriptor) { try { if (urlField == null) { urlField = idc.getDeclaredField("url"); //$NON-NLS-1$ urlField.setAccessible(true); } return (URL) urlField.get(imageDescriptor); } catch (final SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (final NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (final IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (final IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } private static Class<?> getLocation(final ImageDescriptor imageDescriptor) { try { if (locationField == null) { locationField = imageDescriptor.getClass().getDeclaredField("location"); //$NON-NLS-1$ locationField.setAccessible(true); } return (Class<?>) locationField.get(imageDescriptor); } catch (final SecurityException e) { WorkbenchPlugin.log(e); } catch (final NoSuchFieldException e) { WorkbenchPlugin.log(e); } catch (final IllegalAccessException e) { WorkbenchPlugin.log(e); } return null; } private static String getName(final ImageDescriptor imageDescriptor) { try { if (nameField == null) { nameField = imageDescriptor.getClass().getDeclaredField("name"); //$NON-NLS-1$ nameField.setAccessible(true); } return (String) nameField.get(imageDescriptor); } catch (final SecurityException e) { WorkbenchPlugin.log(e); } catch (final NoSuchFieldException e) { WorkbenchPlugin.log(e); } catch (final IllegalAccessException e) { WorkbenchPlugin.log(e); } return null; } /** * @param element * the configuration element * @return <code>true</code> if the checkEnabled is <code>true</code>. */ static boolean getVisibleEnabled(final IConfigurationElement element) { final IConfigurationElement[] children = element.getChildren(IWorkbenchRegistryConstants.TAG_VISIBLE_WHEN); String checkEnabled = null; if (children.length > 0) { checkEnabled = children[0].getAttribute(IWorkbenchRegistryConstants.ATT_CHECK_ENABLED); } return checkEnabled != null && checkEnabled.equalsIgnoreCase("true"); //$NON-NLS-1$ } static MExpression getVisibleWhen(final IConfigurationElement commandAddition) { try { final IConfigurationElement[] visibleConfig = commandAddition.getChildren(IWorkbenchRegistryConstants.TAG_VISIBLE_WHEN); if (visibleConfig.length > 0 && visibleConfig.length < 2) { final IConfigurationElement[] visibleChild = visibleConfig[0].getChildren(); if (visibleChild.length == 0) { final String checkEnabled = visibleConfig[0].getAttribute(IWorkbenchRegistryConstants.ATT_CHECK_ENABLED); if (Boolean.parseBoolean(checkEnabled)) { final String commandId = getCommandId(commandAddition); if (commandId == null) { return null; } final Expression visWhen = new Expression() { @Override public EvaluationResult evaluate(final IEvaluationContext context) { final EHandlerService service = getFromContext(context, EHandlerService.class); final ICommandService commandService = getFromContext(context, ICommandService.class); if (service == null || commandService == null) { WorkbenchPlugin.log("Could not retrieve EHandlerService or ICommandService from context evaluation context for" //$NON-NLS-1$ + commandId); return EvaluationResult.FALSE; } final Command c = commandService.getCommand(commandId); final ParameterizedCommand generateCommand = ParameterizedCommand.generateCommand(c, Collections.EMPTY_MAP); return EvaluationResult.valueOf(service.canExecute(generateCommand)); } }; final MCoreExpression exp = UiFactoryImpl.eINSTANCE.createCoreExpression(); exp.setCoreExpressionId("programmatic.value"); //$NON-NLS-1$ exp.setCoreExpression(visWhen); return exp; } } else if (visibleChild.length > 0) { final Expression visWhen = ExpressionConverter.getDefault().perform(visibleChild[0]); final MCoreExpression exp = UiFactoryImpl.eINSTANCE.createCoreExpression(); exp.setCoreExpressionId("programmatic.value"); //$NON-NLS-1$ exp.setCoreExpression(visWhen); return exp; // visWhenMap.put(configElement, visWhen); } } } catch (final InvalidRegistryObjectException e) { // visWhenMap.put(configElement, null); // TODO Auto-generated catch block e.printStackTrace(); } catch (final CoreException e) { // visWhenMap.put(configElement, null); // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * Do a type-safe extraction of an object from the evalation context * * @param context * the evaluation context * @param expectedType * the expected type * @return an object of the expected type or <code>null</code> * @throws NullPointerException * if either argument is <code>null</code> */ protected static <T> T getFromContext(final IEvaluationContext context, final Class<T> expectedType) { if (context == null || expectedType == null) { throw new NullPointerException(); } final Object rawValue = context.getVariable(expectedType.getName()); return (expectedType.isInstance(rawValue)) ? expectedType.cast(rawValue) : null; } /* * Support Utilities */ public static String getId(final IConfigurationElement element) { String id = element.getAttribute(IWorkbenchRegistryConstants.ATT_ID); // For sub-menu management -all- items must be id'd so enforce this // here (we could optimize by checking the 'name' of the config // element == "menu" if (id == null || id.length() == 0) { id = getCommandId(element); } if (id == null || id.length() == 0) { id = element.toString(); } return id; } static String getName(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_NAME); } static int getMode(final IConfigurationElement element) { if ("FORCE_TEXT".equals(element.getAttribute(IWorkbenchRegistryConstants.ATT_MODE))) { //$NON-NLS-1$ return CommandContributionItem.MODE_FORCE_TEXT; } return 0; } static String getLabel(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_LABEL); } static String getPath(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_PATH); } static String getMenuBarPath(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_MENUBAR_PATH); } static String getToolBarPath(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_TOOLBAR_PATH); } static String getMnemonic(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_MNEMONIC); } static String getTooltip(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_TOOLTIP); } public static String getIconURI(final IConfigurationElement element, final String attr) { String iconPath = element.getAttribute(attr); if (iconPath == null) { return null; } // If iconPath doesn't specify a scheme, then try to transform to a URL // RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) // This allows using data:, http:, or other custom URL schemes if (!iconPath.matches("\\p{Alpha}[\\p{Alnum}+.-]*:.*")) { //$NON-NLS-1$ // First attempt to resolve in ISharedImages (e.g. "IMG_OBJ_FOLDER") // as per bug 391232 & AbstractUIPlugin.imageDescriptorFromPlugin(). final ImageDescriptor d = WorkbenchPlugin.getDefault().getSharedImages().getImageDescriptor(iconPath); if (d != null) { return getImageUrl(d); } final String extendingPluginId = element.getDeclaringExtension().getContributor().getName(); iconPath = "platform:/plugin/" + extendingPluginId + "/" + iconPath; //$NON-NLS-1$//$NON-NLS-2$ } URL url = null; try { url = FileLocator.find(new URL(iconPath)); } catch (final MalformedURLException e) { /* IGNORE */ } return url == null ? iconPath : rewriteDurableURL(url.toString()); } static String getHelpContextId(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_HELP_CONTEXT_ID); } public static boolean isSeparatorVisible(final IConfigurationElement element) { final String val = element.getAttribute(IWorkbenchRegistryConstants.ATT_VISIBLE); return Boolean.valueOf(val).booleanValue(); } public static String getClassSpec(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_CLASS); } public static String getCommandId(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_COMMAND_ID); } public static ItemType getStyle(final IConfigurationElement element) { final String style = element.getAttribute(IWorkbenchRegistryConstants.ATT_STYLE); if (style == null || style.length() == 0) { return ItemType.PUSH; } if (IWorkbenchRegistryConstants.STYLE_TOGGLE.equals(style)) { return ItemType.CHECK; } if (IWorkbenchRegistryConstants.STYLE_RADIO.equals(style)) { return ItemType.RADIO; } if (IWorkbenchRegistryConstants.STYLE_PULLDOWN.equals(style)) { trace("Failed to get style for " + IWorkbenchRegistryConstants.STYLE_PULLDOWN, null); //$NON-NLS-1$ // return CommandContributionItem.STYLE_PULLDOWN; } return ItemType.PUSH; } public static boolean hasPulldownStyle(final IConfigurationElement element) { final String style = element.getAttribute(IWorkbenchRegistryConstants.ATT_STYLE); return IWorkbenchRegistryConstants.STYLE_PULLDOWN.equals(style); } public static boolean getRetarget(final IConfigurationElement element) { final String r = element.getAttribute(IWorkbenchRegistryConstants.ATT_RETARGET); return Boolean.valueOf(r); } public static String getDefinitionId(final IConfigurationElement element) { return element.getAttribute(IWorkbenchRegistryConstants.ATT_DEFINITION_ID); } public static Map<String, String> getParameters(final IConfigurationElement element) { final HashMap<String, String> map = new HashMap<String, String>(); final IConfigurationElement[] parameters = element.getChildren(IWorkbenchRegistryConstants.TAG_PARAMETER); for (final IConfigurationElement parameter : parameters) { final String name = parameter.getAttribute(IWorkbenchRegistryConstants.ATT_NAME); final String value = parameter.getAttribute(IWorkbenchRegistryConstants.ATT_VALUE); if (name != null && value != null) { map.put(name, value); } } return map; } public static MMenu createMenuAddition(final IConfigurationElement menuAddition) { final MMenu element = MenuFactoryImpl.eINSTANCE.createMenu(); final String id = MenuHelper.getId(menuAddition); element.setElementId(id); String text = MenuHelper.getLabel(menuAddition); final String mnemonic = MenuHelper.getMnemonic(menuAddition); if (text != null && mnemonic != null) { final int idx = text.indexOf(mnemonic); if (idx != -1) { text = text.substring(0, idx) + '&' + text.substring(idx); } } element.setVisibleWhen(getVisibleWhen(menuAddition)); element.setIconURI(MenuHelper.getIconURI(menuAddition, IWorkbenchRegistryConstants.ATT_ICON)); element.setLabel(Util.safeString(text)); return element; } public static MMenuElement createLegacyMenuActionAdditions(final MApplication app, final IConfigurationElement element) { final String id = MenuHelper.getId(element); String text = MenuHelper.getLabel(element); final String mnemonic = MenuHelper.getMnemonic(element); if (text != null && mnemonic != null) { final int idx = text.indexOf(mnemonic); if (idx != -1) { text = text.substring(0, idx) + '&' + text.substring(idx); } } final String iconUri = MenuHelper.getIconURI(element, IWorkbenchRegistryConstants.ATT_ICON); final String cmdId = MenuHelper.getActionSetCommandId(element); MCommand cmd = ContributionsAnalyzer.getCommandById(app, cmdId); if (cmd == null) { final ECommandService commandService = app.getContext().get(ECommandService.class); Command command = commandService.getCommand(cmdId); if (command == null) { final ICommandService ics = app.getContext().get(ICommandService.class); command = commandService.defineCommand(cmdId, text, null, ics.getCategory(null), null); } cmd = CommandsFactoryImpl.eINSTANCE.createCommand(); cmd.setCommandName(text); cmd.setElementId(cmdId); app.getCommands().add(cmd); } final String style = element.getAttribute(IWorkbenchRegistryConstants.ATT_STYLE); final String pulldown = element.getAttribute("pulldown"); //$NON-NLS-1$ if (IWorkbenchRegistryConstants.STYLE_PULLDOWN.equals(style) || (pulldown != null && pulldown.equals("true"))) { //$NON-NLS-1$ final MMenuItem item = RenderedElementUtil.createRenderedMenuItem(); item.setLabel(text); if (iconUri != null) { item.setIconURI(iconUri); } final IContextFunction generator = new ContextFunction() { @Override public Object compute(final IEclipseContext context, final String contextKey) { final IWorkbenchWindow window = context.get(IWorkbenchWindow.class); if (window == null) { return null; } final ActionDescriptor desc = new ActionDescriptor(element, ActionDescriptor.T_WORKBENCH_PULLDOWN, window); final PluginAction action = desc.getAction(); return new ActionContributionItem(action) { @Override public void dispose() { super.dispose(); action.disposeDelegate(); } }; } }; RenderedElementUtil.setContributionManager(item, generator); return item; } ItemType type = ItemType.PUSH; if (IWorkbenchRegistryConstants.STYLE_TOGGLE.equals(style)) { type = ItemType.CHECK; } else if (IWorkbenchRegistryConstants.STYLE_RADIO.equals(style)) { type = ItemType.RADIO; } final MHandledMenuItem item = MenuFactoryImpl.eINSTANCE.createHandledMenuItem(); item.setElementId(id); item.setLabel(text); item.setType(type); item.setCommand(cmd); if (iconUri != null) { item.setIconURI(iconUri); } return item; } public static String getDescription(final IConfigurationElement configElement) { return configElement.getAttribute(IWorkbenchRegistryConstants.TAG_DESCRIPTION); } public static MToolBarElement createLegacyToolBarActionAdditions(final MApplication app, final IConfigurationElement element) { final String cmdId = MenuHelper.getActionSetCommandId(element); final String id = MenuHelper.getId(element); String text = MenuHelper.getLabel(element); final String mnemonic = MenuHelper.getMnemonic(element); if (text != null && mnemonic != null) { final int idx = text.indexOf(mnemonic); if (idx != -1) { text = text.substring(0, idx) + '&' + text.substring(idx); } } final String iconUri = MenuHelper.getIconURI(element, IWorkbenchRegistryConstants.ATT_ICON); final String disabledIconUri = MenuHelper.getIconURI(element, IWorkbenchRegistryConstants.ATT_DISABLEDICON); MCommand cmd = ContributionsAnalyzer.getCommandById(app, cmdId); if (cmd == null) { final ECommandService commandService = app.getContext().get(ECommandService.class); Command command = commandService.getCommand(cmdId); if (command == null) { final ICommandService ics = app.getContext().get(ICommandService.class); command = commandService.defineCommand(cmdId, text, null, ics.getCategory(null), null); } cmd = CommandsFactoryImpl.eINSTANCE.createCommand(); cmd.setCommandName(text); cmd.setElementId(cmdId); app.getCommands().add(cmd); } final MHandledToolItem item = MenuFactoryImpl.eINSTANCE.createHandledToolItem(); final String style = element.getAttribute(IWorkbenchRegistryConstants.ATT_STYLE); final String pulldown = element.getAttribute("pulldown"); //$NON-NLS-1$ if (IWorkbenchRegistryConstants.STYLE_TOGGLE.equals(style)) { item.setType(ItemType.CHECK); final IContextFunction generator = createToggleFunction(element); if (generator != null) { item.getTransientData().put(ItemType.CHECK.toString(), generator); } } else if (IWorkbenchRegistryConstants.STYLE_RADIO.equals(style)) { item.setType(ItemType.RADIO); } else { item.setType(ItemType.PUSH); } if (IWorkbenchRegistryConstants.STYLE_PULLDOWN.equals(style) || (pulldown != null && pulldown.equals("true"))) { //$NON-NLS-1$ final MMenu menu = RenderedElementUtil.createRenderedMenu(); final ECommandService cs = app.getContext().get(ECommandService.class); final ParameterizedCommand parmCmd = cs.createCommand(cmdId, null); final IContextFunction generator = new ContextFunction() { @Override public Object compute(final IEclipseContext context, final String contextKey) { return new IMenuCreator() { private ActionDelegateHandlerProxy handlerProxy; private ActionDelegateHandlerProxy getProxy() { if (handlerProxy == null) { handlerProxy = new ActionDelegateHandlerProxy(element, IWorkbenchRegistryConstants.ATT_CLASS, id, parmCmd, PlatformUI .getWorkbench().getActiveWorkbenchWindow(), null, null, null); } return handlerProxy; } private IWorkbenchWindowPulldownDelegate getDelegate() { getProxy(); if (handlerProxy == null) { return null; } if (handlerProxy.getDelegate() == null) { handlerProxy.loadDelegate(); final ISelectionService service = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService(); final IActionDelegate delegate = handlerProxy.getDelegate(); delegate.selectionChanged(handlerProxy.getAction(), service.getSelection()); } return (IWorkbenchWindowPulldownDelegate) handlerProxy.getDelegate(); } public Menu getMenu(final Menu parent) { final IWorkbenchWindowPulldownDelegate2 delegate = (IWorkbenchWindowPulldownDelegate2) getDelegate(); if (delegate == null) { return null; } return delegate.getMenu(parent); } public Menu getMenu(final Control parent) { return getDelegate() == null ? null : getDelegate().getMenu(parent); } public void dispose() { if (handlerProxy != null) { handlerProxy.dispose(); handlerProxy = null; } } }; } }; RenderedElementUtil.setContributionManager(menu, generator); item.setMenu(menu); } item.setElementId(id); item.setCommand(cmd); if (iconUri == null) { item.setLabel(text); } else { item.setIconURI(iconUri); } if (disabledIconUri != null) { setDisabledIconURI(item, disabledIconUri); } final String tooltip = getTooltip(element); // if no tooltip defined, use the textual label as the tooltip item.setTooltip(tooltip == null ? text : tooltip); return item; } private static int getType(final String name) { if (name.equals(IWorkbenchRegistryConstants.TAG_ACTION_SET)) { return ActionDescriptor.T_WORKBENCH; } else if (name.equals(IWorkbenchRegistryConstants.TAG_VIEW_CONTRIBUTION)) { return ActionDescriptor.T_VIEW; } else if (name.equals(IWorkbenchRegistryConstants.TAG_EDITOR_CONTRIBUTION)) { return ActionDescriptor.T_EDITOR; } return -1; } private static IContextFunction createToggleFunction(final IConfigurationElement element) { final Object ice = element.getParent(); if (!(ice instanceof IConfigurationElement)) { return null; } // identify the type of contribution that this is final IConfigurationElement parent = (IConfigurationElement) ice; final int type = getType(parent.getName()); if (type == -1) { // unknown, don't create a toggling function return null; } final IContextFunction generator = new ContextFunction() { private ActionDescriptor getDescriptor(final IEclipseContext context) { switch (type) { case ActionDescriptor.T_WORKBENCH: final IWorkbenchWindow window = context.get(IWorkbenchWindow.class); return window == null ? null : new ActionDescriptor(element, type, window); case ActionDescriptor.T_EDITOR: return new ActionDescriptor(element, type, null); case ActionDescriptor.T_VIEW: final MPart part = context.get(MPart.class); if (part != null) { final Object object = part.getObject(); if (object instanceof CompatibilityPart) { return new ActionDescriptor(element, type, ((CompatibilityPart) object).getPart()); } } return null; default: return null; } } @Override public Object compute(final IEclipseContext context, final String contextKey) { final MHandledItem model = context.get(MHandledItem.class); if (model == null) { return null; } final ActionDescriptor desc = getDescriptor(context); final IAction action = desc.getAction(); final IPropertyChangeListener propListener = new IPropertyChangeListener() { public void propertyChange(final PropertyChangeEvent event) { if (IAction.CHECKED.equals(event.getProperty())) { boolean checked = false; if (event.getNewValue() instanceof Boolean) { checked = ((Boolean) event.getNewValue()).booleanValue(); } model.setSelected(checked); } } }; action.addPropertyChangeListener(propListener); final Runnable obj = new Runnable() { @Execute public void run() { action.removePropertyChangeListener(propListener); } }; model.setSelected(action.isChecked()); return obj; } }; return generator; } public static MMenu createMenu(final MenuManager manager) { final MMenu subMenu = MenuFactoryImpl.eINSTANCE.createMenu(); subMenu.setLabel(manager.getMenuText()); subMenu.setElementId(manager.getId()); return subMenu; } public static MMenuItem createItem(final MApplication application, final CommandContributionItem cci) { if (cci.getCommand() == null) { return null; } final String id = cci.getCommand().getId(); for (final MCommand command : application.getCommands()) { if (id.equals(command.getElementId())) { final CommandContributionItemParameter data = cci.getData(); final MHandledMenuItem menuItem = MenuFactoryImpl.eINSTANCE.createHandledMenuItem(); menuItem.setCommand(command); menuItem.setContributorURI(command.getContributorURI()); if (data.label != null) { menuItem.setLabel(data.label); } else { menuItem.setLabel(command.getCommandName()); } if (data.mnemonic != null) { menuItem.setMnemonics(data.mnemonic); } if (data.icon != null) { menuItem.setIconURI(getIconURI(data.icon, application.getContext())); } else { menuItem.setIconURI(getIconURI(id, application.getContext(), ICommandImageService.TYPE_DEFAULT)); } final String itemId = cci.getId(); menuItem.setElementId(itemId == null ? id : itemId); return menuItem; } } return null; } public static MToolItem createToolItem(final MApplication application, final CommandContributionItem cci) { final String id = cci.getCommand().getId(); for (final MCommand command : application.getCommands()) { if (id.equals(command.getElementId())) { final CommandContributionItemParameter data = cci.getData(); final MHandledToolItem toolItem = MenuFactoryImpl.eINSTANCE.createHandledToolItem(); toolItem.setCommand(command); toolItem.setContributorURI(command.getContributorURI()); String iconURI = null; String disabledIconURI = null; if (data.icon != null) { iconURI = getIconURI(data.icon, application.getContext()); } if (iconURI == null) { iconURI = getIconURI(id, application.getContext(), ICommandImageService.TYPE_DEFAULT); } if (iconURI == null) { toolItem.setLabel(command.getCommandName()); } else { toolItem.setIconURI(iconURI); } if (data.disabledIcon != null) { disabledIconURI = getIconURI(data.disabledIcon, application.getContext()); } if (disabledIconURI == null) { disabledIconURI = getIconURI(id, application.getContext(), ICommandImageService.TYPE_DISABLED); } if (disabledIconURI != null) { setDisabledIconURI(toolItem, disabledIconURI); } if (data.tooltip != null) { toolItem.setTooltip(data.tooltip); } else if (data.label != null) { toolItem.setTooltip(data.label); } else { toolItem.setTooltip(command.getDescription()); } final String itemId = cci.getId(); toolItem.setElementId(itemId == null ? id : itemId); return toolItem; } } return null; } public static MToolItem createToolItem(final MApplication application, final ActionContributionItem item) { final IAction action = item.getAction(); final String id = action.getActionDefinitionId(); if (id != null) { for (final MCommand command : application.getCommands()) { if (id.equals(command.getElementId())) { final MHandledToolItem toolItem = MenuFactoryImpl.eINSTANCE.createHandledToolItem(); toolItem.setCommand(command); toolItem.setContributorURI(command.getContributorURI()); String iconURI = getIconURI(action.getImageDescriptor(), application.getContext()); if (iconURI == null) { iconURI = getIconURI(id, application.getContext(), ICommandImageService.TYPE_DEFAULT); if (iconURI == null) { toolItem.setLabel(command.getCommandName()); } else { toolItem.setIconURI(iconURI); } } else { toolItem.setIconURI(iconURI); } if (action.getToolTipText() != null) { toolItem.setTooltip(action.getToolTipText()); } String disabledIconURI = getIconURI(action.getDisabledImageDescriptor(), application.getContext()); if (disabledIconURI == null) { disabledIconURI = getIconURI(id, application.getContext(), ICommandImageService.TYPE_DEFAULT); } if (disabledIconURI != null) { setDisabledIconURI(toolItem, disabledIconURI); } switch (action.getStyle()) { case IAction.AS_CHECK_BOX: toolItem.setType(ItemType.CHECK); toolItem.setSelected(action.isChecked()); break; case IAction.AS_RADIO_BUTTON: toolItem.setType(ItemType.RADIO); toolItem.setSelected(action.isChecked()); break; default: toolItem.setType(ItemType.PUSH); break; } final String itemId = item.getId(); toolItem.setElementId(itemId == null ? id : itemId); return toolItem; } } } else { final MDirectToolItem toolItem = MenuFactoryImpl.eINSTANCE.createDirectToolItem(); final String itemId = item.getId(); toolItem.setElementId(itemId); String iconURI = getIconURI(action.getImageDescriptor(), application.getContext()); if (iconURI == null) { if (itemId == null) { if (action.getText() != null) { toolItem.setLabel(action.getText()); } } else { iconURI = getIconURI(itemId, application.getContext(), ICommandImageService.TYPE_DEFAULT); if (iconURI == null) { if (action.getText() != null) { toolItem.setLabel(action.getText()); } } else { toolItem.setIconURI(iconURI); } } } else { toolItem.setIconURI(iconURI); } if (action.getToolTipText() != null) { toolItem.setTooltip(action.getToolTipText()); } switch (action.getStyle()) { case IAction.AS_CHECK_BOX: toolItem.setType(ItemType.CHECK); toolItem.setSelected(action.isChecked()); break; case IAction.AS_RADIO_BUTTON: toolItem.setType(ItemType.RADIO); toolItem.setSelected(action.isChecked()); break; default: toolItem.setType(ItemType.PUSH); break; } toolItem.setContributionURI("bundleclass://org.eclipse.ui.workbench/programmic.contribution"); //$NON-NLS-1$ toolItem.setObject(new DirectProxy(action)); toolItem.setEnabled(action.isEnabled()); final IPropertyChangeListener propertyListener = new IPropertyChangeListener() { public void propertyChange(final PropertyChangeEvent event) { final String property = event.getProperty(); if (property.equals(IAction.ENABLED)) { toolItem.setEnabled(action.isEnabled()); } else if (property.equals(IAction.CHECKED)) { toolItem.setSelected(action.isChecked()); } else if (property.equals(IAction.TEXT)) { toolItem.setLabel(action.getText()); } else if (property.equals(IAction.TOOL_TIP_TEXT)) { toolItem.setLabel(action.getToolTipText()); } } }; // property listener is removed in // DirectContributionItem#handleWidgetDispose() action.addPropertyChangeListener(propertyListener); toolItem.getTransientData().put(DirectContributionItem.DISPOSABLE, new Runnable() { public void run() { action.removePropertyChangeListener(propertyListener); } }); return toolItem; } return null; } public static MMenuItem createItem(final MApplication application, final ActionContributionItem item) { final IAction action = item.getAction(); final String id = action.getActionDefinitionId(); if (action instanceof OpenPreferencesAction) { for (final MCommand command : application.getCommands()) { if (IWorkbenchCommandConstants.WINDOW_PREFERENCES.equals(command.getElementId())) { final MHandledMenuItem menuItem = MenuFactoryImpl.eINSTANCE.createHandledMenuItem(); menuItem.setCommand(command); menuItem.setLabel(command.getCommandName()); menuItem.setIconURI(getIconURI(action.getImageDescriptor(), application.getContext())); // extract the mnemonic definition final String text = action.getText(); final int index = text.indexOf('&'); if (index != -1 && index != text.length() - 1) { menuItem.setMnemonics(text.substring(index + 1, index + 2)); } switch (action.getStyle()) { case IAction.AS_CHECK_BOX: menuItem.setType(ItemType.CHECK); menuItem.setSelected(action.isChecked()); break; case IAction.AS_RADIO_BUTTON: menuItem.setType(ItemType.RADIO); menuItem.setSelected(action.isChecked()); break; default: menuItem.setType(ItemType.PUSH); break; } final String itemId = item.getId(); menuItem.setElementId(itemId == null ? id : itemId); return menuItem; } } } else if (id != null) { for (final MCommand command : application.getCommands()) { if (id.equals(command.getElementId())) { final MHandledMenuItem menuItem = MenuFactoryImpl.eINSTANCE.createHandledMenuItem(); menuItem.setCommand(command); if (action.getText() != null) { menuItem.setLabel(action.getText()); } else { menuItem.setLabel(command.getCommandName()); } menuItem.setIconURI(getIconURI(action.getImageDescriptor(), application.getContext())); switch (action.getStyle()) { case IAction.AS_CHECK_BOX: menuItem.setType(ItemType.CHECK); menuItem.setSelected(action.isChecked()); break; case IAction.AS_RADIO_BUTTON: menuItem.setType(ItemType.RADIO); menuItem.setSelected(action.isChecked()); break; default: menuItem.setType(ItemType.PUSH); break; } final String itemId = item.getId(); menuItem.setElementId(itemId == null ? id : itemId); return menuItem; } } } else { final MDirectMenuItem menuItem = MenuFactoryImpl.eINSTANCE.createDirectMenuItem(); if (action.getText() != null) { menuItem.setLabel(action.getText()); } final String itemId = item.getId(); menuItem.setElementId(itemId == null ? id : itemId); menuItem.setIconURI(getIconURI(action.getImageDescriptor(), application.getContext())); switch (action.getStyle()) { case IAction.AS_CHECK_BOX: menuItem.setType(ItemType.CHECK); menuItem.setSelected(action.isChecked()); break; case IAction.AS_RADIO_BUTTON: menuItem.setType(ItemType.RADIO); menuItem.setSelected(action.isChecked()); break; default: menuItem.setType(ItemType.PUSH); break; } menuItem.setContributionURI("bundleclass://org.eclipse.ui.workbench/programmic.contribution"); //$NON-NLS-1$ menuItem.setObject(new DirectProxy(action)); return menuItem; } return null; } static class DirectProxy { private final IAction action; public DirectProxy(final IAction action) { this.action = action; } @CanExecute public boolean canExecute() { return action.isEnabled(); } @Execute public void execute() { action.run(); } } public static String getIconURI(final ImageDescriptor descriptor, final IEclipseContext context) { if (descriptor == null) { return null; } // Attempt to retrieve URIs from the descriptor and convert into a more // durable form in case it's to be persisted if (descriptor.getClass().toString().endsWith("URLImageDescriptor")) { //$NON-NLS-1$ final URL url = getUrl(descriptor.getClass(), descriptor); return rewriteDurableURL(url.toExternalForm()); } else if (descriptor.getClass().toString().endsWith("FileImageDescriptor")) { //$NON-NLS-1$ final Class<?> sourceClass = getLocation(descriptor); if (sourceClass == null) { return null; } final String path = getName(descriptor); if (path == null) { return null; } final Bundle bundle = FrameworkUtil.getBundle(sourceClass); // get the fully qualified class name String parentPath = sourceClass.getName(); // remove the class's name parentPath = parentPath.substring(0, parentPath.lastIndexOf('.')); // swap '.' with '/' so that it becomes a path parentPath = parentPath.replace('.', '/'); // construct the URL final URL url = FileLocator.find(bundle, new Path(parentPath).append(path), null); return url == null ? null : rewriteDurableURL(url.toString()); } else { if (descriptor instanceof IAdaptable) { Object o = ((IAdaptable) descriptor).getAdapter(URL.class); if (o != null) { return rewriteDurableURL(o.toString()); } o = ((IAdaptable) descriptor).getAdapter(URI.class); if (o != null) { return rewriteDurableURL(o.toString()); } } else if (context != null) { final IAdapterManager adapter = context.get(IAdapterManager.class); if (adapter != null) { Object o = adapter.getAdapter(descriptor, URL.class); if (o != null) { return rewriteDurableURL(o.toString()); } o = adapter.getAdapter(descriptor, URI.class); if (o != null) { return rewriteDurableURL(o.toString()); } } } } return null; } /** * Rewrite certain types of URLs to more durable forms, as these URLs may may be persisted in the model. * * @param url * the url * @return the rewritten URL */ private static String rewriteDurableURL(final String url) { // Rewrite bundleentry and bundleresource entries as they are // invalidated on -clean or a bundle remove, . These Platform URIs are // of the form: // bundleentry://<bundle-id>.XXX/path/to/file // bundleresource://<bundle-id>.XXX/path/to/file if (!url.startsWith("bundleentry:") && !url.startsWith("bundleresource:")) { //$NON-NLS-1$ //$NON-NLS-2$ return url; } final BundleContext ctxt = FrameworkUtil.getBundle(WorkbenchWindow.class).getBundleContext(); try { final URI uri = new URI(url); final String host = uri.getHost(); final String bundleId = host.substring(0, host.indexOf('.')); final Bundle bundle = ctxt.getBundle(Long.parseLong(bundleId)); final StringBuilder builder = new StringBuilder("platform:/plugin/"); //$NON-NLS-1$ builder.append(bundle.getSymbolicName()); builder.append(uri.getPath()); return builder.toString(); } catch (final URISyntaxException e) { return url; } } private static String getIconURI(final String commandId, final IEclipseContext workbench, final int type) { if (commandId == null) { return null; } final ICommandImageService imageService = workbench.get(ICommandImageService.class); final ImageDescriptor descriptor = imageService.getImageDescriptor(commandId, type); return getIconURI(descriptor, workbench); } /** * @param item * @param disabledIconURI */ public static void setDisabledIconURI(final MToolItem item, final String disabledIconURI) { item.getTransientData().put(IPresentationEngine.DISABLED_ICON_IMAGE_KEY, disabledIconURI); } }