package abbot.finder.matchers.swt;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import abbot.finder.swt.MultiMatcher;
import abbot.finder.swt.MultipleWidgetsFoundException;
/**
* A matcher for the text of a widget.
* <p/>
* To speed up search, optionally a class type can be provided which a widget
* must match.
*
* @author Jack Frink
* @version $Id: TextMultiMatcher.java,v 1.1 2005-12-19 20:28:31 pq Exp $
*/
public class TextMultiMatcher extends ClassMatcher implements MultiMatcher {
private final Class clazz;
private final String text;
private int index;
private String wtext = null;
private String wtexts[] = null;
private final boolean mustBeShowing;
private volatile boolean controlShowing = true;
private boolean throwException = false;
/**
* Constructs a Matcher for the text given at the indicated index.
* <p/>
* The widget must be visible.
* @param text the text to match.
* @param index the particular repitition of the text to match
*/
public TextMultiMatcher(String text, int index) {
this(text, index, true, Widget.class);
}
/**
*This constructor allows you to get all Strings matching
* the text back via a multiple widgets found exception
* <p/>
* The text must be visible.
* @param text the text to match.
* @param boolean throwException
*/
public TextMultiMatcher(String text, boolean throwException) {
this(text, 1, true, Widget.class);
this.throwException = throwException;
}
/**
* Constructs a matcher with the text, index and the class given.
* <p/>
* The widget must be visible. Note that searches are considerably faster
* when a class is provided to the matcher.
* @param text the text to match.
* @param clazz the Class to match.
*/
public TextMultiMatcher(String text, int index, Class clazz) {
this(text, index, true, clazz);
}
/**
* Constructs a Matcher with the text, index, visibility and class given.
* <p/>
* Note that searches are considerably faster when a class is provided
* to the matcher.
* @param text the text to match.
* @param mustBeShowing true if the widget must be visible.
* @param clazz the class to match.
*/
public TextMultiMatcher(String text, int index, boolean mustBeShowing, Class clazz) {
super(clazz);
this.text = text;
this.index = index;
this.clazz = clazz;
this.mustBeShowing = mustBeShowing;
}
/**
* {@inheritDoc}
* @param w {@inheritDoc}
* @return {@inheritDoc}
* @see abbot.finder.swt.Matcher#matches(org.eclipse.swt.widgets.Widget)
*/
public boolean matches(final Widget w) {
if (this.clazz != null) {
boolean superResult = super.matches(w);
if (!superResult) {
return false;
}
}
/* allow trimmed matches? (ignore whitespace in making comparisons) */
setWtext(null);
setWtexts(null);
controlShowing = true;
w.getDisplay().syncExec( new Runnable() {
public void run() {
if (w instanceof Control) {
controlShowing = ((Control)w).getVisible() && ((Control)w).getShell().getVisible();
//System.out.println("Widget " + w + " showing: " + controlShowing);
}
if (w instanceof Button) {
setWtext(((Button)w).getText());
}
if (w instanceof Combo) {
setWtext(((Combo)w).getText());
}
if (w instanceof Decorations) {
setWtext(((Decorations)w).getText());
}
if (w instanceof Group) {
setWtext(((Group)w).getText());
}
if (w instanceof Item) {
if (w instanceof TableItem && ((TableItem)w).getParent().getColumnCount() > 0 ) {
int columns = ((TableItem)w).getParent().getColumnCount();
setWtext(((TableItem)w).getText(0));
String[] lWtexts = new String[columns];
for (int i=0;i<lWtexts.length;i++) {
lWtexts[i] = ((TableItem)w).getText(i);
}
setWtexts(lWtexts);
} else {
setWtext(((Item)w).getText());
}
}
if (w instanceof Label) {
setWtext(((Label)w).getText());
}
if (w instanceof Text) {
setWtext(((Text)w).getText());
}
}});
// System.out.println ("Matching: wtext, text");
// System.out.println ("wtext: " + wtext);
// System.out.println ("text: " + text);
String[] lWtexts = this.getWtexts();
if (lWtexts!=null) {
for (int i=0;i<lWtexts.length;i++) {
//System.out.println("wts:" + wtexts[i]);
if (stringsMatch(text,lWtexts[i])) return true;
}
}
if (mustBeShowing && !controlShowing) return false;
if (this.getWtext()==null) return false;
if (text == null)
return this.getWtext() == null;
return stringsMatch(text, getWtext());
}
public boolean matches (Dialog d) {
String dtext = d.getText();
if (text == null)
return dtext == null;
return stringsMatch(text, dtext);
}
/*
* @see abbot.finder.swt.MultiMatcher#bestMatch(org.eclipse.swt.widgets.Widget[])
*/
public Widget bestMatch(Widget[] candidates) throws MultipleWidgetsFoundException {
if (throwException) {
/* ignore the passed index */
throw new MultipleWidgetsFoundException(candidates);
}
if (candidates.length < index)
throw new MultipleWidgetsFoundException(candidates);
else
return candidates[index-1];
}
public String toString() {
return "Text matcher (" + text + ")";
}
// Necessitated by JVM memory model requirements
private synchronized String getWtext() {
return this.wtext;
}
// Necessitated by JVM memory model requirements
private synchronized void setWtext(String pWtext) {
this.wtext = pWtext;
}
// Necessitated by JVM memory model requirements
private synchronized String[] getWtexts() {
return this.wtexts;
}
// Necessitated by JVM memory model requirements
private synchronized void setWtexts(String[] pWtexts) {
this.wtexts = pWtexts;
}
/**
* Retrieve the text of this matcher.
* @return Returns the text.
*/
public String getText() {
return text;
}
}