/******************************************************************************* * 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; import java.awt.event.InputEvent; import java.io.IOException; import java.io.LineNumberReader; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Widget; import com.windowtester.internal.debug.IRuntimePluginTraceOptions; import com.windowtester.internal.debug.TraceHandler; import com.windowtester.internal.runtime.Diagnostic; import com.windowtester.internal.runtime.ISelectionTarget; import com.windowtester.internal.runtime.Platform; import com.windowtester.internal.runtime.UIContextCommon; import com.windowtester.internal.runtime.condition.ConditionMonitor; import com.windowtester.internal.runtime.locator.IDefaultUISelectorFactory; import com.windowtester.internal.runtime.locator.IUISelector; import com.windowtester.internal.runtime.locator.IUISelector2; import com.windowtester.internal.runtime.selector.ClickHelper; import com.windowtester.internal.runtime.selector.IClickDriver; import com.windowtester.internal.runtime.system.WidgetSystem; import com.windowtester.internal.swing.UIContextSwing; import com.windowtester.internal.swing.UIContextSwingFactory; import com.windowtester.runtime.IAdaptable; import com.windowtester.runtime.IClickDescription; import com.windowtester.runtime.IUIContext; import com.windowtester.runtime.MultipleWidgetsFoundException; import com.windowtester.runtime.WT; import com.windowtester.runtime.WaitTimedOutException; import com.windowtester.runtime.WidgetNotFoundException; import com.windowtester.runtime.WidgetSearchException; import com.windowtester.runtime.condition.ICondition; import com.windowtester.runtime.condition.IConditionMonitor; import com.windowtester.runtime.internal.factory.WTRuntimeManager; import com.windowtester.runtime.locator.ILocator; import com.windowtester.runtime.locator.IMenuItemLocator; import com.windowtester.runtime.locator.IWidgetLocator; import com.windowtester.runtime.locator.IWidgetReference; import com.windowtester.runtime.locator.WidgetReference; import com.windowtester.runtime.locator.XYLocator; import com.windowtester.runtime.monitor.IUIThreadMonitor; import com.windowtester.runtime.swing.SwingWidgetLocator; import com.windowtester.runtime.swt.condition.shell.IShellMonitor; import com.windowtester.runtime.swt.internal.application.ApplicationContext; import com.windowtester.runtime.swt.internal.condition.shell.ShellMonitor; import com.windowtester.runtime.swt.internal.debug.LogHandler; import com.windowtester.runtime.swt.internal.dnd.DragAndDropHelper; import com.windowtester.runtime.swt.internal.finder.ShellFinder; import com.windowtester.runtime.swt.internal.hover.HoverInfo; import com.windowtester.runtime.swt.internal.hover.IHoverInfo; import com.windowtester.runtime.swt.internal.locator.ICloseableLocator; import com.windowtester.runtime.swt.internal.monitor.UIThreadMonitorSWT; import com.windowtester.runtime.swt.internal.operation.effects.PlaybackAdvisor; import com.windowtester.runtime.swt.internal.preferences.PlaybackSettings; import com.windowtester.runtime.swt.internal.selection.SelectionTarget; import com.windowtester.runtime.swt.internal.selector.DefaultSWTWidgetSelector; import com.windowtester.runtime.swt.internal.selector.ListHelper; import com.windowtester.runtime.swt.internal.selector.UIDriver; import com.windowtester.runtime.swt.internal.text.TextEntryStrategy; import com.windowtester.runtime.swt.internal.widgets.finder.SWTWidgetFinder; import com.windowtester.runtime.util.ScreenCapture; import com.windowtester.runtime.util.TestMonitor; /** * Abstract implementation of {@link com.windowtester.runtime.IUIContext}. * */ public class UIContextSWT extends UIContextCommon { //a default value for cases where no button mask is specified private static final int DEFAULT_BUTTON_MASK = WT.BUTTON1; private final UIDriver _driver = new UIDriver(); // private final HighlightingDriver _highlightingDriver = new HighlightingDriver(); private IUIThreadMonitor _threadMonitor; private Display _display; private ShellMonitor _shellMonitor; private ActionDirector _director; private DragAndDropHelper _dndHelper; //private TextDriver textDriver = new TextDriver(this); /* package */ final ApplicationContext applicationContext = new ApplicationContext(); final ClickManager clickManager = new ClickManager(); //number of find retry attempts private int _findAttempts; //////////////////////////////////////////////////////////////////////////// // // System set-up // //////////////////////////////////////////////////////////////////////////// { WidgetSystem.addDefaultSelector(new IDefaultUISelectorFactory() { public IUISelector create(Object widget) { if (widget instanceof IWidgetReference) widget = ((IWidgetReference)widget).getWidget(); if (widget instanceof Widget) return new DefaultSWTWidgetSelector(); return null; } }); getClickDriver().addClickListener(clickManager); } //used to manage clicks for DND operations class ClickManager implements IClickDriver.Listener { //TODO: overriding click makes this go away? public void clicked(IClickDescription click, IWidgetLocator clicked) { cacheTargetInfo(click, clicked); } public void contextClicked(IClickDescription click, IWidgetLocator clicked) { cacheTargetInfo(click, clicked); } private void cacheTargetInfo(IClickDescription click, IWidgetLocator clicked) { //this greedy try-catch is a safety against failures here that should just go ignored try { Widget widget = null; if (clicked instanceof IWidgetReference){ Object refPayload = ((IWidgetReference)clicked).getWidget(); if (refPayload instanceof Widget) widget = (Widget) refPayload; } //only re-find if the reference did not carry a widget if (widget == null) widget = findWidget(clicked); //in case there is no widget found, we default to the current location if (widget == null) cacheInfoFromCurrentCursorLocation(); else cacheInfoFromClick(click, widget); } catch (Exception e) { LogHandler.log(e); } } void cacheInfoFromCurrentCursorLocation() { getDriver().setMouseHoverInfo(HoverInfo.getAbsolute(UIDriver.getCurrentCursorLocation())); return; } private void cacheInfoFromClick(IClickDescription click, Widget widget) { /* * TODO: this involves an extra bounds calculation -- we should remove this... * The issue is that since actions that were once in the UIDriver have become decentralized, this is a bit * tricky. Anyway, definitely "todo". */ Point location = UIDriver.getLocation(widget); if (location == null) location = UIDriver.getCurrentCursorLocation(); if (!click.isDefaultCenterClick()) { location.x += click.x(); location.y += click.y(); } IHoverInfo hover = HoverInfo.getAbsolute(location); getDriver().setMouseHoverInfo(hover); } } //////////////////////////////////////////////////////////////////////////// // // Accessors // //////////////////////////////////////////////////////////////////////////// /** * Answer the display associated with the receiver. * * @return the display or <code>null</code> if it has not been set */ public Display getDisplay() { return _display; } /** * Set the display associated with the receiver. * * @param display the display (not <code>null</code>) */ public void setDisplay(Display display) { if (display == null) throw new IllegalArgumentException("display cannot be null"); _display = display; // pre-configure platform specific information ListHelper.calculateItemListSpacing(display); //start menu watcher // MenuWatcher.getInstance(display).startWatching(); } ActionDirector getDirector() { if (_director == null) _director = new ActionDirector(this); return _director; } protected DragAndDropHelper getDNDHelper() { if (_dndHelper == null) _dndHelper = new DragAndDropHelper(this); return _dndHelper; } // ////////////////////////////////////////////////////////////////////////// // // Adaptation // // ////////////////////////////////////////////////////////////////////////// /** * Override the superclass implementation to return an SWT appropriate thread monitor * and check the SWT adapter factor before calling super. * * @see IUIContext#getAdapter(java.lang.Class) */ public Object getAdapter(Class<?> adapter) { if (adapter == IShellMonitor.class) return getShellMonitor(); // UIContextSwing if (adapter.equals(UIContextSwing.class)){ return UIContextSwingFactory.createContext(); } //add compatibility to NEW generic interface if (adapter.equals(IUIThreadMonitor.class) || adapter.equals(com.windowtester.runtime.monitor.IUIThreadMonitor.class) || adapter.getName().equals("com.windowtester.swt.monitor.IUIThreadMonitor")) { //NOTE: access by name is required because a legacy interface has been moved OUT of this plugin //into the compatibility layer if (_threadMonitor == null) _threadMonitor = new UIThreadMonitorSWT(this, _display); return _threadMonitor; } if (adapter.equals(PlaybackSettings.class)) return getPlaybackSettings(); if (adapter.equals(UIDriver.class)) return getDriver(); Object result = AdapterFactory.getInstance().getAdapter(this, adapter); if (result != null) return result; return super.getAdapter(adapter); } // ////////////////////////////////////////////////////////////////////////// // // UI actions // // ////////////////////////////////////////////////////////////////////////// /* (non-Javadoc) * @see com.windowtester.internal.runtime.UIContextCommon#click(com.windowtester.runtime.locator.ILocator) */ public IWidgetLocator click(ILocator locator) throws WidgetSearchException { /* * An unfortunate feature of the new API is that we have 2 classes named MenuItemLocator that subclass ILocator * The rub is that only the swt version knows how to perform the click. * To guard against users using the runtime version when they MEAN the SWT * version, we do a little adaptation. * * */ if (locator instanceof com.windowtester.runtime.locator.MenuItemLocator) { com.windowtester.runtime.locator.MenuItemLocator pathLocator = (com.windowtester.runtime.locator.MenuItemLocator)locator; locator = new com.windowtester.runtime.swt.locator.MenuItemLocator(pathLocator.getPath()); } handleConditions(); return super.click(locator); } /* (non-Javadoc) * @see com.windowtester.internal.runtime.UIContextCommon#click(int, com.windowtester.runtime.locator.ILocator, int) */ public IWidgetLocator click(int clickCount, ILocator locator, int buttonMask) throws WidgetSearchException { handleConditions(); //mouseMove(locator); // If this is a Swing locator, then redirect it to the Swing UI context // TODO: Move "_swingContext" field and associated code from UIContext into this class if (locator instanceof SwingWidgetLocator // TODO: hack to handle XYLocators... need a polymorphic approach or better SWT/Swing integration || (locator instanceof XYLocator && ((XYLocator) locator).locator() instanceof SwingWidgetLocator) ) { UIContextSwing uiSwing = (UIContextSwing) getAdapter(UIContextSwing.class); // Must translate SWT button mask to Swing button mask int swingButtonMask = InputEvent.BUTTON1_MASK; if ((buttonMask & WT.BUTTON2) != 0) swingButtonMask = InputEvent.BUTTON2_MASK; if ((buttonMask & WT.SHIFT) != 0) swingButtonMask &= InputEvent.SHIFT_MASK; if ((buttonMask & WT.CTRL) != 0) swingButtonMask &= InputEvent.CTRL_MASK; if ((buttonMask & WT.ALT) != 0) swingButtonMask &= InputEvent.ALT_MASK; return uiSwing.click(clickCount, locator, swingButtonMask); } return clicked(super.click(clickCount, locator, buttonMask)); } /* (non-Javadoc) * @see com.windowtester.internal.runtime.UIContextCommon#click(int, com.windowtester.runtime.locator.ILocator) */ public IWidgetLocator click(int clickCount, ILocator locator) throws WidgetSearchException { handleConditions(); return super.click(clickCount, locator); } /* (non-Javadoc) * @see com.windowtester.internal.runtime.UIContextCommon#contextClick(com.windowtester.runtime.locator.ILocator, com.windowtester.runtime.locator.IMenuItemLocator) */ public IWidgetLocator contextClick(ILocator locator, IMenuItemLocator menuItem) throws WidgetSearchException { handleConditions(); return super.contextClick(locator, menuItem); } /* (non-Javadoc) * @see com.windowtester.internal.runtime.UIContextCommon#contextClick(com.windowtester.runtime.locator.ILocator, com.windowtester.runtime.locator.IMenuItemLocator, int) */ public IWidgetLocator contextClick(ILocator locator, IMenuItemLocator menuItem, int modifierMask) throws WidgetSearchException { handleConditions(); return super.contextClick(locator, menuItem, modifierMask); } /* (non-Javadoc) * @see com.windowtester.internal.runtime.UIContextCommon#contextClick(com.windowtester.runtime.locator.ILocator, java.lang.String) */ public IWidgetLocator contextClick(ILocator locator, String menuItem) throws WidgetSearchException { handleConditions(); return super.contextClick(locator, menuItem); } /* (non-Javadoc) * @see com.windowtester.internal.runtime.UIContextCommon#contextClick(com.windowtester.runtime.locator.ILocator, java.lang.String, int) */ public IWidgetLocator contextClick(ILocator locator, String menuItem, int modifierMask) throws WidgetSearchException { handleConditions(); return super.contextClick(locator, menuItem, modifierMask); } /** * A hook for post-processing clicked widgets before returning them to the client. */ private IWidgetLocator clicked(IWidgetLocator click) { PlaybackAdvisor.getDefault().postClickPause(); return click; } /////////////////////////////////////////////////////////////////////////// // // Text entry actions // /////////////////////////////////////////////////////////////////////////// /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#enterText(java.lang.String) */ public void enterText(String txt) { handleConditions(); //temporary call out to pluggable text entry strategy //getDriver().enterText(txt); TextEntryStrategy.getCurrent().enterText(this, txt); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#keyClick(int) */ public void keyClick(int key) { handleConditions(); getDriver().keyClick(key); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#keyClick(char) */ public void keyClick(char key) { handleConditions(); getDriver().keyClick(key); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#keyClick(int, char) */ public void keyClick(int ctrl, char c) { handleConditions(); getDriver().keyClick(ctrl, c); } /////////////////////////////////////////////////////////////////////////// // // Move/selection // /////////////////////////////////////////////////////////////////////////// /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#mouseMove(com.windowtester.runtime.locator.ILocator) */ public IWidgetLocator mouseMove(ILocator locator) throws WidgetSearchException { handleConditions(); ISelectionTarget target = getTarget(locator); return doMouseMove(target); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#dragTo(com.windowtester.runtime.locator.ILocator) */ public IWidgetLocator dragTo(ILocator locator) throws WidgetSearchException { handleConditions(); ISelectionTarget target = getTarget(locator); IUISelector2 selector2 = adaptToSelector2(locator); if (selector2 != null) { return selector2.dragTo(this, target); } //we need a pause lest the OS interpret the drag mouseDown as a double click UIDriver.pause(1000); //<-- we use the driver to avoid triggering conditions return doDragTo(target); } private IUISelector2 adaptToSelector2(ILocator locator) { locator = ClickHelper.getWidgetLocator(locator); //parses out XYs if (locator instanceof IUISelector2) return (IUISelector2)locator; if (locator instanceof IAdaptable) return (IUISelector2) ((IAdaptable)locator).getAdapter(IUISelector2.class); return null; } private IWidgetLocator doDragTo(ISelectionTarget target) throws WidgetSearchException { IClickDescription click = target.getClickDescription(); IWidgetLocator locator = target.getWidgetLocator(); Widget w = findWidget(locator); //drag and wrapper the result in a widget reference Widget dropTarget = click.isDefaultCenterClick() ? dragTo(w) : dragTo(w, click.x(), click.y()); return WidgetReference.create(dropTarget); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#dragTo(com.windowtester.runtime.locator.ILocator, int) */ public IWidgetLocator dragTo(ILocator locator, int mods) throws WidgetSearchException { /* * This is a bit tricky since we don't want to handle conditions WHILE a key is * down and the actual drag is being done in a subclass who is free to handle conditions... * * The current work-around is to "go native" * */ //LogHandler.log("modifiers in dragTo ignored -- not implemented"); //go native so that conditions are not handled while the key is down boolean isStatePreDragNative = applicationContext.isNative(); //cache for restore applicationContext.setNative(); try { getDriver().mouseDown(mods); return dragTo(locator); } finally { getDriver().mouseUp(mods); //restore state if (!isStatePreDragNative) applicationContext.setDefault(); } } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#close(com.windowtester.runtime.locator.IWidgetLocator) */ public void close(IWidgetLocator locator) throws WidgetSearchException { ICloseableLocator closeable = getCloseable(locator); if (closeable != null) { closeable.doClose(this); return; } //conditions handled in the close //handleConditions(); Widget widget = findWidget(locator); if (widget == null) throw new WidgetSearchException("target of a close call must not be null"); if (!(widget instanceof Shell)) throw new WidgetSearchException("target of a close call must be a Shell, got a: " + widget.getClass() + " instead"); close((Shell)widget); } private ICloseableLocator getCloseable(IWidgetLocator locator) { if (locator instanceof ICloseableLocator) return (ICloseableLocator)locator; if (locator instanceof IAdaptable) return (ICloseableLocator) ((IAdaptable)locator).getAdapter(ICloseableLocator.class); return null; } //close the given shell protected void close(Shell shell) { handleConditions(); getDriver().close(shell); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#setFocus(com.windowtester.runtime.locator.IWidgetLocator) */ /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#find(com.windowtester.runtime.locator.IWidgetLocator) */ public IWidgetLocator find(IWidgetLocator locator) throws WidgetSearchException { /* * TODO: remove _findAttempts as a field and refactor to a parameter of a second * find helper method */ handleConditions(); IWidgetLocator[] locators = findAll(locator); //success condition if (locators.length == 1) { _findAttempts = 0; IWidgetReference ref = (IWidgetReference)locators[0]; //test for raw/generic reference case and upgrade as needed Object widget = ref.getWidget(); if (widget instanceof Widget && ref.getClass().equals(WidgetReference.class)) { ref = WTRuntimeManager.asReference(widget); } // // TODO[pq]: this special case should be fixed -- rub: hyperlink refs are NOT widgets... // IWidgetReference<?> ref = (IWidgetReference<?>)locators[0]; //// System.out.println("UIContextSWT.find(): " + ref); // Object widget = ref.getWidget(); // if (!(widget instanceof Widget)) // return ref; // System.out.println("+++ adapting: " + ref); // HERE: thought : really only want to upgrade if it's a legacy WidgetReference instance... // // TODO[pq]: this translation will not be needed when the finder is replaced // return SWTWidgets.asReference((Widget)widget); return ref; } //update attempt number and possibly try again if (_findAttempts++ < SWTWidgetFinder.getMaxFinderRetries()) { TraceHandler.trace(IRuntimePluginTraceOptions.BASIC, "UIContextSWT failed to find widget (" + locator + ") retrying [" + _findAttempts + "/" + SWTWidgetFinder.getMaxFinderRetries() +"]"); pause(SWTWidgetFinder.getFinderRetryInterval()); return find(locator); } //in the error case, handle cleanup before throwing the exception handleCleanup(); //be sure to reset find attempts for next find _findAttempts = 0; if (locators.length > 1) { StringBuffer buf = new StringBuffer(200); buf.append("Multiple Widgets Found:\nlooking for\n "); buf.append(locator.toString()); buf.append("\nand found:"); for (int i = 0; i < locators.length; i++) { buf.append("\n "); try { buf.append(getToStringOnUIThread(locators[i])); } catch (Exception e) { buf.append(locators[i].getClass() + " - " + e); } } throw new MultipleWidgetsFoundException(buf.toString()); } throw new WidgetNotFoundException("Widget NOT Found:\n" + locator.toString()); } /** * Handle cleanup. Consider making this protected so subclasses can override. */ private void handleCleanup() { takeScreenShot(); closeOpenShells(); } private void closeOpenShells() { new ExceptionHandlingHelper(_display, true, this).closeOpenShells(); } private void takeScreenShot() { String testcaseID = TestMonitor.getInstance().getCurrentTestCaseID(); TraceHandler.trace(IRuntimePluginTraceOptions.WIDGET_SELECTION, "Creating screenshot for testcase: " + testcaseID); //TODO: make this filename format user configurable ScreenCapture.createScreenCapture(testcaseID /*+ "_" + desc*/); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#findAll(com.windowtester.runtime.locator.IWidgetLocator) */ public IWidgetLocator[] findAll(IWidgetLocator locator) { handleConditions(); return (IWidgetLocator[])locator.findAll(this); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#getActiveWindow() */ public Object getActiveWindow() { handleConditions(); Display display = getDisplay(); if (display == null) display = Display.getDefault(); return ShellFinder.getActiveShell(display); } /////////////////////////////////////////////////////////////////////////// // // Selection helpers // /////////////////////////////////////////////////////////////////////////// private IWidgetLocator doMouseMove(ISelectionTarget target) throws WidgetSearchException { IWidgetLocator hoverTarget = getDirector().doMouseMove(target); //this is a bit of a kludge --- the idea is to update the cached target info for drag and drops clickManager.cacheInfoFromCurrentCursorLocation(); return hoverTarget; } IWidgetLocator doWidgetMouseMove(ISelectionTarget target) throws WidgetSearchException { IClickDescription click = target.getClickDescription(); IWidgetLocator locator = target.getWidgetLocator(); Widget targetWidget = findWidget(locator); // move and wrapper target if (click.isDefaultCenterClick()) mouseMove(targetWidget); else mouseMove(targetWidget, click.x(), click.y()); return WidgetReference.create(targetWidget); } /////////////////////////////////////////////////////////////////////////// // // Widget finding helpers // /////////////////////////////////////////////////////////////////////////// private ISelectionTarget getTarget(ILocator locator) { return SelectionTarget.parse(locator); } private Widget findWidget(IWidgetLocator locator) throws WidgetSearchException { IWidgetReference ref = (IWidgetReference) find((IWidgetLocator)locator); Object target = ref.getWidget(); if (target == null) throw new IllegalArgumentException("widget reference must not be null"); if (!(target instanceof Widget)) return null; //NULL is now a sentinel //throw new IllegalArgumentException("widget reference must of class Widget, got: " + target.getClass()); return (Widget)target; } /////////////////////////////////////////////////////////////////////////// // // Drag and drop actions // /////////////////////////////////////////////////////////////////////////// public Widget dragTo(Widget target) { handleConditions(); return getDNDHelper().dragTo(target); } // /** // * @see com.windowtester.swt.IUIContext#dragTo(java.lang.String) // */ // public Widget dragTo(String widgetHandle) throws WidgetNotFoundException, MultipleWidgetsFoundException { // //condition handling done in find // return getDNDHelper().dragTo(find(widgetHandle)); // } public Widget dragTo(Widget target, int x, int y) { handleConditions(); return getDNDHelper().dragTo(target, x, y); } // /** // * @see com.windowtester.swt.IUIContext#dragTo(java.lang.String, int, int) // */ // public Widget dragTo(String widgetHandle, int x, int y) throws WidgetNotFoundException, MultipleWidgetsFoundException { // //condition handling done in find // return getDNDHelper().dragTo(find(widgetHandle), x, y); // } // /** // * @see com.windowtester.swt.IUIContext#dragTo(org.eclipse.swt.widgets.Widget, java.lang.String, int, int) // */ // public Widget dragTo(Widget w, String path, int x, int y) throws WidgetNotFoundException, MultipleWidgetsFoundException { // handleConditions(); // try { // return getDNDHelper().dragTo(w, path, x, y); // } catch (com.windowtester.runtime.WidgetNotFoundException e) { // throw new WidgetNotFoundException(e); // } catch (com.windowtester.runtime.MultipleWidgetsFoundException e) { // throw new MultipleWidgetsFoundException(e); // } // } // /** // * @see com.windowtester.swt.IUIContext#dragTo(java.lang.String, java.lang.String, int, int) // */ // public Widget dragTo(String widgetHandle, String path, int x, int y) throws WidgetNotFoundException, MultipleWidgetsFoundException { // //condition handling done in find // try { // return getDNDHelper().dragTo(find(widgetHandle), path, x, y); // } catch (com.windowtester.runtime.WidgetNotFoundException e) { // throw new WidgetNotFoundException(e); // } catch (com.windowtester.runtime.MultipleWidgetsFoundException e) { // throw new MultipleWidgetsFoundException(e); // } // } // /** // * @see com.windowtester.swt.IUIContext#dragTo(int, int) // */ // public void dragTo(int x, int y) { // handleConditions(); // getDNDHelper().dragTo(x,y); // } /////////////////////////////////////////////////////////////////////////// // // Timing // /////////////////////////////////////////////////////////////////////////// /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#pause(int) */ public void pause(int ms) { expectDelay(ms); handleConditions(); UIDriver.pause(ms); } /*package*/ void expectDelay(long ms) { if (_threadMonitor != null) _threadMonitor.expectDelay(ms); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#wait(com.windowtester.runtime.condition.ICondition) */ public void wait(ICondition condition) throws WaitTimedOutException { wait(condition, WT.getDefaultWaitTimeOut()); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#wait(com.windowtester.runtime.condition.ICondition, long) */ public void wait(ICondition condition, long timeout) throws WaitTimedOutException { wait(condition, timeout, WT.getDefaultWaitInterval()); } /* (non-Javadoc) * @see com.windowtester.runtime.IUIContext#wait(com.windowtester.runtime.condition.ICondition, long, int) */ public void wait(ICondition condition, long timeout, int interval) throws WaitTimedOutException { expectDelay(timeout); // TODO [author=Dan] waitForShellShowing/Disposed had handleConditions // but other wait(...) methods did not, so this is a slight change handleConditions(); long now = System.currentTimeMillis(); while (!ConditionMonitor.test(this, condition)) { if (System.currentTimeMillis() - now > timeout) { // If the display is valid, then capture the screen and close open shells if (_display == null) LogHandler.log("failed to get current display in wait timeout handling"); else if (_display.isDisposed()) LogHandler.log("current display is disposed in wait timeout handling"); else { doScreenCapture("on timeout"); new ExceptionHandlingHelper(_display, true).closeOpenShells(); } // Build diagnostic information throw new WaitTimedOutException(Diagnostic.toString("Timed out waiting for condition", condition)); } //note conditions are handled in the pause pause(interval); } } protected PlaybackSettings getPlaybackSettings() { return Platform.isRunning() ? RuntimePlugin.getDefault().getPlaybackSettings() : PlaybackSettings .loadFromFile(); } public UIDriver getDriver() { return /*isHighlightingOrDelayOn() ? _highlightingDriver : */ _driver; } protected boolean isHighlightingOrDelayOn() { return getPlaybackSettings().getHighlightingOn() || getPlaybackSettings().getDelayOn(); } protected int getDefaultButtonMask() { return DEFAULT_BUTTON_MASK; } // ////////////////////////////////////////////////////////////////////// // // Condition-handling // // ////////////////////////////////////////////////////////////////////// /** * Answer the local shell monitor associated with this instance. * @return the shell monitor (not <code>null</code>) */ private IShellMonitor getShellMonitor() { if (_shellMonitor == null) _shellMonitor = new ShellMonitor((ConditionMonitor) getConditionMonitor()); return _shellMonitor; } /** * Check for any active conditions and handle them. If a condition is handled, * original hover context will be restored post condition handling. * * @return one of the following flags indicating what was processed: * {@link IConditionMonitor#PROCESS_NONE} if conditions were processed but no conditions were satisfied, * {@link IConditionMonitor#PROCESS_ONE_OR_MORE} if conditions were processed and at least on condition was satisfied, * {@link IConditionMonitor#PROCESS_RECURSIVE} if conditions were already being processed and no additional action was taken. */ public int handleConditions() { /* * Since conditions might access the UI thread, we need to skip them * in the Native case. */ if (applicationContext.isNative()) return IConditionMonitor.PROCESS_NATIVE; // cache current info IHoverInfo hoverInfo = getDriver().getCurrentMouseHoverInfo(); // process conditions int result = super.handleConditions(); // if conditions were handled, restore hover context (if there is one) if (hoverInfo != null && result == IConditionMonitor.PROCESS_ONE_OR_MORE) { Point location = hoverInfo.getLocation(); // notice we do this using the driver directly so that we don't retrigger // condition-handling... if (location != null) getDriver().mouseMove(location.x, location.y); } return result; } // ////////////////////////////////////////////////////////////////////////// // // Utility // // ////////////////////////////////////////////////////////////////////////// /** * Determine if the current test is for the Eclipse organization by examining the * stack trace for classes in unexpected packages. * * @return <code>true</code> if running any classes in unexpected packages are found */ static boolean isEclipseOrgTest() { StringWriter stringWriter = new StringWriter(1000); PrintWriter writer = new PrintWriter(stringWriter); try { throw new RuntimeException(); } catch (Exception e) { e.printStackTrace(writer); } return isEclipseOrgTest(stringWriter.toString()); } /** * Determine if the current test is for the Eclipse organization by examining the * stack trace for classes in unexpected packages. * * @param stackTrace the stack trace (not <code>null</code>) * @return <code>true</code> if running any classes in unexpected packages are found */ static boolean isEclipseOrgTest(String stackTrace) { LineNumberReader reader = new LineNumberReader(new StringReader(stackTrace)); while (true) { String line; try { line = reader.readLine(); } catch (IOException e) { return true; } if (line == null) return true; line = line.trim(); if (line.startsWith("at")) { line = line.substring(2).trim(); if (line.startsWith("com.windowtester.")) continue; if (line.startsWith("java.lang.")) continue; if (line.startsWith("junit.extensions.")) continue; if (line.startsWith("junit.framework.")) continue; if (line.startsWith("org.eclipse.")) continue; if (line.startsWith("org.osgi.")) continue; if (line.startsWith("sun.reflect.")) continue; return false; } } } private String getToStringOnUIThread(final Object o) { Display display = getDisplay(); if (display == null) display = Display.getDefault(); if (display == null) return "<unable to retrieve display -- toString() failed>"; final String [] str = new String[1]; display.syncExec(new Runnable(){ public void run() { str[0] = o.toString(); } }); return str[0]; } /////////////////////////////////////////////////////////////////////////// // // Primitive mouse action commands // /////////////////////////////////////////////////////////////////////////// protected void mouseMove(Widget w) { handleConditions(); getDriver().mouseMove(w); } protected void mouseMove(Widget w, int x, int y) { handleConditions(); getDriver().mouseMove(w, x, y); } }