/*******************************************************************************
* 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.operation;
import org.eclipse.swt.graphics.Point;
import com.windowtester.runtime.WT;
import com.windowtester.runtime.swt.internal.widgets.SWTWidgetReference;
/**
* Perform a click or drag operation by pushing mouse move, mouse down, and mouse up
* operations onto the OS event queue.
*/
public class SWTMouseOperation extends SWTOperation
{
/**
* The mouse button ({@link WT#BUTTON1}, ...) and any modifiers ({@link WT#SHIFT},
* {@link WT#CTRL}, ...)
*/
private final int accelerator;
/**
* The starting location or <code>null</code> if the mouse operation should occur at
* the current mouse location
*/
private SWTLocation start = null;
/**
* The ending location or <code>null</code> if the mouse up should occur in the same
* location as the mouse down
*/
private SWTLocation end = null;
/**
* The number of mouse clicks or zero if the mouse should only be moved
*/
private int clickCount = 1;
/**
* Construct a new click operation that clicks the mouse at the current mouse
* location.
* <p>
* WARNING! Use {@link SWTShowMenuOperation} for context clicks (right mouse button) and
* menu selection
*
* @param accelerator the button to be clicked such as {@link WT#BUTTON1} or
* {@link WT#BUTTON2} bit-wise and with the modifier keys such as
* {@link WT#SHIFT} and {@link WT#CTRL}
*/
public SWTMouseOperation(int accelerator) {
this.accelerator = accelerator;
}
/**
* Queue a step that waits for a particular menu item to become enabled. Typically,
* this is called *before* calling {@link #click(int, SWTLocation, boolean)}
*
* @return this operation so that calls can be cascaded on a single line such as
* <code>new SWTMouseOperation().waitForEnabled(...).at(...).execute();</code>
*/
public SWTMouseOperation waitForEnabled(SWTWidgetReference<?> widgetRef) {
return (SWTMouseOperation) super.waitForEnabled(widgetRef);
}
/**
* Set the location at which the click or drag is to start. If this method is not
* called, then the mouse down occurs at the current mouse location.
*
* @param location the location where the mouse down should occur
* @return this operation so that calls can be cascaded on a single line such as
* <code>new SWTMouseClickOperation(WT.BUTTON1).at(10, 20).execute();</code>
*/
public SWTMouseOperation at(SWTLocation location) {
this.start = location;
return this;
}
/**
* Set the location to which the mouse is dragged before the mouse up event. If this
* method is not called, then the mouse up occurs at the same location as the mouse
* down (e.g. a click).
*
* @param location the location where the mouse up should occur
* @return this operation so that calls can be cascaded on a single line such as
* <code>new SWTMouseClickOperation(WT.BUTTON1).at(10, 20).execute();</code>
*/
public SWTOperation dragTo(SWTLocation location) {
this.end = location;
return this;
}
/**
* Set the number of times the mouse is clicked in rapid succession. If you call this
* with a value of zero, then the mouse is moved but not clicked (no mouse down or
* mouse up events are generated).
*
* @param clickCount the click count (0 = move only, 1 = single click, 2 = double
* click, ...)
* @return this operation so that calls can be cascaded on a single line such as
* <code>new SWTMouseClickOperation(WT.BUTTON1).at(10, 20).execute();</code>
*/
public SWTOperation count(int clickCount) {
this.clickCount = clickCount;
return this;
}
/**
* Perform the mouse operation
*/
public void execute() {
queueStep(new Step() {
public void executeInUI() throws Exception {
queueMouseEventsInUI();
}
});
super.execute();
}
//=======================================================================
// Internal
/**
* Queue the mouse events for the operation
*
* @return <code>true</code> if successful
*/
protected void queueMouseEventsInUI() throws Exception {
int button = getButton(accelerator);
Point startLoc;
if (start != null) {
startLoc = start.location();
// Linux needs a wiggle and not just a move
queueMouseWiggle(startLoc);
}
else {
// TODO: Get the current mouse location and wiggle
startLoc = null;
}
if (clickCount > 0) {
queueModifierKeysDown(accelerator);
queueMouseDown(button, startLoc);
for (int i = 1; i < clickCount; i++) {
queueMouseUp(button, startLoc);
queueMouseDown(button, startLoc);
}
Point endLoc = end != null ? end.location() : startLoc;
// Linux needs a mouse move even for a mouse click
// and it does not hurt on the Windows side
if (endLoc != null)
queueMouseMove(endLoc);
queueMouseUp(button, endLoc);
queueModifierKeysUp(accelerator);
// Linux (and Mac?) needs a wiggle to push through events
// TODO: If endLoc is null, get the current mouse location and wiggle
if (endLoc != null)
queueMouseWiggle(endLoc);
}
}
}