/*******************************************************************************
* 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.condition;
import com.windowtester.runtime.IUIContext;
/**
* A condition monitor checks for registered conditions and activates their associated
* handlers. The order in which conditions are checked is entirely unspecified. Once a
* condition is satisfied, the associated handler is activated before checking any
* remaining conditions. Conditions are not checked during the handling of conditions to
* prevent infinite recursion.
* <p>
* Conditions are processed BEFORE all atomic event generating UIContext actions. For
* example, conditions are checked before the click method in the following code:
*
* <pre>
* public void testMain() throws Exception {
* IUIContext ui = getUIContext();
* ui.click(new MenuItemLocator("New/Project..."));
* ...
* </pre>
*
* <p>
* Conditions are added by obtaining this interface from the IUIContext. The
* {@link com.windowtester.runtime.condition.ICondition#test()} method and the
* {@link com.windowtester.runtime.condition.IHandler#handle(IUIContext)} method are both
* called on the WindowTester test thread, so accessing widgets must be through the
* IUIContext interface, using locator accessor methods such as a implementor of
* {@link com.windowtester.runtime.condition.IsEnabled#isEnabled(IUIContext)}, using
* {@link com.windowtester.runtime.swt.condition.SWTUIConditionAdapter}, or using
* {@link org.eclipse.swt.widgets.Display#syncExec(java.lang.Runnable)}. For example:
*
* <pre>
* public void testSomething() throws Exception {
* IUIContext ui = getUIContext();
* IConditionMonitor cm = ui.getAdapter(IConditionMonitor.class);
* cm.addHandler(
* new ICondition() {
* public boolean test() {
* ... test some condition here ...
* }
* },
* new IHandler() {
* public void handle(IUIContext ui) {
* ... take some actions here ...
* }
* }
* );
* ...
* </pre>
*
* or using {@link com.windowtester.runtime.swt.condition.SWTUIConditionAdapter}
*
* <pre>
* public void testSomething() throws Exception {
* IUIContext ui = getUIContext();
* IConditionMonitor cm = ui.getAdapter(IConditionMonitor.class);
* cm.addHandler(
* new SWTUIConditionAdapter() {
* public boolean testUI(Display display) {
* ... test some condition here ...
* }
* },
* new IHandler() {
* public void handle(IUIContext ui) {
* ... take some actions here ...
* }
* }
* );
* ...
* </pre>
*
* If {@link IConditionMonitor} detects that an {@link ICondition} implements
* {@link IUICondition}, then {@link IConditionMonitor} calls {@link #testUI(IUIContext)}
* rather than {@link ICondition#test()}.
*/
public interface IConditionMonitor
{
/**
* A flag returned by {@link #process()} indicating that the conditions were processed
* and no conditions were satisified.
*/
public static final int PROCESS_NONE = 0;
/**
* A flag returned by {@link #process()} indicating that the conditions were processed
* and at least one condition was satisfied.
*/
public static final int PROCESS_ONE_OR_MORE = 1;
/**
* A flag returned by {@link #process()} indicating that conditions are already being
* processed and that the call returned immediately
*/
public static final int PROCESS_RECURSIVE = 2;
/**
* A flag returned by {@link #process()} indicating that no conditions were
* processed because the application is interacting with native OS functionality
* and that the call returned immediately. Since conditions might access the UI thread
* during processing, it is necessary to skip them when the application goes native
* lest the test thread be blocked.
*/
public static final int PROCESS_NATIVE = 3;
/**
* Add the specified condition and associated handler to the receiver so that it is
* included the next time that conditions are processed. WARNING! No checking is
* performed to prevent condition/handler pairs from being added multiple times.
*
* @param condition the condition to be tested (not <code>null</code>)
* @param handler the handler to be activated if the condition is satisified
*/
void add(ICondition condition, IHandler handler);
/**
* Add a handler that is called when a dialog matching the specified condition becomes
* visible. The handler's <code>test</code> method is called on the UI thread and
* the <code>handle</code> is called on the WindowTester test.
*
* @param conditionHandler the condition handler to match (not <code>null</code>)
*/
void add(IConditionHandler conditionHandler);
/**
* Remove all the registered handlers from this monitor.
*/
void removeAll();
/**
* Process all condition/handler pairs by checking each condition and calling the
* associated handlers for any conditions that are satisfied. Nested calls to this
* method return immediately without taking any action.
*
* @param ui the UIContext instance for use in condition handling
* @return one of the following flags indicating what was processed:
* {@link #PROCESS_NONE} if conditions were processed but no conditions were
* satisified, {@link #PROCESS_ONE_OR_MORE} if conditions were processed and
* at least on condition was satisified, {@link #PROCESS_RECURSIVE} if
* conditions were already being processed and no additional action was taken.
*/
int process(IUIContext ui);
}