/******************************************************************************* * Copyright Technophobia Ltd 2012 * * This file is part of the Substeps Eclipse Plugin. * * The Substeps Eclipse Plugin is free software: you can redistribute it and/or modify * it under the terms of the Eclipse Public License v1.0. * * The Substeps Eclipse Plugin is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Eclipse Public License for more details. * * You should have received a copy of the Eclipse Public License * along with the Substeps Eclipse Plugin. If not, see <http://www.eclipse.org/legal/epl-v10.html>. ******************************************************************************/ package com.technophobia.substeps.test.component.general; import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withMnemonic; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.instanceOf; import java.util.Arrays; 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.swtbot.swt.finder.exceptions.WidgetNotFoundException; import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; 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.hamcrest.Matcher; /** * This helper is a workaround for a bug in SWTBot, where the bot can't find a * dynamically created context menu * * @author Stefan Seelmann (initial) * @author Stefan Schaefer (extension) */ public class ContextMenuHelper { /** * Clicks the context menu matching the text. * * @param text * the text on the context menu. * @throws WidgetNotFoundException * if the widget is not found. */ public static void clickContextMenu(final AbstractSWTBot<?> bot, final String... texts) { // show final MenuItem menuItem = UIThreadRunnable.syncExec(new WidgetResult<MenuItem>() { @Override public MenuItem run() { MenuItem mItem = null; final Control control = (Control) bot.widget; // MenuDetectEvent added by Stefan Schaefer final Event event = new Event(); control.notifyListeners(SWT.MenuDetect, event); if (!event.doit) { return null; } Menu menu = control.getMenu(); for (final String text : texts) { @SuppressWarnings("unchecked") final Matcher<?> matcher = allOf(instanceOf(MenuItem.class), withMnemonic(text)); mItem = show(menu, matcher); if (mItem != null) { menu = mItem.getMenu(); } else { hide(menu); break; } } return mItem; } }); if (menuItem == null) { throw new WidgetNotFoundException("Could not find menu: " + Arrays.asList(texts)); } // click click(menuItem); // hide UIThreadRunnable.syncExec(new VoidResult() { @Override public void run() { hide(menuItem.getParent()); } }); } private static MenuItem show(final Menu menu, final Matcher<?> matcher) { if (menu != null) { menu.notifyListeners(SWT.Show, new Event()); final MenuItem[] items = menu.getItems(); 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()); } } }