/*******************************************************************************
* 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.widgets;
import java.util.concurrent.Callable;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.TreeItem;
import com.windowtester.internal.runtime.locator.IUISelector;
import com.windowtester.runtime.IClickDescription;
import com.windowtester.runtime.IUIContext;
import com.windowtester.runtime.WT;
import com.windowtester.runtime.WidgetSearchException;
import com.windowtester.runtime.condition.ICondition;
import com.windowtester.runtime.internal.concurrent.VoidCallable;
import com.windowtester.runtime.locator.IWidgetLocator;
import com.windowtester.runtime.locator.IWidgetReference;
import com.windowtester.runtime.swt.internal.drivers.MenuDriver;
import com.windowtester.runtime.swt.internal.operation.SWTLocation;
import com.windowtester.runtime.swt.internal.operation.SWTMenuOperation;
import com.windowtester.runtime.swt.internal.operation.SWTMouseOperation;
import com.windowtester.runtime.swt.internal.operation.SWTShowMenuOperation;
import com.windowtester.runtime.swt.internal.operation.SWTTreeItemLocation;
import com.windowtester.runtime.swt.internal.operation.SWTTreeItemOperation;
import com.windowtester.runtime.swt.internal.util.TextUtils;
/**
* A {@link TreeItem} reference.
*/
public class TreeItemReference extends ItemReference<TreeItem>
implements ISWTWidgetReferenceWithContextMenu, TreeItemReferenceContainer, IUISelector
{
/*
* NOTE: implementation of IUISelector is provisional.
*
*/
/* (non-Javadoc)
* @see com.windowtester.internal.runtime.locator.IUISelector#click(com.windowtester.runtime.IUIContext, com.windowtester.runtime.locator.IWidgetReference, com.windowtester.runtime.IClickDescription)
*/
public IWidgetLocator click(IUIContext ui, IWidgetReference widget, IClickDescription click) throws WidgetSearchException {
return show().click(click);
}
/* (non-Javadoc)
* @see com.windowtester.internal.runtime.locator.IUISelector#contextClick(com.windowtester.runtime.IUIContext, com.windowtester.runtime.locator.IWidgetReference, com.windowtester.runtime.IClickDescription, java.lang.String)
*/
public IWidgetLocator contextClick(IUIContext ui, IWidgetReference widget,
final IClickDescription click, String menuItemPath)
throws WidgetSearchException {
final TreeItemReference item = show();
return new MenuDriver().resolveAndSelect(new Callable<MenuReference>() {
public MenuReference call() throws Exception {
return item.showContextMenu(click);
}
}, menuItemPath);
}
public class ItemExpandedCondition implements ICondition {
public boolean test() {
return getExpanded();
}
@Override
public String toString() {
return TreeItemReference.this.toString() + " to be expanded";
}
}
public class ItemCheckedCondition implements ICondition{
public boolean test() {
return getChecked();
}
@Override
public String toString() {
return TreeItemReference.this.toString() + " to be checked";
}
}
public TreeItemReference(TreeItem item) {
super(item);
}
/* (non-Javadoc)
* @see com.windowtester.runtime.swt.internal.widgets.SWTWidgetReference#getParent()
*/
public TreeReference getParent() {
return displayRef.execute(new Callable<TreeReference>() {
public TreeReference call() throws Exception {
return new TreeReference(widget.getParent());
}
});
}
/**
* Proxy for {@link TreeItem#getText(int)}
*/
public String getText(final int column) {
return displayRef.execute(new Callable<String>() {
public String call() throws Exception {
return widget.getText(column);
}
});
}
/**
* Proxy for {@link TreeItem#getItems()}
*/
public TreeItemReference[] getItems() {
return displayRef.execute(new Callable<TreeItemReference[]>() {
public TreeItemReference[] call() throws Exception {
return asReferencesOfType(widget.getItems(), TreeItemReference.class);
}
});
}
/**
* Calculate the client area of the widget or a column within the widget and convert that from local coordinates to
* global coordinates (also known as display coordinates).
*
* @param columnIndex the zero based column index or -1 for the bounds of the entire tree item
* @return the area of the widget or widget column in display coordinates
*/
public Rectangle getDisplayBounds(final int columnIndex) {
return displayRef.execute(new Callable<Rectangle>() {
public Rectangle call() throws Exception {
TreeItem treeItem = getWidget();
Rectangle localBounds = columnIndex >= 0 ? treeItem.getBounds(columnIndex) : treeItem.getBounds();
return treeItem.getDisplay().map(treeItem.getParent(), null, localBounds);
}
});
}
/* (non-Javadoc)
* @see com.windowtester.runtime.swt.internal.widgets.IControlReference#isVisible()
*/
public boolean isVisible() {
// TODO[pq]: this is NOT right -- returns false -- the rub is we need a way to detect visibility (perhaps parent expansion state?)
return super.isVisible();
}
@Override
public boolean isEnabled() {
return getParent().isEnabled();
}
/* (non-Javadoc)
* @see com.windowtester.runtime.swt.internal.widgets.CompositeReference#setChildren(com.windowtester.runtime.swt.internal.widgets.SWTWidgetReference.ChildSet)
*/
@Override
protected void setChildren(ChildSet children) {
children.add(getItems());
}
//
//
// @Override
// public void accept(SWTWidgetReference.Visitor visitor) {
// super.accept(visitor);
// visitor.visitEnter(this);
// visitAll(visitor, getItems());
// visitor.visitLeave(this);
// }
/**
* Proxy for {@link TreeItem#setExpanded(boolean)}.
*/
public void setExpanded(final boolean expanded) {
displayRef.execute(new VoidCallable() {
public void call() throws Exception {
widget.setExpanded(expanded);
}
});
}
/**
* Proxy for {@link TreeItem#getExpanded()}.
*/
public boolean getExpanded() {
return displayRef.execute(new Callable<Boolean>() {
public Boolean call() throws Exception {
return widget.getExpanded();
}
});
}
/**
* Proxy for {@link TreeItem#setChecked(boolean)}.
*/
public void setChecked(final boolean checked) {
displayRef.execute(new VoidCallable() {
public void call() throws Exception {
widget.setChecked(checked);
}
});
}
/**
* Proxy for {@link TreeItem#getChecked()}.
*/
public boolean getChecked(){
return displayRef.execute(new Callable<Boolean>() {
public Boolean call() throws Exception {
return widget.getChecked();
}
});
}
public void expand() {
// new SWTTreeItemExpandEvent(this).dispatch();
new SWTTreeItemOperation(this).show().expand().execute();
// TODO[pq]: wait for expand?
// new SWTOperation() {
// protected boolean queueEventsInUI() throws Exception {
// queueWidgetEvent(widget, SWT.Expand);
// postEventsInUI();
// widget.setExpanded(true);
// queueWidgetEvent(widget, SWT.MouseMove);
// queueWidgetEvent(widget, SWT.Activate);
// queueWidgetEvent(widget, SWT.FocusIn);
// queueWidgetEvent(widget, SWT.MouseDown);
// queueWidgetEvent(widget, SWT.MeasureItem);
// queueWidgetEvent(widget, SWT.Deactivate);
// queueWidgetEvent(widget, SWT.FocusOut);
// return true;
// }
// }.execute();
}
public ICondition isExpanded(){
return new ItemExpandedCondition();
}
@SuppressWarnings("deprecation")
public TreeItemReference check(){
// new SWTTreeItemOperation(this).check().execute();
new SWTTreeItemOperation(this).show().checkSWTBotStyle().execute();
return this;
}
public TreeItemReference show(){
new SWTTreeItemOperation(this).show().execute();
return this;
}
public TreeItemReference click(IClickDescription click) {
show();
if ((click.modifierMask() & WT.CHECK) != 0) {
check();
}
else {
// new SWTTreeItemClickOperation(this).forClick(click).execute();
SWTTreeItemLocation loc = SWTTreeItemLocation.withDefaultTopLeft33(this, click);
// TODO process column base clicks
loc.column(-1 /* column */);
new SWTMouseOperation(click.modifierMask()).at(loc).count(click.clicks()).execute();
}
return this;
}
public ICondition isChecked(){
return new ItemCheckedCondition();
}
public String getPathString() {
//based on TreeItemPathMatcher implementation
return displayRef.execute(new Callable<String>(){
public String call() throws Exception {
TreeItem item = widget;
String path = TextUtils.escapeSlashes(item.getText());
//handle dummy child case (approximate?)
if (path == "") {
TreeItem parentItem = item.getParentItem();
if (parentItem != null)
if (!parentItem.getExpanded()) {
return path;
}
}
for (TreeItem parent = item.getParentItem(); parent != null; parent = parent
.getParentItem()) {
//prepend
//(be sure to fix slashes here too!
path = TextUtils.escapeSlashes(parent.getText()) + '/' + path;
}
return path;
}
});
}
/* (non-Javadoc)
* @see ISWTWidgetReferenceWithContextMenu#showContextMenu()
*/
public MenuReference showContextMenu(IClickDescription click) {
show();
// Tree items default context click location is NOT in the center of the tree item
SWTLocation location = SWTTreeItemLocation.withDefaultTopLeft33(this, click);
// On Linux, tree menus work more reliably with pauseOnMouseDown = true
// and it does not make a difference either way on Windows
SWTMenuOperation op = new SWTShowMenuOperation(null).waitForIdle().click(WT.BUTTON3, location, true);
op.execute();
return op.getMenu();
}
}