/******************************************************************************* * 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 org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Widget; import abbot.tester.swt.WidgetLocator; import com.windowtester.internal.debug.IRuntimePluginTraceOptions; import com.windowtester.internal.debug.TraceHandler; import com.windowtester.internal.runtime.Platform; import com.windowtester.runtime.MultipleWidgetsFoundException; import com.windowtester.runtime.WidgetNotFoundException; import com.windowtester.runtime.swt.internal.effects.HighlighterFactory; import com.windowtester.runtime.swt.internal.effects.IHighlighter; import com.windowtester.runtime.swt.internal.effects.LineIteratorUtil; import com.windowtester.runtime.swt.internal.effects.MenuItemHighlightingSelector; import com.windowtester.runtime.swt.internal.preferences.PlaybackSettings; import com.windowtester.swt.RuntimePlugin; /** * A decorator that wraps calls to drive UI events in highlighting actions. * * @author Phil Quitslund * */ public class HighlightingDriver extends UIDriver { //pq: removing presentation bits // private PresentationContext pc; // /** * Create an instance (using the default settings). */ public HighlightingDriver() { //this(RuntimePlugin.getDefault().getPlaybackSettings()); try { if (Platform.isRunning()) _settings = RuntimePlugin.getDefault().getPlaybackSettings(); } catch (Throwable t) { //ignore: if an exception occurs we will properly setup settings below //TODO: this is NOT a clean way to do this! wee _should_ clean it up! } if (_settings == null) _settings = PlaybackSettings.loadFromFile(); // pc = getPresentationContext(); // pc.setDefaultShowNoteDuration(5000); } /** * Create an instance. * @param settings */ public HighlightingDriver(PlaybackSettings settings) { _settings = settings; // pc = getPresentationContext(); } /////////////////////////////////////////////////////////////////////////////////// // // Decorated selection actions. // /////////////////////////////////////////////////////////////////////////////////// /** * @see com.windowtester.event.swt.UIDriver#click(org.eclipse.swt.widgets.Widget, int, int, int) */ public Widget click(Widget w, int x, int y, int mask) { //first move the mouse to the point of interest: mouseMove(w); //do highlighting highlight(w); //click super.click(w, x, y, mask); //pause postClickPause(); return w; } public void postClickPause() { if (_settings.getDelayOn()) pause(_settings.getWidgetClickDelay()); } private Point pointT; private Point cursorT; public void mouseMove(final Widget w, int x, int y) { int delay = _settings.getMouseMoveDelay(); if (!_settings.getDelayOn() || delay == 0) { TraceHandler.trace(IRuntimePluginTraceOptions.WIDGET_SELECTION, "delay off or 0 so not slowing down mouse move"); super.mouseMove(w, x, y); return; } TraceHandler.trace(IRuntimePluginTraceOptions.WIDGET_SELECTION, "calling overriden mouseMove with delay: " + delay); w.getDisplay().syncExec(new Runnable(){ public void run(){ pointT = WidgetLocator.getLocation(w); } }); w.getDisplay().syncExec(new Runnable(){ public void run(){ cursorT = w.getDisplay().getCursorLocation(); } }); Point cursorLocation = cursorT; Point target = new Point(pointT.x+x,pointT.y+y); TraceHandler.trace(IRuntimePluginTraceOptions.WIDGET_SELECTION, "source=" + cursorLocation); TraceHandler.trace(IRuntimePluginTraceOptions.WIDGET_SELECTION, "target=" + target); Point[] path = LineIteratorUtil.getPath(cursorLocation, target); TraceHandler.trace(IRuntimePluginTraceOptions.WIDGET_SELECTION, "...starting move"); for (int i = 0; i < path.length; i++) { super.mouseMove(path[i].x, path[i].y); pause(delay); } } /** * @see com.windowtester.event.swt.UIDriver#enterText(java.lang.String) */ public void enterText(String str) { Display d = Display.getDefault(); Control control = UIProxy.getFocusControl(d); showDefaultNote(control, str); //if it's disabled or set to zero, don't bother decorating if (!_settings.getDelayOn() || _settings.getKeyClickDelay() == 0) { super.enterText(str); return; } TraceHandler.trace(IRuntimePluginTraceOptions.WIDGET_SELECTION, "entering text with delay: " + _settings.getKeyClickDelay()); //enter text one char at a time, pausing as we go for (int i=0; i <= str.length()-1; ++i) { keyClick(str.charAt(i)); } } // /** // * @see com.windowtester.event.swt.UIDriver#clickExpand(org.eclipse.swt.widgets.Widget) // */ // public Widget clickExpand(Widget w) { // //do highlighting // highlight(w); // //click // return super.clickExpand(w); // } /** * @see com.windowtester.event.swt.UIDriver#click(org.eclipse.swt.widgets.Widget, java.lang.String) */ public Widget click(Widget w, String itemLabelOrPath) throws WidgetNotFoundException, MultipleWidgetsFoundException { /** * This is a hack and a kludge but menu highlighting is more invasive and requires * input at more points than before and after... * * In the future this should be broken out and handled more uniformly. * */ if (w instanceof MenuItem) { return new MenuItemHighlightingSelector(_settings).click(w, itemLabelOrPath); } //highlight root highlight(w); //show automatic bubble note showDefaultNote(w, itemLabelOrPath); //click Widget clicked = super.click(w, itemLabelOrPath); //highlight node highlight(clicked); return clicked; } /** * @throws MultipleWidgetsFoundException * @throws WidgetNotFoundException * @see com.windowtester.event.swt.UIDriver#click(org.eclipse.swt.widgets.Widget, java.lang.String, int) */ public Widget click(Widget w, String itemLabelOrPath, int mask) throws WidgetNotFoundException, MultipleWidgetsFoundException { // show automatic bubble note showDefaultNote(w, itemLabelOrPath); //highlight root highlight(w); //click Widget clicked = super.click(w, itemLabelOrPath, mask); //highlight node highlight(clicked); return clicked; } /** * Click and pause. * @see com.windowtester.event.swt.UIDriver#keyClick(char) */ public void keyClick(char key) { super.keyClick(key); pause(_settings.getKeyClickDelay()); } /** * Click and pause. * @see com.windowtester.event.swt.UIDriver#keyClick(int, char) */ public void keyClick(int ctrl, char c) { super.keyClick(ctrl, c); pause(_settings.getKeyClickDelay()); } /** * Click and pause. * @see com.windowtester.event.swt.UIDriver#keyClick(int) */ public void keyClick(int key) { super.keyClick(key); pause(_settings.getKeyClickDelay()); } /////////////////////////////////////////////////////////////////////////////////// // // Utilities. // /////////////////////////////////////////////////////////////////////////////////// /** * Do the highlighting (if enabled). * @param w - the widget to highlight */ public void highlight(Widget w) { if (_settings.getHighlightingOn()) { IHighlighter highlighter = HighlighterFactory.create(w, _settings); highlighter.doPaint(this); } } /** * Pause for highlighting. */ public void highlightPause() { pause(_settings.getHighlightDuration()); } // protected PresentationContext getPresentationContext(){ // PresentationContext pc = new SwtPresentationContext(null, Display.getDefault()); // return pc; // } // private String wrapForNote(String str) { // String adjustText = "Enter text \'"; // if (str.length()>20) // adjustText += "\'" + str.substring(0, 20) + "...\'"; // else // adjustText += "\'" + str + "\'"; // return adjustText; // } /* (non-Javadoc) * @see com.windowtester.event.swt.UIDriver#click(org.eclipse.swt.widgets.Widget) */ public synchronized Widget click(Widget w) { showDefaultNote(w, null); return super.click(w); } private void showDefaultNote(Widget w, String originalText){ //pq: removing presentation bits // if(!pc.isShowNotesAutomatically()) // return; // // String text = null; // if(w instanceof Text){ // String label = getSiblingLabel((Text)w); // if(label!=null) // text = wrapForNote(originalText) + " into '"+label+"' field"; // else // text = wrapForNote(originalText); // } // if(w instanceof Button){ // text = "Click '"+UIProxy.getText((Button)w)+"' button"; // } // if(w instanceof TreeItem){ // text = "Select '"+originalText+"'"; // } // if(w instanceof Tree){ // text = "Select '"+originalText+"' in the tree"; // } // if(w instanceof List){ // text = "Select '"+originalText+"' in the list"; // } // if(w instanceof Combo){ // String label = getSiblingLabel((Combo)w); // if(label!=null) // text = "Select '"+originalText+"' in '"+label+"'."; // else // text = "Select '"+originalText; // } // // if(text!=null) // pc.showNote(text, UIProxy.getBounds(w), IPresentationContext.STYLE_NORMAL, pc.getDefaultShowNoteDuration()); } // private String getSiblingLabel(final Control c) { // final Display d = Display.getDefault(); // RunnableWithResult r = new RunnableWithResult() { // public Object runWithResult() { // Control[] children = c.getParent().getChildren(); // if(children.length<=1) // return null; // Control tmp = children[0]; // for (int i = 1; i < children.length; i++) { // Control control = children[i]; // if((tmp instanceof Label)&&(control==c)){ // return ((Label)tmp).getText(); // } // tmp = control; // } // return null; // } // }; // d.syncExec(r); // return (String)r.getResult(); // } }