001 /*
002 * Created on Nov 21, 2008
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 *
014 * Copyright @2008-2010 the original author or authors.
015 */
016 package org.fest.swing.driver;
017
018 import static org.fest.swing.query.ComponentVisibleQuery.isVisible;
019 import static org.fest.swing.timing.Pause.pause;
020 import static org.fest.swing.util.TimeoutWatch.startWatchWithTimeoutOf;
021
022 import java.awt.Component;
023 import java.awt.event.ComponentAdapter;
024 import java.awt.event.ComponentEvent;
025
026 import org.fest.swing.annotation.RunsInEDT;
027 import org.fest.swing.exception.WaitTimedOutError;
028 import org.fest.swing.util.TimeoutWatch;
029
030 /**
031 * Understands waiting for a <code>{@link Component}</code> to be shown.
032 *
033 * @author Alex Ruiz
034 */
035 public final class ComponentShownWaiter extends ComponentAdapter {
036
037 private static final int DEFAULT_TIMEOUT = 5000;
038 private static final int DEFAULT_SLEEP_TIME = 10;
039
040 private Component toWaitFor;
041 private volatile boolean shown;
042
043 /**
044 * Waits until the given component is shown on the screen, using a timeout of 5 seconds.
045 * @param toWaitFor the component to wait for.
046 * @throws WaitTimedOutError if the component is not shown before the default timeout of 5 seconds.
047 */
048 public static void waitTillShown(Component toWaitFor) {
049 new ComponentShownWaiter(toWaitFor).startWaiting(DEFAULT_TIMEOUT);
050 }
051
052 /**
053 * Waits until the given component is shown on the screen.
054 * @param toWaitFor the component to wait for.
055 * @param timeout the amount to time (in milliseconds) to wait for the component to be shown.
056 * @throws WaitTimedOutError if the component is not shown before the given timeout expires.
057 */
058 public static void waitTillShown(Component toWaitFor, long timeout) {
059 new ComponentShownWaiter(toWaitFor).startWaiting(timeout);
060 }
061
062 private ComponentShownWaiter(Component toWaitFor) {
063 this.toWaitFor = toWaitFor;
064 toWaitFor.addComponentListener(this);
065 }
066
067 private void startWaiting(long timeout) {
068 if (alreadyVisible()) return;
069 TimeoutWatch watch = startWatchWithTimeoutOf(timeout);
070 while (!shown) {
071 pause(DEFAULT_SLEEP_TIME);
072 if (watch.isTimeOut()) {
073 done();
074 throw new WaitTimedOutError("Timed out waiting for component to be visible");
075 }
076 }
077 }
078
079 private boolean alreadyVisible() {
080 if (!isVisible(toWaitFor)) return false;
081 done();
082 return true;
083 }
084
085 /**
086 * Notification that the component to wait for is finally shown on the screen.
087 * @param e the event raised when the component has been made visible.
088 */
089 @RunsInEDT
090 @Override public void componentShown(ComponentEvent e) {
091 shown = true;
092 done();
093 }
094
095 private void done() {
096 toWaitFor.removeComponentListener(this);
097 toWaitFor = null;
098 }
099 }