package saros.stf.server.bot.widget; import static org.eclipse.swtbot.swt.finder.matchers.WithMnemonicRegex.withMnemonicRegex; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.instanceOf; import java.util.Arrays; import java.util.regex.Pattern; import org.apache.log4j.Logger; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Widget; import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException; import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; import org.eclipse.swtbot.swt.finder.results.BoolResult; import org.eclipse.swtbot.swt.finder.results.VoidResult; import org.eclipse.swtbot.swt.finder.results.WidgetResult; import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBot; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.hamcrest.Matcher; public class ContextMenuHelper { private static final Logger log = Logger.getLogger(ContextMenuHelper.class); /** * Clicks the context menu item matching the text nodes. * * @param bot a SWTBot class that wraps a {@link Widget} which extends {@link Control}. E.g. * {@link SWTBotTree}. * @param nodes the nodes of the context menu e.g New, Class * @throws WidgetNotFoundException if the widget is not found. */ public static void clickContextMenu( final AbstractSWTBot<? extends Control> bot, final String... nodes) { clickContextMenuWithRegEx(bot, quote(nodes)); } /** * Clicks the context menu item matching the text nodes with regular expression. * * @param bot a SWTBot class that wraps a {@link Widget} which extends {@link Control}. E.g. * {@link SWTBotTree}. * @param nodes the nodes of the context menu e.g New, Class * @throws WidgetNotFoundException if the widget is not found. */ public static void clickContextMenuWithRegEx( final AbstractSWTBot<? extends Control> bot, final String... nodes) { final MenuItem menuItem = getMenuItemWithRegEx(bot, nodes); // show if (menuItem == null) { throw new WidgetNotFoundException("Could not find menu with regex: " + Arrays.asList(nodes)); } // click click(menuItem); // hide UIThreadRunnable.syncExec( new VoidResult() { @Override public void run() { hide(menuItem.getParent()); } }); } /** * Checks if the context menu item matching the text nodes exists. * * @param bot a SWTBot class that wraps a {@link Widget} which extends {@link Control}. E.g. * {@link SWTBotTree}. * @param nodes the nodes of the context menu e.g New, Class * @return <tt>true</tt> if the context menu item exists, <tt>false</tt> otherwise */ public static boolean existsContextMenu( final AbstractSWTBot<? extends Control> bot, final String... nodes) { final MenuItem menuItem = getMenuItemWithRegEx(bot, quote(nodes)); // hide if (menuItem != null) { UIThreadRunnable.syncExec( new VoidResult() { @Override public void run() { hide(menuItem.getParent()); } }); return true; } return false; } /** * Checks if the context menu item matching the text nodes is enabled. * * @param bot a SWTBot class that wraps a {@link Widget} which extends {@link Control}. E.g. * {@link SWTBotTree}. * @param nodes the nodes of the context menu e.g New, Class * @return <tt>true</tt> if the context menu item is enabled, <tt>false</tt> otherwise * @throws WidgetNotFoundException if the widget is not found. */ public static boolean isContextMenuEnabled( final AbstractSWTBot<? extends Control> bot, final String... nodes) { final MenuItem menuItem = getMenuItemWithRegEx(bot, quote(nodes)); // show if (menuItem == null) { throw new WidgetNotFoundException("could not find menu: " + Arrays.asList(nodes)); } return UIThreadRunnable.syncExec( new BoolResult() { @Override public Boolean run() { boolean enabled = menuItem.isEnabled(); hide(menuItem.getParent()); return enabled; } }); } private static MenuItem show(final Menu menu, final Matcher<?> matcher) { if (menu != null) { menu.notifyListeners(SWT.Show, new Event()); MenuItem[] items = menu.getItems(); if (log.isTraceEnabled()) { for (final MenuItem menuItem : items) log.trace( "found context menu item: " + menuItem.getText() + "[enabled=" + menuItem.isEnabled() + "]"); } for (final MenuItem menuItem : items) { if (matcher.matches(menuItem)) { return menuItem; } } menu.notifyListeners(SWT.Hide, new Event()); } return null; } private static void click(final MenuItem menuItem) { final Event event = new Event(); event.time = (int) System.currentTimeMillis(); event.widget = menuItem; event.display = menuItem.getDisplay(); event.type = SWT.Selection; UIThreadRunnable.asyncExec( menuItem.getDisplay(), new VoidResult() { @Override public void run() { menuItem.notifyListeners(SWT.Selection, event); } }); } private static void hide(final Menu menu) { menu.notifyListeners(SWT.Hide, new Event()); if (menu.getParentMenu() != null) { hide(menu.getParentMenu()); } } private static MenuItem getMenuItemWithRegEx( final AbstractSWTBot<? extends Control> bot, final String... texts) { final MenuItem menuItem = UIThreadRunnable.syncExec( new WidgetResult<MenuItem>() { @Override public MenuItem run() { MenuItem menuItem = null; Control control = bot.widget; Event event = new Event(); control.notifyListeners(SWT.MenuDetect, event); if (!event.doit) { return null; } Menu menu = control.getMenu(); for (String text : texts) { Matcher<?> matcher = allOf(instanceOf(MenuItem.class), withMnemonicRegex(text)); menuItem = show(menu, matcher); if (menuItem != null) menu = menuItem.getMenu(); else break; } return menuItem; } }); return menuItem; } private static String[] quote(String[] text) { final String[] quotedText = new String[text.length]; for (int i = 0; i < text.length; i++) quotedText[i] = Pattern.quote(text[i]); return quotedText; } }