/******************************************************************************* * 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.Color; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import com.windowtester.runtime.WaitTimedOutException; import com.windowtester.runtime.internal.concurrent.SafeCallable; import com.windowtester.runtime.internal.concurrent.VoidCallable; import com.windowtester.runtime.swt.internal.operation.SWTShowMenuOperation; import com.windowtester.runtime.swt.internal.widgets.SWTWidgetReference.Visitor; import com.windowtester.runtime.swt.internal.widgets.finder.MatchCollector; /** * A {@link Display} reference. */ public class DisplayReference implements IVisitable, ISearchable { private static final int DEFAULT_EXEC_WAIT_TIME = 10000; private final Display display; public static DisplayReference getDefault() { return new DisplayReference(Display.getDefault()); } public DisplayReference(Display display) { this.display = display; } /* (non-Javadoc) * @see com.windowtester.runtime.swt.internal.widgets.IDisplayReference#getDisplay() */ public Display getDisplay() { // TODO[pq]: come up with a pithy message to warn users that any access to the returned item must be down safely on the UI thread return display; } /* (non-Javadoc) * @see com.windowtester.runtime.swt.internal.widgets.IDisplayReference#getFocusControl() */ public ControlReference<?> getFocusControl() { return execute(new Callable<ControlReference<?>>() { public ControlReference<?> call() throws Exception { return SWTWidgetReference.forControl(display.getFocusControl()); } }); } /* (non-Javadoc) * @see com.windowtester.runtime.swt.internal.widgets.IDisplayReference#getActiveShell() */ public ShellReference getActiveShell() { return execute(new Callable<ShellReference>() { public ShellReference call() throws Exception { Shell shell = display.getActiveShell(); return ShellReference.forShell(shell); } }); } public ShellReference[] getShells() { return execute(new Callable<ShellReference[]>() { public ShellReference[] call() throws Exception { return ShellReference.forShells(display.getShells()); } }); } /* (non-Javadoc) * @see com.windowtester.runtime.swt.widgets.IDisplayReference#getSystemColor(int) */ public Color getSystemColor(final int id) { return execute(new Callable<Color>() { public Color call() throws Exception { return display.getSystemColor(id); } }); } public ISWTWidgetReference<?>[] findWidgets(ISWTWidgetMatcher matcher) { //implemented in terms of a visit: MatchCollector collector = new MatchCollector(matcher); return (ISWTWidgetReference<?>[]) collector.findMatchesIn(this).toArray(SWTWidgetReference.emptyArray()); } public void accept(Visitor visitor) { for (ShellReference shell : getShells()) shell.accept(visitor); } /** * Convenience method that calls {@link #execute(Callable, long)} with a maximum wait * time of 10 seconds. */ public <T> T execute(Callable<T> callable) { return execute(callable, DEFAULT_EXEC_WAIT_TIME); } /** * Execute the specified callable on the SWT UI thread. This method will not return * until the callable finishes executing, an exception is thrown, or the specified * maximum number of milliseconds have elapsed. If an exception does occur and the * callable object implements {@link SafeCallable}, then * {@link SafeCallable#handleException(Exception)} is called with the exception that * occurred. * * @param maxWaitTime the maximum number of milliseconds to wait for the UI thread to * execute the callable. If this method is called from the SWT UI thread, * then the maximum number of milliseconds is ignored. * @throws SWTUIException if there is an exception when executing the callable on * the UI thread * @throws IllegalStateException if the receiver is already executing * @throws WaitTimedOutException if the UI thread does not execute the callable with * specified number of milliseconds */ public <T> T execute(Callable<T> callable, long maxWaitTime) { return new SWTUIExecutor<T>(callable).run(getDisplay(), maxWaitTime, 10); } /** * Convenience method that calls {@link #execute(Callable, long)} with a maximum wait * time of 10 seconds, but does not return any result */ public void execute(final VoidCallable voidCallable) { execute(voidCallable, DEFAULT_EXEC_WAIT_TIME); } /** * Convenience method that calls {@link #execute(Callable, long)} , but does not * return any result */ public void execute(final VoidCallable voidCallable, int maxWaitTime) { execute(new SafeCallable<Object>() { public Object call() throws Exception { voidCallable.call(); return null; } public Object handleException(Throwable e) throws Throwable { voidCallable.handleException(e); return null; } }, maxWaitTime); } /** * Cleanup by closing any open menus */ public void closeAllMenus() { new SWTShowMenuOperation(null).closeAllMenus().execute(); } /** * Check if the UI thread has finished processing all asynchronous messages. * * @return <code>true</code> if the UI thread is idle or disposed */ public boolean isIdle() { return execute(new Callable<Boolean>() { public Boolean call() throws Exception { return display.isDisposed() || !display.readAndDispatch(); } }); } }