/*******************************************************************************
* 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.finder.legacy;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
import abbot.finder.swt.Matcher;
import abbot.finder.swt.SWTHierarchy;
import com.windowtester.runtime.swt.internal.abbot.matcher.HierarchyMatcher;
import com.windowtester.runtime.swt.internal.abbot.matcher.ShellComponentMatcher;
import com.windowtester.runtime.swt.internal.finder.ShellFinder;
import com.windowtester.runtime.swt.internal.finder.legacy.WidgetFinder.MatchResult;
import com.windowtester.runtime.swt.internal.selector.UIDriver;
/**
* Used for scoping widget searches by active shell.
*
*/
public class SearchScopeHelper {
private final SWTHierarchy _hierarchy;
private final WidgetFinder _finder = new WidgetFinder();
//used for caching current active shell
//private Shell _activeShell;
private static int MAX_SHELL_FIND_RETRIES = 6;
private static int SHELL_FIND_RETRY_INTERVAL = 500;
/**
* Create an instance based on the given hierarchy.
*/
public SearchScopeHelper(SWTHierarchy hierarchy) {
_hierarchy = hierarchy;
}
/**
* Find the Shell by which to scope this search.
*/
public Shell getShellSearchScope(Matcher m) {
//if it is explicitly scoped by a shell matcher, use that shell for scope
if (m instanceof HierarchyMatcher) {
Matcher topMatcher = getTopMatcher((HierarchyMatcher)m);
if (topMatcher instanceof ShellComponentMatcher) {
final ShellComponentMatcher shellMatcher = (ShellComponentMatcher)topMatcher;
MatchResult result = _finder.find(_hierarchy, new Matcher() {
public boolean matches(Widget w) {
return shellMatcher.isShellMatch(w);
}
});
if (result.getType() == WidgetFinder.MATCH)
return (Shell) result.getWidget();
//TODO: handle exceptions here
return null;
}
}
//if no top level shell matcher is specified, use the active shell
return getActiveShell();
}
private Shell getActiveShell() {
//rolling back to address regressions on win32
// fetchAndSetActiveShell();
// validateActiveShell();
// return _activeShell;
/*
* Rather than return null right away, we will wait a bit for
* the shell to be non-null. This eases debugging.
*
*
* TODO: we should really be delegating to a UIContext but there's no instance handy...
*/
Shell shell = ShellFinder.getActiveShell(getDisplay());
for(int i =0; shell == null && i < MAX_SHELL_FIND_RETRIES; ++i) {
UIDriver.pause(SHELL_FIND_RETRY_INTERVAL);
shell = ShellFinder.getActiveShell(getDisplay());
}
return shell;
}
// /**
// * Get the active shell from the display.
// */
// private void fetchAndSetActiveShell() {
// final Display display = getDisplay();
// display.syncExec(new Runnable() {
// public void run() {
// _activeShell = display.getActiveShell();
// }
// });
// if (_activeShell == null)
// LogHandler.log("fetch of active shell yielded <null> in SearchScopeHelper");
// }
/**
* Get the display.
*/
private Display getDisplay() {
return _hierarchy.getDisplay();
}
// /**
// * Confirm that the active shell is valid.
// * Invalid case:
// * - active shell is BEHIND a modal shell that is inactive
// * (despite having event focus)
// */
// private void validateActiveShell() {
// Shell modalShell = getModalShell();
// if (modalShell != null && modalShell != _activeShell) {
// LogHandler.log("(SearchScopeHelper) - active shell: " + toString(_activeShell) + " invalid, updating to current modal shell: " + toString(modalShell));
// _activeShell = modalShell;
// }
// }
// /**
// * Get the string representation of this shell.
// */
// private String toString(Shell shell) {
// return UIProxy.getToString(shell);
// }
// /**
// * Get the current modal shell or <code>null</code> if there is none.
// */
// private Shell getModalShell() {
// return ShellFinder.getModalShell(getDisplay());
// }
private Matcher getTopMatcher(HierarchyMatcher matcher) {
Matcher parent = null;
do {
parent = matcher.getParentMatcher();
if (parent instanceof HierarchyMatcher)
matcher = (HierarchyMatcher) parent;
//TODO: clean up this logic
} while (parent != null && parent instanceof HierarchyMatcher);
return parent;
}
}