package abbot.finder.swt;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
import abbot.tester.swt.DecorationsTracker;
/** Provide filtering of components in the current hierarchy to facilitate
testing. Widgets may be filtered after disposal so they don't factor
into future test results.<p>
In general, only Decorations are filtered, and isFiltered checks for both self
and Decorations being filtered. So getWidgets() returns a filtered set only
when the parent is a Decorations or Shell.<p>
*/
public class TestHierarchy extends SWTHierarchy {
private Map filtered = new WeakHashMap();
// private Map transientFiltered = new WeakHashMap();
// private static boolean trackAppletConsole =
// Boolean.getBoolean("abbot.applet.track_console");
// must keep a reference to this, or it will be gc'd
// private Listener listener;
public TestHierarchy(Display d) {
super(d);
display = d;
tracker = DecorationsTracker.getTracker(display);
//ignoreExisting();
// Watch for introduction of transient dialogs so we can automatically
// filter them on dispose (WINDOW_CLOSED). Don't do anything when the
// component is simply hidden, since we can't tell whether it will be
// re-used.
// TODO: look up the equivalent for SWT
// listener = new Listener() {
// public void handleEvent(Event e) {
// if (e.type == SWT.Activate || e.type == SWT.Deiconify
// && e.widget instanceof Decorations) {
// final Decorations d = (Decorations)e.widget;
// if (transientFiltered.containsKey(d)) {
// // In case we disposed of it before
// setFiltered(d, false);
// }
// }
// else if (e.type == SWT.Close) {
// Decorations d = (Decorations)e.widget;
// if (SWT.isTransientDialog(w)) {
// setFiltered(w, true);
// transientFiltered.put(w, Boolean.TRUE);
// }
// }
// }
// };
// Add a weak listener so we don't leave a listener lingering about.
// new WeakSWTEventListener(listener, WindowEvent.WINDOW_EVENT_MASK);
}
public boolean contains(Widget c) {
return super.contains(c) && !isFiltered(c);
}
public void dispose(Decorations d) {
if (contains(d)) {
super.dispose(d);
setFiltered(d, true);
}
}
public void ignoreExisting() {
Iterator iter = getRoots().iterator();
while (iter.hasNext()) {
setFiltered((Widget)iter.next(), true);
}
}
public Collection getRoots() {
Collection s = super.getRoots();
s.removeAll(filtered.keySet());
return s;
}
public Collection getWidgets(Widget w) {
//return super.getWidgets(w);
if (!isFiltered(w)) {
Collection s = super.getWidgets(w);
// NOTE: this only removes those components which are directly
// filtered.
s.removeAll(filtered.keySet());
return s;
}
return EMPTY;
}
// private boolean isDecorationsFiltered(Widget w) {
// if (w instanceof Control) {
// Decorations d = ((Control)w).getShell();
// return w != null && isFiltered(w);
// } else {
// return false;
// }
// }
public boolean isFiltered(Widget w) {
return filtered.containsKey(w);
//|| (!(w instanceof Decorations) && isDecorationsFiltered(w));
}
/** Indicates whether the given component is to be included in the
Hierarchy. If the component is a Window, recursively applies the
action to all owned Windows.
*/
public void setFiltered(final Widget w, final boolean filter) {
// if (SWT.isSharedInvisibleFrame(c)) {
// Iterator iter = getWidgets(c).iterator();
// while (iter.hasNext()) {
// setFiltered((Widget)iter.next(), filter);
// }
// }
// else
{
if (filter)
filtered.put(w, Boolean.TRUE);
else
filtered.remove(w);
if (w instanceof Shell) {
display.syncExec( new Runnable() {
public void run() {
Shell[] owned = ((Shell)w).getShells();
for (int i=0;i < owned.length;i++) {
setFiltered(owned[i], filter);
}
}
});
}
}
}
}