/*******************************************************************************
* 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.util.ArrayList;
import java.util.Map;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.e4.core.contexts.ContextFunction;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
import org.eclipse.e4.ui.internal.workbench.RenderedElementUtil;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.application.commands.MCommand;
import org.eclipse.e4.ui.model.application.commands.MParameter;
import org.eclipse.e4.ui.model.application.commands.impl.CommandsFactoryImpl;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
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.MMenuContribution;
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.MToolBar;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
import org.eclipse.e4.ui.model.application.ui.menu.MTrimContribution;
import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl;
import org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.activities.IIdentifierListener;
import org.eclipse.ui.activities.IdentifierEvent;
import org.eclipse.ui.commands.ICommandImageService;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.menus.CompatibilityWorkbenchWindowControlContribution;
import org.eclipse.ui.internal.menus.ControlContributionRegistry;
import org.eclipse.ui.internal.menus.DynamicMenuContributionItem;
import org.eclipse.ui.internal.menus.MenuLocationURI;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.internal.services.ServiceLocator;
/**
* @since 6.1
*/
public class MenuAdditionCacheEntry {
final static String MAIN_TOOLBAR = "org.eclipse.ui.main.toolbar"; //$NON-NLS-1$
final static String TRIM_COMMAND1 = "org.eclipse.ui.trim.command1"; //$NON-NLS-1$
final static String TRIM_COMMAND2 = "org.eclipse.ui.trim.command2"; //$NON-NLS-1$
final static String TRIM_VERTICAL1 = "org.eclipse.ui.trim.vertical1"; //$NON-NLS-1$
final static String TRIM_VERTICAL2 = "org.eclipse.ui.trim.vertical2"; //$NON-NLS-1$
final static String TRIM_STATUS = "org.eclipse.ui.trim.status"; //$NON-NLS-1$
/**
* Test whether the location URI is in one of the pre-defined workbench trim areas.
*
* @param location
* @return true if the URI is in workbench trim area.
*/
static boolean isInWorkbenchTrim(final MenuLocationURI location) {
final String path = location.getPath();
return MAIN_TOOLBAR.equals(path) || TRIM_COMMAND1.equals(path) || TRIM_COMMAND2.equals(path) || TRIM_VERTICAL1.equals(path)
|| TRIM_VERTICAL2.equals(path) || TRIM_STATUS.equals(path);
}
private final MApplication application;
// private IEclipseContext appContext;
private final IConfigurationElement configElement;
private final MenuLocationURI location;
private final String namespaceIdentifier;
// private final IActivityManager activityManager;
public MenuAdditionCacheEntry(final MApplication application, final IEclipseContext appContext, final IConfigurationElement configElement,
final String attribute, final String namespaceIdentifier) {
this.application = application;
// this.appContext = appContext;
assert appContext.equals(this.application.getContext());
this.configElement = configElement;
this.location = new MenuLocationURI(attribute);
this.namespaceIdentifier = namespaceIdentifier;
// final IWorkbench workbench = application.getContext().get(IWorkbench.class);
// activityManager = workbench.getActivitySupport().getActivityManager();
}
private boolean inToolbar() {
return location.getScheme().startsWith("toolbar"); //$NON-NLS-1$
}
/**
* @return <code>true</code> if this is a toolbar contribution
*/
public void mergeIntoModel(final ArrayList<MMenuContribution> menuContributions, final ArrayList<MToolBarContribution> toolBarContributions,
final ArrayList<MTrimContribution> trimContributions) {
if ("menu:help?after=additions".equals(location.toString())) { //$NON-NLS-1$
final IConfigurationElement[] menus = configElement.getChildren(IWorkbenchRegistryConstants.TAG_MENU);
if (menus.length == 1 && "org.eclipse.update.ui.updateMenu".equals(MenuHelper.getId(menus[0]))) { //$NON-NLS-1$
return;
}
}
if (location.getPath() == null || location.getPath().length() == 0) {
WorkbenchPlugin.log("MenuAdditionCacheEntry.mergeIntoModel: Invalid menu URI: " + location); //$NON-NLS-1$
return;
}
if (inToolbar()) {
if (isInWorkbenchTrim(location)) {
processTrimChildren(trimContributions, toolBarContributions, configElement);
} else {
String query = location.getQuery();
if (query == null || query.length() == 0) {
query = "after=additions"; //$NON-NLS-1$
}
processToolbarChildren(toolBarContributions, configElement, location.getPath(), query);
}
return;
}
final MMenuContribution menuContribution = MenuFactoryImpl.eINSTANCE.createMenuContribution();
final String idContrib = MenuHelper.getId(configElement);
if (idContrib != null && idContrib.length() > 0) {
menuContribution.setElementId(idContrib);
}
if ("org.eclipse.ui.popup.any".equals(location.getPath())) { //$NON-NLS-1$
menuContribution.setParentId("popup"); //$NON-NLS-1$
} else {
menuContribution.setParentId(location.getPath());
}
String query = location.getQuery();
if (query == null || query.length() == 0) {
query = "after=additions"; //$NON-NLS-1$
}
menuContribution.setPositionInParent(query);
menuContribution.getTags().add("scheme:" + location.getScheme()); //$NON-NLS-1$
String filter = ContributionsAnalyzer.MC_MENU;
if ("popup".equals(location.getScheme())) { //$NON-NLS-1$
filter = ContributionsAnalyzer.MC_POPUP;
}
menuContribution.getTags().add(filter);
menuContribution.setVisibleWhen(MenuHelper.getVisibleWhen(configElement));
addMenuChildren(menuContribution, configElement, filter);
menuContributions.add(menuContribution);
processMenuChildren(menuContributions, configElement, filter);
}
/**
* @param menuContributions
* @param filter
*/
private void processMenuChildren(final ArrayList<MMenuContribution> menuContributions, final IConfigurationElement element, final String filter) {
final IConfigurationElement[] menus = element.getChildren(IWorkbenchRegistryConstants.TAG_MENU);
if (menus.length == 0) {
return;
}
for (final IConfigurationElement menu : menus) {
final MMenuContribution menuContribution = MenuFactoryImpl.eINSTANCE.createMenuContribution();
final String idContrib = MenuHelper.getId(menu);
if (idContrib != null && idContrib.length() > 0) {
menuContribution.setElementId(idContrib);
}
menuContribution.setParentId(idContrib);
menuContribution.setPositionInParent("after=additions"); //$NON-NLS-1$
menuContribution.getTags().add("scheme:" + location.getScheme()); //$NON-NLS-1$
menuContribution.getTags().add(filter);
menuContribution.setVisibleWhen(MenuHelper.getVisibleWhen(menu));
addMenuChildren(menuContribution, menu, filter);
menuContributions.add(menuContribution);
processMenuChildren(menuContributions, menu, filter);
}
}
private void addMenuChildren(final MElementContainer<MMenuElement> container, final IConfigurationElement parent, final String filter) {
final IConfigurationElement[] items = parent.getChildren();
for (final IConfigurationElement child : items) {
final String itemType = child.getName();
final String id = MenuHelper.getId(child);
if (IWorkbenchRegistryConstants.TAG_COMMAND.equals(itemType)) {
final MMenuElement element = createMenuCommandAddition(child);
container.getChildren().add(element);
} else if (IWorkbenchRegistryConstants.TAG_SEPARATOR.equals(itemType)) {
final MMenuElement element = createMenuSeparatorAddition(child);
container.getChildren().add(element);
} else if (IWorkbenchRegistryConstants.TAG_MENU.equals(itemType)) {
final MMenu element = createMenuAddition(child, filter);
container.getChildren().add(element);
} else if (IWorkbenchRegistryConstants.TAG_TOOLBAR.equals(itemType)) {
System.out.println("Toolbar: " + id + " in " + location); //$NON-NLS-1$//$NON-NLS-2$
} else if (IWorkbenchRegistryConstants.TAG_DYNAMIC.equals(itemType)) {
final ContextFunction generator = new ContextFunction() {
@Override
public Object compute(final IEclipseContext context, final String contextKey) {
final ServiceLocator sl = new ServiceLocator();
sl.setContext(context);
final DynamicMenuContributionItem item = new DynamicMenuContributionItem(MenuHelper.getId(child), sl, child);
return item;
}
};
final MMenuItem menuItem = RenderedElementUtil.createRenderedMenuItem();
menuItem.setElementId(id);
RenderedElementUtil.setContributionManager(menuItem, generator);
menuItem.setVisibleWhen(MenuHelper.getVisibleWhen(child));
container.getChildren().add(menuItem);
}
}
}
/**
* @param iConfigurationElement
* @return
*/
private MMenuElement createMenuCommandAddition(final IConfigurationElement commandAddition) {
final MHandledMenuItem item = MenuFactoryImpl.eINSTANCE.createHandledMenuItem();
item.setElementId(MenuHelper.getId(commandAddition));
final String commandId = MenuHelper.getCommandId(commandAddition);
MCommand commandById = ContributionsAnalyzer.getCommandById(application, commandId);
if (commandById == null) {
commandById = CommandsFactoryImpl.eINSTANCE.createCommand();
commandById.setElementId(commandId);
commandById.setCommandName(commandId);
application.getCommands().add(commandById);
}
item.setCommand(commandById);
final Map parms = MenuHelper.getParameters(commandAddition);
for (final Object obj : parms.entrySet()) {
final Map.Entry e = (Map.Entry) obj;
final MParameter parm = CommandsFactoryImpl.eINSTANCE.createParameter();
parm.setName(e.getKey().toString());
parm.setValue(e.getValue().toString());
item.getParameters().add(parm);
}
final String iconUrl = MenuHelper.getIconURI(commandAddition, IWorkbenchRegistryConstants.ATT_ICON);
if (iconUrl == null) {
final ICommandImageService commandImageService = application.getContext().get(ICommandImageService.class);
ImageDescriptor descriptor = commandImageService == null ? null : commandImageService.getImageDescriptor(commandId);
if (descriptor == null) {
descriptor = commandImageService == null ? null : commandImageService.getImageDescriptor(item.getElementId());
}
if (descriptor != null) {
item.setIconURI(MenuHelper.getImageUrl(descriptor));
}
} else {
item.setIconURI(iconUrl);
}
item.setLabel(MenuHelper.getLabel(commandAddition));
item.setMnemonics(MenuHelper.getMnemonic(commandAddition));
item.setTooltip(MenuHelper.getTooltip(commandAddition));
item.setType(MenuHelper.getStyle(commandAddition));
item.setVisibleWhen(MenuHelper.getVisibleWhen(commandAddition));
createIdentifierTracker(item);
return item;
}
private class IdListener implements IIdentifierListener {
public void identifierChanged(final IdentifierEvent identifierEvent) {
application.getContext().set(identifierEvent.getIdentifier().getId(), identifierEvent.getIdentifier().isEnabled());
}
}
private final IdListener idUpdater = new IdListener();
private void createIdentifierTracker(final MApplicationElement item) {
if (item.getElementId() != null && item.getElementId().length() > 0) {
final String id = namespaceIdentifier + "/" + item.getElementId(); //$NON-NLS-1$
item.getPersistedState().put(MenuManagerRenderer.VISIBILITY_IDENTIFIER, id);
// final IIdentifier identifier = activityManager.getIdentifier(id);
// if (identifier != null) {
// application.getContext().set(identifier.getId(), identifier.isEnabled());
// identifier.addIdentifierListener(idUpdater);
// }
}
}
private MMenuElement createMenuSeparatorAddition(final IConfigurationElement sepAddition) {
final String name = MenuHelper.getName(sepAddition);
final MMenuElement element = MenuFactoryImpl.eINSTANCE.createMenuSeparator();
element.setElementId(name);
if (!MenuHelper.isSeparatorVisible(sepAddition)) {
element.setVisible(false);
element.getTags().add(MenuManagerRenderer.GROUP_MARKER);
}
return element;
}
private MMenu createMenuAddition(final IConfigurationElement menuAddition, final String filter) {
// Is this for a menu or a ToolBar ? We can't create
// a menu directly under a Toolbar; we have to add an
// item of style 'pulldown'
if (inToolbar()) {
return null;
}
final MMenu menu = MenuHelper.createMenuAddition(menuAddition);
menu.getTags().add(filter);
// addMenuChildren(menu, menuAddition, filter);
return menu;
}
private boolean isUndefined(final String query) {
if (query == null || query.length() == 0) {
return true;
}
final int index = query.indexOf('=');
return index == -1 || query.substring(index + 1).equals("additions"); //$NON-NLS-1$
}
private void processTrimLocation(final MTrimContribution contribution) {
String query = location.getQuery();
if (TRIM_COMMAND2.equals(location.getPath())) {
contribution.setParentId(MAIN_TOOLBAR);
if (isUndefined(query)) {
query = "endof"; //$NON-NLS-1$
}
contribution.setPositionInParent(query);
} else {
contribution.setParentId(location.getPath());
if (query == null || query.length() == 0) {
query = "after=additions"; //$NON-NLS-1$
}
contribution.setPositionInParent(query);
}
}
private void processTrimChildren(final ArrayList<MTrimContribution> trimContributions, final ArrayList<MToolBarContribution> toolBarContributions,
final IConfigurationElement element) {
final IConfigurationElement[] toolbars = element.getChildren(IWorkbenchRegistryConstants.TAG_TOOLBAR);
if (toolbars.length == 0) {
return;
}
final MTrimContribution trimContribution = MenuFactoryImpl.eINSTANCE.createTrimContribution();
final String idContrib = MenuHelper.getId(configElement);
if (idContrib != null && idContrib.length() > 0) {
trimContribution.setElementId(idContrib);
}
processTrimLocation(trimContribution);
trimContribution.getTags().add("scheme:" + location.getScheme()); //$NON-NLS-1$
for (final IConfigurationElement toolbar : toolbars) {
final MToolBar item = MenuFactoryImpl.eINSTANCE.createToolBar();
item.setElementId(MenuHelper.getId(toolbar));
item.getTransientData().put("Name", MenuHelper.getLabel(toolbar)); //$NON-NLS-1$
processToolbarChildren(toolBarContributions, toolbar, item.getElementId(), "after=additions"); //$NON-NLS-1$
trimContribution.getChildren().add(item);
}
trimContributions.add(trimContribution);
}
private void processToolbarChildren(final ArrayList<MToolBarContribution> contributions, final IConfigurationElement toolbar, final String parentId,
final String position) {
final MToolBarContribution toolBarContribution = MenuFactoryImpl.eINSTANCE.createToolBarContribution();
final String idContrib = MenuHelper.getId(toolbar);
if (idContrib != null && idContrib.length() > 0) {
toolBarContribution.setElementId(idContrib);
}
toolBarContribution.setParentId(parentId);
toolBarContribution.setPositionInParent(position);
toolBarContribution.getTags().add("scheme:" + location.getScheme()); //$NON-NLS-1$
final IConfigurationElement[] items = toolbar.getChildren();
for (final IConfigurationElement item : items) {
final String itemType = item.getName();
if (IWorkbenchRegistryConstants.TAG_COMMAND.equals(itemType)) {
final MToolBarElement element = createToolBarCommandAddition(item);
toolBarContribution.getChildren().add(element);
} else if (IWorkbenchRegistryConstants.TAG_SEPARATOR.equals(itemType)) {
final MToolBarElement element = createToolBarSeparatorAddition(item);
toolBarContribution.getChildren().add(element);
} else if (IWorkbenchRegistryConstants.TAG_CONTROL.equals(itemType)) {
final MToolBarElement element = createToolControlAddition(item);
toolBarContribution.getChildren().add(element);
}
}
contributions.add(toolBarContribution);
}
private MToolBarElement createToolControlAddition(final IConfigurationElement element) {
final String id = MenuHelper.getId(element);
final MToolControl control = MenuFactoryImpl.eINSTANCE.createToolControl();
control.setElementId(id);
control.setContributionURI(CompatibilityWorkbenchWindowControlContribution.CONTROL_CONTRIBUTION_URI);
ControlContributionRegistry.add(id, element);
control.setVisibleWhen(MenuHelper.getVisibleWhen(element));
createIdentifierTracker(control);
return control;
}
private MToolBarElement createToolBarSeparatorAddition(final IConfigurationElement sepAddition) {
final String name = MenuHelper.getName(sepAddition);
final MToolBarElement element = MenuFactoryImpl.eINSTANCE.createToolBarSeparator();
element.setElementId(name);
if (!MenuHelper.isSeparatorVisible(sepAddition)) {
element.setToBeRendered(false);
element.setVisible(false);
element.getTags().add(MenuManagerRenderer.GROUP_MARKER);
}
return element;
}
private MToolBarElement createToolBarCommandAddition(final IConfigurationElement commandAddition) {
final MHandledToolItem item = MenuFactoryImpl.eINSTANCE.createHandledToolItem();
item.setElementId(MenuHelper.getId(commandAddition));
final String commandId = MenuHelper.getCommandId(commandAddition);
MCommand commandById = ContributionsAnalyzer.getCommandById(application, commandId);
if (commandById == null) {
commandById = CommandsFactoryImpl.eINSTANCE.createCommand();
commandById.setElementId(commandId);
commandById.setCommandName(commandId);
application.getCommands().add(commandById);
}
item.setCommand(commandById);
final Map parms = MenuHelper.getParameters(commandAddition);
for (final Object obj : parms.entrySet()) {
final Map.Entry e = (Map.Entry) obj;
final MParameter parm = CommandsFactoryImpl.eINSTANCE.createParameter();
parm.setName(e.getKey().toString());
parm.setValue(e.getValue().toString());
item.getParameters().add(parm);
}
String iconUrl = MenuHelper.getIconURI(commandAddition, IWorkbenchRegistryConstants.ATT_ICON);
if (iconUrl == null) {
final ICommandImageService commandImageService = application.getContext().get(ICommandImageService.class);
ImageDescriptor descriptor = commandImageService == null ? null : commandImageService.getImageDescriptor(commandId,
ICommandImageService.IMAGE_STYLE_TOOLBAR);
if (descriptor == null) {
descriptor = commandImageService == null ? null : commandImageService.getImageDescriptor(item.getElementId(),
ICommandImageService.IMAGE_STYLE_TOOLBAR);
if (descriptor == null) {
item.setLabel(MenuHelper.getLabel(commandAddition));
} else {
item.setIconURI(MenuHelper.getImageUrl(descriptor));
}
} else {
item.setIconURI(MenuHelper.getImageUrl(descriptor));
}
} else {
item.setIconURI(iconUrl);
}
iconUrl = MenuHelper.getIconURI(commandAddition, IWorkbenchRegistryConstants.ATT_DISABLEDICON);
if (iconUrl == null) {
final ICommandImageService commandImageService = application.getContext().get(ICommandImageService.class);
if (commandImageService != null) {
ImageDescriptor descriptor = commandImageService.getImageDescriptor(commandId, ICommandImageService.TYPE_DISABLED,
ICommandImageService.IMAGE_STYLE_TOOLBAR);
if (descriptor == null) {
descriptor = commandImageService.getImageDescriptor(item.getElementId(), ICommandImageService.TYPE_DISABLED,
ICommandImageService.IMAGE_STYLE_TOOLBAR);
}
if (descriptor != null) {
iconUrl = MenuHelper.getImageUrl(descriptor);
}
}
}
if (iconUrl != null) {
MenuHelper.setDisabledIconURI(item, iconUrl);
}
item.setTooltip(MenuHelper.getTooltip(commandAddition));
item.setType(MenuHelper.getStyle(commandAddition));
if (MenuHelper.hasPulldownStyle(commandAddition)) {
final MMenu element = MenuFactoryImpl.eINSTANCE.createMenu();
final String id = MenuHelper.getId(commandAddition);
element.setElementId(id);
item.setMenu(element);
}
item.setVisibleWhen(MenuHelper.getVisibleWhen(commandAddition));
createIdentifierTracker(item);
return item;
}
}