/******************************************************************************* * Copyright (c) 2012 Google, Inc. * 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: * Google, Inc. - initial API and implementation *******************************************************************************/ package com.windowtester.runtime.swt.internal.selector; import com.windowtester.internal.runtime.provisional.WTInternal; import com.windowtester.runtime.MultipleWidgetsFoundException; import com.windowtester.runtime.WT; import com.windowtester.runtime.WidgetNotFoundException; import com.windowtester.runtime.swt.internal.abbot.matcher.NameOrLabelMatcher; import com.windowtester.runtime.swt.internal.operation.SWTKeyOperation; import com.windowtester.runtime.swt.internal.operation.SWTLocation; import com.windowtester.runtime.swt.internal.operation.SWTMouseOperation; import com.windowtester.runtime.swt.internal.operation.SWTShowMenuBarOperation; import com.windowtester.runtime.swt.internal.operation.SWTShowMenuOperation; import com.windowtester.runtime.swt.internal.operation.SWTShowViewMenuOperation; import com.windowtester.runtime.swt.internal.operation.SWTWidgetLocation; import com.windowtester.runtime.swt.internal.widgets.MenuItemReference; import com.windowtester.runtime.swt.internal.widgets.ToolItemReference; import com.windowtester.runtime.util.ScreenCapture; import com.windowtester.runtime.util.StringComparator; import com.windowtester.swt.util.PathStringTokenizerUtil; /** * A consolidation of the {@link PopupMenuSelector2} and {@link MenuItemSelector} classes * * @author Dan Rubel */ public class SWTMenuSelector { /** * Select the specified top level menu item(s) from the active window's menu bar * * @param menuItemPath the slash separated path indicating the menu item(s) to be * selected * @return the last menu item that was selected */ public MenuItemReference selectMenu(String menuItemPath) throws MultipleWidgetsFoundException, WidgetNotFoundException { return resolveAndSelect(new SWTShowMenuBarOperation().openMenuBar(), menuItemPath); } /** * Open the menu associated with the specified tool item and select the specified menu * item(s) * * @param itemRef the tool item with the associated menu * @param menuItemPath the slash separated path indicating the menu item(s) to be * selected * @return the last menu item that was selected */ public MenuItemReference selectToolItemMenu(ToolItemReference itemRef, String menuItemPath) throws MultipleWidgetsFoundException, WidgetNotFoundException { return resolveAndSelect(new SWTShowMenuOperation().openMenuClick(WT.BUTTON1, new SWTWidgetLocation(itemRef, WTInternal.RIGHT).offset(-3, 0), false), menuItemPath); } /** * Open the menu associated with the specified view and select the specified menu * item(s) * * @param viewId the identifier of the view * @param menuItemPath the slash separated path indicating the menu item(s) to be * selected * @return the last menu item that was selected */ public MenuItemReference selectViewMenu(String viewId, String menuItemPath) throws MultipleWidgetsFoundException, WidgetNotFoundException { return resolveAndSelect(new SWTShowViewMenuOperation().openViewMenu(viewId), menuItemPath); } /** * Perform a context click at the specified location and select the specified menu * item(s) * * @param location the location at which the right click should occur to open the * context menu * @param pauseOnMouseDown <code>true</code> if the mouse down event should be * processed before the mouse up event is posted. * @param menuItemPath the slash separated path indicating the menu item(s) to be * selected * @return the last menu item that was selected */ public MenuItemReference contextClick(SWTLocation location, boolean pauseOnMouseDown, String menuItemPath) throws MultipleWidgetsFoundException, WidgetNotFoundException { return resolveAndSelect(new SWTShowMenuOperation().openMenuClick(WT.BUTTON3, location, pauseOnMouseDown), menuItemPath); } /** * Find the menu item(s) specified by the menu item path and select each one in * succession. This method assumes that the operation specified, when executed by this * method, opens the menu containing the first item to be selected. * * @param firstOp the operation that opens the menu containing the first item to be * selected. * @param menuItems the menu items in the currently open menu * @return the last menu item that was selected */ private MenuItemReference resolveAndSelect(SWTShowMenuOperation firstOp, String menuItemPath) throws MultipleWidgetsFoundException, WidgetNotFoundException { String[] elements = PathStringTokenizerUtil.tokenize(menuItemPath); int index = 0; try { firstOp.execute(); MenuItemReference itemRef = getNextMenuItem(firstOp.getMenuItems(), elements[index]); index++; // Click each cascading menu item and wait for the menu to appear while (index < elements.length) { SWTShowMenuOperation op = new SWTShowMenuOperation(); op.openMenuClick(WT.BUTTON1, new SWTWidgetLocation(itemRef, WTInternal.CENTER), false).execute(); itemRef = getNextMenuItem(op.getMenuItems(), elements[index]); index++; } // Select the last menu item using a standard click SWTMouseOperation op = new SWTMouseOperation(WT.BUTTON1); op.at(new SWTWidgetLocation(itemRef, WTInternal.CENTER)); op.execute(); index++; return itemRef; } // If any exception occurs, take a screenshot and close any open menus finally { if (index <= elements.length) { ScreenCapture.createScreenCapture(); // Close any open menus while (index > 0) { new SWTKeyOperation().keyCode(WT.ESC).execute(); index--; } } } } /** * Search the specified menu items for an item with text matching specified text * * @param items the menu items to be searched * @param itemText the text to be matched * @return the menu item with text matching the specified text */ private MenuItemReference getNextMenuItem(MenuItemReference[] items, String itemText) throws MultipleWidgetsFoundException, WidgetNotFoundException { // Get menu item text StringBuilder allItemText = new StringBuilder(128); String[] textForItems = new String[items.length]; for (int i = 0; i < items.length; i++) { String text = items[i].getText(); textForItems[i] = text; allItemText.append('\n'); allItemText.append(text); } // Look for an exact match MenuItemReference found = null; for (int i = 0; i < textForItems.length; i++) { if (itemText.equals(NameOrLabelMatcher.trimMenuText(textForItems[i]))) { if (found == null) found = items[i]; else throw new MultipleWidgetsFoundException("Multiple items found for " + itemText + " in " + allItemText); } } if (found != null) return found; // Look for a pattern match for (int i = 0; i < textForItems.length; i++) { if (StringComparator.matches(textForItems[i], itemText)) { if (found == null) found = items[i]; else throw new MultipleWidgetsFoundException("Multiple items found for " + itemText + " in " + allItemText); } } if (found != null) return found; throw new WidgetNotFoundException("No item found for " + itemText + " in " + allItemText); } }