001 /* 002 * Created on Oct 8, 2007 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 005 * 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 is distributed on 010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 011 * specific language governing permissions and limitations under the License. 012 * 013 * Copyright @2007-2010 the original author or authors. 014 */ 015 package org.fest.swing.monitor; 016 017 import static org.fest.swing.edt.GuiActionRunner.execute; 018 019 import java.awt.*; 020 import java.util.Collection; 021 022 import org.fest.swing.annotation.RunsInCurrentThread; 023 import org.fest.swing.annotation.RunsInEDT; 024 import org.fest.swing.edt.GuiQuery; 025 import org.fest.util.VisibleForTesting; 026 027 /** 028 * Understands a monitor that keeps track of all known root windows (showing, hidden, closed.) 029 * 030 * @author Alex Ruiz 031 */ 032 public class WindowMonitor { 033 034 private final Context context; 035 private final ContextMonitor contextMonitor; 036 private final Windows windows; 037 private final WindowStatus windowStatus; 038 private final WindowAvailabilityMonitor windowAvailabilityMonitor; 039 040 /** 041 * Create an instance of WindowTracker which will track all windows coming and going on the current and subsequent 042 * <code>AppContext</code>s. 043 * <p> 044 * <strong>WARNING:</strong> if an applet loads this class, it will only ever see stuff in its own 045 * <code>AppContext</code>. 046 * </p> 047 * @param toolkit the <code>Toolkit</code> to use. 048 */ 049 @RunsInCurrentThread 050 WindowMonitor(Toolkit toolkit) { 051 this(toolkit, new Context(toolkit), new WindowStatus(new Windows())); 052 } 053 054 @VisibleForTesting 055 @RunsInCurrentThread 056 WindowMonitor(Toolkit toolkit, Context context, WindowStatus windowStatus) { 057 this.context = context; 058 this.windowStatus = windowStatus; 059 windows = windowStatus.windows(); 060 contextMonitor = new ContextMonitor(context, windows); 061 contextMonitor.attachTo(toolkit); 062 windowAvailabilityMonitor = new WindowAvailabilityMonitor(windows); 063 windowAvailabilityMonitor.attachTo(toolkit); 064 populateExistingWindows(); 065 } 066 067 private void populateExistingWindows() { 068 for (Frame f : Frame.getFrames()) examine(f); 069 } 070 071 @RunsInCurrentThread 072 private void examine(Window w) { 073 windows.attachNewWindowVisibilityMonitor(w); 074 for (Window owned : w.getOwnedWindows()) examine(owned); 075 windows.markExisting(w); 076 context.addContextFor(w); 077 } 078 079 /** 080 * Returns whether the window is ready to receive OS-level event input. A window's "isShowing" flag may be set 081 * <code>true</code> before the <code>WINDOW_OPENED</code> event is generated, and even after the 082 * <code>WINDOW_OPENED</code> is sent the window peer is not guaranteed to be ready. 083 * @param w the given window. 084 * @return whether the window is ready to receive OS-level event input. 085 */ 086 public boolean isWindowReady(Window w) { 087 if (windows.isReady(w)) return true; 088 windowStatus.checkIfReady(w); 089 return false; 090 } 091 092 /** 093 * Returns the event queue corresponding to the given component. In most cases, this is the same as 094 * <code>Component.getToolkit().getSystemEventQueue()</code>, but in the case of applets will bypass the 095 * <code>AppContext</code> and provide the real event queue. 096 * @param c the given component. 097 * @return the event queue corresponding to the given component. 098 */ 099 public EventQueue eventQueueFor(Component c) { 100 return context.eventQueueFor(c); 101 } 102 103 /** 104 * Returns all known event queues. 105 * @return all known event queues. 106 */ 107 public Collection<EventQueue> allEventQueues() { 108 return context.allEventQueues(); 109 } 110 111 /** 112 * Return all available root windows. A root window is one that has a null parent. Nominally this means a list similar 113 * to that returned by <code>{@link Frame#getFrames() Frame.getFrames()}</code>, but in the case of an 114 * <code>{@link java.applet.Applet}</code> may return a few dialogs as well. 115 * @return all available root windows. 116 */ 117 public Collection<Window> rootWindows() { 118 return context.rootWindows(); 119 } 120 121 /** 122 * Returns the singleton instance of this class. 123 * @return the singleton instance of this class. 124 */ 125 @RunsInEDT 126 public static WindowMonitor instance() { 127 return SingletonLazyLoader.INSTANCE; 128 } 129 130 @RunsInEDT 131 private static class SingletonLazyLoader { 132 static final WindowMonitor INSTANCE = execute(new GuiQuery<WindowMonitor>() { 133 protected WindowMonitor executeInEDT() throws Throwable { 134 return new WindowMonitor(Toolkit.getDefaultToolkit()); 135 } 136 }); 137 } 138 }