org.assertj.swing.monitor.WindowMonitor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of assertj-swing Show documentation
Show all versions of assertj-swing Show documentation
Fluent interface for functional GUI testing
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* Copyright 2012-2015 the original author or authors.
*/
package org.assertj.swing.monitor;
import static org.assertj.core.util.Preconditions.checkNotNull;
import static org.assertj.swing.edt.GuiActionRunner.execute;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.Window;
import java.util.Collection;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.assertj.core.util.VisibleForTesting;
import org.assertj.swing.annotation.RunsInCurrentThread;
import org.assertj.swing.annotation.RunsInEDT;
import org.assertj.swing.edt.GuiQuery;
import org.assertj.swing.util.ToolkitProvider;
/**
* Monitor that keeps track of all known root AWT or Swing {@code Window}s (showing, hidden, closed).
*
* @author Alex Ruiz
*/
public class WindowMonitor {
private final Context context;
private final ContextMonitor contextMonitor;
private final Windows windows;
private final WindowStatus windowStatus;
private final WindowAvailabilityMonitor windowAvailabilityMonitor;
/**
*
* Create an instance of WindowTracker which will track all windows coming and going on the current and subsequent
* {@code AppContext}s.
*
*
*
* WARNING: if an applet loads this class, it will only ever see stuff in its own {@code AppContext}.
*
*
* @param toolkit the {@code Toolkit} to use.
*/
@RunsInCurrentThread
WindowMonitor(@Nonnull Toolkit toolkit) {
this(toolkit, new Context(toolkit), new WindowStatus(new Windows()));
}
@VisibleForTesting
@RunsInCurrentThread
WindowMonitor(@Nonnull Toolkit toolkit, @Nonnull Context context, @Nonnull WindowStatus windowStatus) {
this.context = context;
this.windowStatus = windowStatus;
windows = windowStatus.windows();
contextMonitor = new ContextMonitor(context, windows);
contextMonitor.attachTo(toolkit);
windowAvailabilityMonitor = new WindowAvailabilityMonitor(windows);
windowAvailabilityMonitor.attachTo(toolkit);
populateExistingWindows();
}
private void populateExistingWindows() {
for (Frame f : Frame.getFrames()) {
examine(checkNotNull(f));
}
}
@RunsInCurrentThread
private void examine(@Nonnull Window w) {
windows.attachNewWindowVisibilityMonitor(w);
for (Window owned : w.getOwnedWindows()) {
examine(checkNotNull(owned));
}
windows.markExisting(w);
context.addContextFor(w);
}
/**
* Returns whether the AWT or Swing {@code Window} is ready to receive OS-level event input. A {@code Window}'s
* "isShowing" flag may be set {@code true} before the {@code WINDOW_OPENED} event is generated, and even after the
* {@code WINDOW_OPENED} event is sent, the {@code Window} peer is not guaranteed to be ready.
*
* @param w the given {@code Window}.
* @return whether the {@code Window} is ready to receive OS-level event input.
*/
public boolean isWindowReady(@Nonnull Window w) {
if (windows.isReady(w)) {
return true;
}
windowStatus.checkIfReady(w);
return false;
}
/**
* Returns the event queue corresponding to the given AWT or Swing {@code Compoenent}. In most cases, this is the same
* as {@code Component.getToolkit().getSystemEventQueue()}, but in the case of applets will bypass the
* {@code AppContext} and provide the real event queue.
*
* @param c the given {@code Component}.
* @return the event queue corresponding to the given component.
*/
public @Nullable EventQueue eventQueueFor(@Nonnull Component c) {
return context.eventQueueFor(c);
}
/**
* @return all known event queues.
*/
public @Nonnull Collection allEventQueues() {
return context.allEventQueues();
}
/**
* Return all available root {@code Window}s. A root {@code Window} is one that has a {@code null} parent. Nominally
* this means a list similar to that returned by {@code Frame.getFrames()}, but in the case of an {@code Applet} may
* return a few dialogs as well.
*
* @return all available root {@code Window}s.
*/
public @Nonnull Collection rootWindows() {
return context.rootWindows();
}
/**
* @return the singleton instance of this class.
*/
@RunsInEDT
public static @Nonnull WindowMonitor instance() {
return SingletonLazyLoader.INSTANCE;
}
@RunsInEDT
private static class SingletonLazyLoader {
static final WindowMonitor INSTANCE = execute(new GuiQuery() {
@Override
protected WindowMonitor executeInEDT() {
return new WindowMonitor(ToolkitProvider.instance().defaultToolkit());
};
});
}
}