blob: f0a36b236fd87c1766ea97037ce01e40acd0d5db [file] [log] [blame]
package org.eclipse.scout.sdk.ui.menu;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import org.eclipse.core.commands.Command;
import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.scout.commons.holders.BooleanHolder;
import org.eclipse.scout.sdk.ui.action.IScoutHandler;
import org.eclipse.scout.sdk.ui.extensions.IContextMenuContributor;
import org.eclipse.scout.sdk.ui.internal.ScoutSdkUi;
import org.eclipse.scout.sdk.ui.internal.extensions.ContextMenuContributorExtensionPoint;
import org.eclipse.scout.sdk.ui.view.outline.pages.IPage;
import org.eclipse.ui.services.IServiceLocator;
public class MenuVisibilityTester extends PropertyTester {
private final static int MENU_PREPARATION_MAX_DURATION = 15; // ms
private static <T> boolean contains(T[] list, T toSearch) {
if (list == null) return false;
for (T t : list) {
if (t != null && t.equals(toSearch)) return true;
}
return false;
}
private static IContextMenuContributor getMenuContributor(Class<? extends IScoutHandler> menu, IPage p) {
for (IContextMenuContributor c : ContextMenuContributorExtensionPoint.getContextMenuContributors(p)) {
try {
Class<? extends IScoutHandler>[] menus = c.getSupportedMenuActionsFor(p);
if (contains(menus, menu)) {
return c;
}
}
catch (Throwable t) {
ScoutSdkUi.logError("Could not get supported menues for extension '" + c.toString() + "'!");
}
}
return null;
}
private static HashMap<IPage, IContextMenuContributor> getMenuContributorsForAllPages(Class<? extends IScoutHandler> menu, List<IPage> pages) {
HashMap<IPage, IContextMenuContributor> mapping = new HashMap<IPage, IContextMenuContributor>();
for (IPage p : pages) {
IContextMenuContributor c = getMenuContributor(menu, p);
mapping.put(p, c);
}
return mapping;
}
private static void prepareMenu(IScoutHandler menu, HashMap<IPage, IContextMenuContributor> contributors) {
for (Entry<IPage, IContextMenuContributor> entry : contributors.entrySet()) {
entry.getValue().prepareMenuAction(entry.getKey(), menu);
}
}
private static boolean isMenuAvailableInAllPages(HashMap<IPage, IContextMenuContributor> contributors) {
for (IContextMenuContributor c : contributors.values()) {
if (c == null) return false;
}
return true;
}
private static List<IPage> getFilteredSelection(Collection<?> c) {
ArrayList<IPage> ret = new ArrayList<IPage>(c.size());
for (Object o : c) {
if (o instanceof IPage) {
ret.add((IPage) o);
}
}
return ret;
}
@SuppressWarnings("unchecked")
@Override
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
if (receiver instanceof StructuredSelection) {
receiver = ((StructuredSelection) receiver).toList();
}
if (receiver instanceof Collection && args != null && args.length == 3 && args[0] instanceof Class && args[1] instanceof Command && args[2] instanceof IServiceLocator) {
if (IScoutHandler.class.isAssignableFrom((Class<?>) args[0])) {
List<IPage> selectedNodes = getFilteredSelection((Collection<?>) receiver);
if (selectedNodes.size() == 0) {
return false;
}
else {
try {
// get class of current menu
Class<? extends IScoutHandler> currentMenuClass = (Class<? extends IScoutHandler>) args[0];
Command cmd = (Command) args[1];
// for each page in the selection: get a contributor that supports the menu
HashMap<IPage, IContextMenuContributor> contributors = getMenuContributorsForAllPages(currentMenuClass, selectedNodes);
// check if a contributor is available for each selected page (if not: the menu is not supported by each selected node)
if (!isMenuAvailableInAllPages(contributors)) return false;
IScoutHandler currentMenu = ScoutMenuContributionItemFactory.getMenuInstance(currentMenuClass);
if (currentMenu == null) return false; // no instance could be created -> do not show the menu
cmd.setHandler(currentMenu);
// check for multi select
if (!currentMenu.isMultiSelectSupported() && selectedNodes.size() > 1) return false;
// prepare the menu
prepareMenu(currentMenu, contributors);
long menuPreparationStartTime = System.currentTimeMillis();
// check if menu is visible
if (!currentMenu.isVisible()) return false;
// evaluate the enabled state after the menu has been prepared
currentMenu.setEnabled(new BooleanHolder(currentMenu.isActive()));
long duration = System.currentTimeMillis() - menuPreparationStartTime;
if (duration > MENU_PREPARATION_MAX_DURATION) {
// preparation of a menu should not take longer than 10ms
ScoutSdkUi.logWarning("Context menu '" + currentMenuClass.getName() + "' took longer than " + MENU_PREPARATION_MAX_DURATION + "ms to calculate its state (" + duration + "ms).");
}
// if we come here, all selected rows support the current menu and the menu is visible and prepared: enable the handler
IServiceLocator serviceLocator = (IServiceLocator) args[2];
ScoutMenuContributionItemFactory.activateHandler(serviceLocator, currentMenu);
// register the key stroke
ScoutMenuContributionItemFactory.registerKeyStroke(currentMenu.getKeyStroke(), cmd);
return true;
}
catch (Exception e) {
ScoutSdkUi.logError(e);
}
}
}
}
return false;
}
}