blob: b20331c472ada998f0982403e02761da95b10431 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009-2013 Mia-Software and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Gabriel Barbier (Mia-Software) - initial API and implementation
* Nicolas Bros (Mia-Software) - refactoring for new discovery framework
* Nicolas Bros (Mia-Software) - Bug 344117 - NPE during context menu generation prevents 'Progress' view from coming up
* Gregoire Dupe (Mia-Software) - Bug 422168 - Discovery menu breakable by an extension exception
*******************************************************************************/
package org.eclipse.modisco.infra.discovery.ui.internal.actions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.modisco.infra.common.core.logging.MoDiscoLogger;
import org.eclipse.modisco.infra.discovery.catalog.DiscovererDescription;
import org.eclipse.modisco.infra.discovery.core.IDiscoveryManager;
import org.eclipse.modisco.infra.discovery.ui.Activator;
import org.eclipse.modisco.infra.discovery.ui.Messages;
import org.eclipse.modisco.infra.discovery.ui.internal.registry.DiscovererUI;
import org.eclipse.modisco.infra.discovery.ui.internal.registry.DiscovererUIRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.menus.IWorkbenchContribution;
import org.eclipse.ui.services.IServiceLocator;
/** Populates the MoDisco menu dynamically (and lazily, when it is shown). */
public class ContributionItemForMoDiscoMenu extends ContributionItem implements
IWorkbenchContribution {
private Shell shell;
private ISelectionService selectionService;
public void initialize(final IServiceLocator serviceLocator) {
this.selectionService = (ISelectionService) serviceLocator
.getService(ISelectionService.class);
}
@Override
public void fill(final Menu menu, final int index) {
super.fill(menu, index);
this.shell = menu.getShell();
ISelection selection = this.selectionService.getSelection();
// ClassCastException in Eclipse 3.5 : TextSelection /
// IStructuredSelection ...
if (selection instanceof IStructuredSelection && !selection.isEmpty()) {
final IStructuredSelection structuredSelection = (IStructuredSelection) selection;
MenuItem modiscoItem = new MenuItem(menu, SWT.CASCADE, index);
modiscoItem.setText(Messages.ContributionItemForMoDiscoMenu_discoverersMenuLabel);
// modiscoItem.setImage(getMoDiscoImage());
// Add MoDisco menu
final Menu modiscoMenu = new Menu(modiscoItem);
modiscoItem.setMenu(modiscoMenu);
modiscoMenu.addMenuListener(new MenuListener() {
public void menuShown(final MenuEvent event) {
for (MenuItem menuItem : modiscoMenu.getItems()) {
menuItem.dispose();
}
/*
* Items and sub-menus will only be available if they match
* selected resources.
*
* First, retrieve selected resource
*
* Second, check if available discoverers handle it
*
* Third, if discoverers list is not empty, we will create a
* menu item for each. For each menu item, we have to link
* menu action to menu event like usual menu.
*/
final List<DiscovererDescription> discoverers = new ArrayList<DiscovererDescription>();
// retrieve selected item
try {
/*
* for multiple selection, we have to check each
* selected object separately.
*/
Object[] selectedObjects = structuredSelection.toArray();
for (DiscovererDescription discoverer : IDiscoveryManager.INSTANCE
.getDiscoverers()) {
boolean applicable = true;
for (final Object selectedObject : selectedObjects) {
// check discoverer compatibility
try {
if (!IDiscoveryManager.INSTANCE.isApplicable(discoverer,
selectedObject)) {
applicable = false;
break;
}
} catch (Exception e) {
MoDiscoLogger.logError(e, Activator.getDefault());
}
}
if (applicable) {
discoverers.add(discoverer);
}
}
if (discoverers.size() > 0) {
// sort, in order to avoid random order each time
// the menu is created
Collections.sort(discoverers,
ContributionItemForMoDiscoMenu.DISCOVERERS_COMPARATOR);
for (DiscovererDescription discoverer : discoverers) {
// management of intermediate menu
createMenuForDiscoverer(discoverer, modiscoMenu, selectedObjects);
}
} else {
MenuItem discovererMenu = new MenuItem(modiscoMenu, SWT.PUSH);
discovererMenu
.setText(Messages.ContributionItemForMoDiscoMenu_noApplicableDiscoverer);
discovererMenu.setEnabled(false);
}
} catch (Exception e) {
MoDiscoLogger.logError(e, Activator.getDefault());
}
}
public void menuHidden(final MenuEvent e) {
//
}
});
}
}
private final void createMenuForDiscoverer(final DiscovererDescription discoverer,
final Menu modiscoMenu, final Object[] selectedObjects) {
Menu parentMenu = modiscoMenu;
DiscovererUI discovererUI = DiscovererUIRegistry.getInstance().getDiscovererUI(
discoverer.getId());
if (discovererUI == null) {
if (Platform.inDebugMode()) {
MoDiscoLogger
.logWarning(
"No discoverer UI defined for discoverer " + discoverer.getId() //$NON-NLS-1$
+ ". It will not appear in the MoDisco menu.", Activator.getDefault()); //$NON-NLS-1$
}
return;
}
final String[] pathParts;
if (discovererUI.getPath().length() == 0) {
pathParts = new String[0];
} else {
pathParts = discovererUI.getPath().split("/"); //$NON-NLS-1$
}
if (pathParts.length > 0) {
for (String pathEntry : pathParts) {
MenuItem intermediateMenu = null;
for (MenuItem item : parentMenu.getItems()) {
if (item.getText().equalsIgnoreCase(pathEntry)) {
intermediateMenu = item;
}
}
if (intermediateMenu == null) {
intermediateMenu = new MenuItem(parentMenu, SWT.CASCADE,
parentMenu.getItemCount());
intermediateMenu.setText(pathEntry);
parentMenu = new Menu(intermediateMenu);
intermediateMenu.setMenu(parentMenu);
} else {
parentMenu = intermediateMenu.getMenu();
}
}
}
// final menu
MenuItem discovererMenu = new MenuItem(parentMenu, SWT.PUSH, 0);
String label = discovererUI.getLabel();
if (!label.trim().endsWith("...")) { //$NON-NLS-1$
if (!MoDiscoMenuSelectionListener.getExpectedInputParameters(discoverer).isEmpty()) {
// add ellipsis to follow Eclipse guidelines for an item that
// opens a dialog before doing something
label += "..."; //$NON-NLS-1$
}
}
discovererMenu.setText(label);
if (discovererUI.getImageIcon() != null) {
discovererMenu.setImage(discovererUI.getImageIcon());
}
MoDiscoMenuSelectionListener handler = new MoDiscoMenuSelectionListener(discoverer,
selectedObjects, this.shell);
discovererMenu.addSelectionListener(handler);
}
// private Image image;
// private final Image getMoDiscoImage() {
// if (this.image == null) {
// ImageDescriptor descriptor = Activator.getImageDescriptor("icons/discoverer16x16.png"); //$NON-NLS-1$
// if (descriptor != null) {
// this.image = descriptor.createImage();
// }
// }
// return this.image;
// }
@Override
public boolean isDynamic() {
return true;
}
private static final Comparator<DiscovererDescription> DISCOVERERS_COMPARATOR = new Comparator<DiscovererDescription>() {
public int compare(final DiscovererDescription o1, final DiscovererDescription o2) {
String str1 = null;
String str2 = null;
if (o1 != null && o1.getId() != null) {
DiscovererUI ui1 = DiscovererUIRegistry.getInstance().getDiscovererUI(o1.getId());
if (ui1 != null) {
str1 = ui1.getLabel();
}
}
if (str1 == null) {
return 1;
}
if (o2 != null && o2.getId() != null) {
DiscovererUI ui2 = DiscovererUIRegistry.getInstance().getDiscovererUI(o2.getId());
if (ui2 != null) {
str2 = ui2.getLabel();
}
}
if (str2 == null) {
return -1;
}
return str2.compareToIgnoreCase(str1);
}
};
}