/*******************************************************************************
* 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.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;
import com.windowtester.runtime.WidgetSearchException;
import com.windowtester.runtime.locator.IWidgetReference;
import com.windowtester.runtime.swt.internal.debug.LogHandler;
import com.windowtester.runtime.swt.internal.finder.FinderUtil;
import com.windowtester.runtime.swt.internal.reveal.IRevealStrategy;
import com.windowtester.runtime.swt.internal.reveal.RevealStrategyFactory;
import com.windowtester.runtime.swt.internal.selector.BasicWidgetSelector;
import com.windowtester.runtime.swt.internal.selector.PopupMenuSelector2;
import com.windowtester.runtime.swt.internal.selector.PopupMenuSelector.PopupFailedException;
import com.windowtester.runtime.swt.locator.TableItemLocator;
import com.windowtester.runtime.MultipleWidgetsFoundException;
import com.windowtester.runtime.WidgetNotFoundException;
/*
* The other version is kept for leagcey purposes as old UIContext actions
* depend on its idiosyncarcies. Moving forward, this is teh prefered tree item selector.
*
*
*/
public class TableItemSelector2 extends BasicWidgetSelector {
/** How far from the left to nudge a click action */
public static final int LEFT_NUDGE = 8;
private final IRevealStrategy _revealer = RevealStrategyFactory.getRevealer(TableItem.class);
///////////////////////////////////////////////////////////////////////////
//
// API
//
///////////////////////////////////////////////////////////////////////////
/**
* @see com.windowtester.event.swt.ISWTWidgetSelectorDelegate#click(org.eclipse.swt.widgets.Widget, int, int, int)
*/
public Widget click(Widget w, int x, int y, int mask) {
if (w instanceof TableItem) {
getRevealer().reveal(w, x, y);
}
// this click should be relative to 0 column, coordinates x & y are ignored
actionClickTableItem((TableItem)w, 0, mask);
return w;
}
public Widget click(Widget w, int mask) {
return click(w, LEFT_NUDGE, 4, mask); //this is a fudged coordinate
}
public Widget click(int clicks, Widget w, int mask) throws WidgetSearchException {
return click(clicks, w, 0, new Point(LEFT_NUDGE, 4), mask); //this is a fudged coordinate
}
public Widget click(int clicks, Widget w, int column, Point offset, int mask) throws WidgetSearchException {
if (w instanceof TableItem) {
column = column == TableItemLocator.UNSPECIFIED_COLUMN ? 0 : column;
Point revealOffset = getClickOffset((TableItem)w, column, offset, mask);
//legacy revealer uses strings to describe paths (in this case columns)
String colString = "0";
try {
colString = Integer.toString(column);
} catch (NumberFormatException e) {
LogHandler.log(e);
}
getRevealer().reveal(w, colString, revealOffset.x, revealOffset.y);
actionClickTableItem(clicks, (TableItem)w, column, offset, mask);
}
return w;
}
/**
* @see com.windowtester.swt.ISWTWidgetSelectorDelegate#click(org.eclipse.swt.widgets.Widget, IWidgetReference, int)
*/
public Widget click(Widget w, String itemLabel, int mask) throws WidgetNotFoundException, MultipleWidgetsFoundException {
if (w instanceof TableItem) {
getRevealer().reveal(w, itemLabel, LEFT_NUDGE, 4); //this is a fudged coordinate
}
int columnIndex = 0;
try {
columnIndex = Integer.parseInt(itemLabel);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(itemLabel + " must be an integer value to select the item column");
}
actionClickTableItem((TableItem)w, columnIndex, mask);
return w;
}
/**
* @see com.windowtester.swt.ISWTWidgetSelectorDelegate#doubleClick(org.eclipse.swt.widgets.Widget, java.lang.String, int)
*/
public Widget doubleClick(Widget w, String itemLabel, int mask) {
int columnIndex = 0;
try {
columnIndex = Integer.parseInt(itemLabel);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(itemLabel + " must be an integer value to select the item column");
}
actionDoubleClickTableItem((TableItem)w, columnIndex, mask);
return w;
}
protected void actionDoubleClickTableItem(final TableItem item, final int columnIndex, final int mask) {
final Display display = item.getDisplay();
display.syncExec(new ItemClickProcess(2, item, columnIndex, mask));
//pauseCurrentThread(500); // wait to allow OS consume events
}
/**
* Clicks in the center of the TableItem and the column given.
* <p/>
* @param item the item to click onto.
* @param columnIndex the column to click onto.
*/
protected void actionClickTableItem(final TableItem item, final int columnIndex, final int mask) {
// final Display display = item.getDisplay();
//
// new SystemEventMonitor(UIProxy.getParent(item), SWT.MouseUp){
// public void syncExecEvents() {
// display.syncExec(new ItemClickProcess(1, item, columnIndex, mask));
// }
// }.run();
new ItemClickProcess(1, item, columnIndex, mask).run();
}
/**
* Clicks in the center of the TableItem and the column given.
* <p/>
* @param item the item to click onto.
* @param columnIndex the column to click onto.
*/
protected void actionClickTableItem(final int numClicks, final TableItem item, final int columnIndex, final Point offset, final int mask) {
// new SystemEventMonitor(UIProxy.getParent(item), SWT.MouseUp){
// public void syncExecEvents() {
// new ItemClickProcess(numClicks, item, columnIndex, offset, mask).run();
// }
// }.run();
new ItemClickProcess(numClicks, item, columnIndex, offset, mask).run();
}
/**
* Calculate the offset for clicking a table item.
*/
public Point getClickOffset(Rectangle rect, int mask) {
/*
* center clicking does not work...
* (For example, clicking the Debug item in the Open New Perspective Wizard)
* Our stop-gap is to click the far left of the item (thinking that it would have to be
* REALLY tiny to miss.
*/
return new Point(LEFT_NUDGE, rect.height/2);
}
private Point getClickOffset(TableItem item, int columnIndex, Point offset, int mask){
//fix column
columnIndex = (columnIndex == TableItemLocator.UNSPECIFIED_COLUMN) ? 0 : columnIndex;
boolean check = (mask & SWT.CHECK) == SWT.CHECK;
if (check){
// if check is present the offset should be relative to the first column (and xy is ignored)
Rectangle itemBounds = UIProxy.getBounds(item, 0);
return new Point(itemBounds.x/2 - 1, itemBounds.y + itemBounds.height/2);
} else {
if (offset != null) {
return offset;
}
Rectangle itemBounds = UIProxy.getBounds(item, columnIndex);
return new Point(itemBounds.x + LEFT_NUDGE, itemBounds.y+ itemBounds.height/2);
}
}
private Point getContextClickOffset(TableItem item, int columnIndex, Point offset, int mask){
//fix column
columnIndex = (columnIndex == TableItemLocator.UNSPECIFIED_COLUMN) ? 0 : columnIndex;
boolean check = (mask & SWT.CHECK) == SWT.CHECK;
if (check){
// if check is present the offset should be relative to the first column (and xy is ignored)
Rectangle itemBounds = UIProxy.getBounds(item, 0);
return new Point(itemBounds.x/2 - 1, itemBounds.height/2);
} else {
if (offset != null) {
return offset;
}
Rectangle itemBounds = UIProxy.getBounds(item, columnIndex);
return new Point(itemBounds.x + LEFT_NUDGE, itemBounds.height/2);
}
}
/* (non-Javadoc)
* @see com.windowtester.event.selector.swt.BasicWidgetSelector#getClickOffset(org.eclipse.swt.widgets.Widget)
*/
public Point getClickOffset(Widget w, int mask) {
if (!(w instanceof TableItem)) {
LogHandler.log("unexpected class " + w.getClass() + " in TableItemSelector.getClickOffset()");
//log but move on...
}
TableItem item = (TableItem)w;
// this only make sense when columnIndex = 0
return getClickOffset(item, 0, null, mask);
}
private IRevealStrategy getRevealer() {
return _revealer;
}
private class ItemClickProcess implements Runnable {
private int clickNum;
private TableItem item;
private int columnIndex;
private int mask;
private final Point offset;
public ItemClickProcess(int clickNum, TableItem item, int columnIndex, Point offset, int mask){
this.clickNum = clickNum;
this.item = item;
this.columnIndex = columnIndex;
this.offset = offset;
this.mask = mask;
}
public ItemClickProcess(int clickNum, TableItem item, int columnIndex, int mask){
this(clickNum, item, columnIndex, null, mask);
}
public void run() {
final boolean[] isValidColumnIndex = new boolean[1];
Display.getDefault().syncExec(new Runnable() {
public void run() {
isValidColumnIndex[0] = item.getParent().getColumnCount() >= columnIndex && columnIndex >= 0;
}
});
if (!isValidColumnIndex[0]) {
return;
}
// get the offset of the click relative to the table
final Point clickOffset = getClickOffset(item, columnIndex, offset, mask);
// convert it to Display coordinates
final Point[] clickLocation = new Point[1];
Display.getDefault().syncExec(new Runnable() {
public void run() {
clickLocation[0] = item.getParent().toDisplay(clickOffset);
}
});
// make a click
click(clickLocation[0].x, clickLocation[0].y, mask, clickNum);
// causes test not to return when modal dialog opens on double click
//waitForIdle(item.getDisplay());
}
}
/**
* Returns offset for clicks on columns in table cell
* @param item
* @param column
* @return
*/
public Point getTableCellClickOffset(TableItem item, int column){
return getContextClickOffset(item, column, null, SWT.BUTTON3);
}
// public Widget contextClick(TableItem item, int column, Point offset, String menuItemPath) throws WidgetSearchException {
//
// Control control = FinderUtil.getControl(item);
// if (control == null)
// throw new UnsupportedOperationException("Context menus unsupported for widgets of type: " + item.getClass());
// Widget clicked = null;
// offset = getContextClickOffset(item, column, offset, SWT.BUTTON3);
//
//
// try {
// clicked = new PopupMenuSelector2().runPopup(control, item, offset.x, offset.y, menuItemPath);
//
// } catch (PopupFailedException e) {
// throw new WidgetNotFoundException("menu item: " + menuItemPath + " not found in widget " + item);
// }
//
// return clicked;
// }
}