001 /*
002 * Copyright 2002-2004 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.richclient.application;
017
018 import java.awt.Window;
019 import java.util.ArrayList;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.Observable;
023 import java.beans.PropertyChangeSupport;
024 import java.beans.PropertyChangeListener;
025
026 import org.springframework.util.Assert;
027 import org.springframework.binding.value.PropertyChangePublisher;
028
029 /**
030 * A manager for a group of windows. Window managers are needed in applications
031 * which create many different windows in addition to a main window. A window
032 * manager can be used to remember all the windows that an application has
033 * created (independent of whether they are presently open or closed). There can
034 * be several window managers, and they can be arranged into a tree. This kind
035 * of organization makes it simple to close whole subgroupings of windows.
036 * <p>
037 * Associating a window with a window manager is done with
038 * <code>WindowManager.add(Window)</code>. A window is automatically removed
039 * from its window manager as a side effect of closing the window.
040 *
041 * @see Window
042 */
043 public class WindowManager extends Observable implements PropertyChangePublisher {
044
045 /**
046 * List of windows managed by this window manager (element type:
047 * <code>Window</code>).
048 */
049 private List windows = new ArrayList();
050
051 /**
052 * Parent window manager, or <code>null</code> if none.
053 */
054 private WindowManager parentManager;
055
056 /**
057 * List of window managers who have this window manager as their parent
058 * (element type: <code>WindowManager</code>).
059 */
060 private List subManagers;
061
062 /**
063 * Holds the currently active window.
064 */
065 private ApplicationWindow activeWindow;
066
067 private final PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
068
069 /**
070 * Creates an empty window manager without a parent window manager (that is,
071 * a root window manager).
072 */
073 public WindowManager() {
074 }
075
076 /**
077 * Creates an empty window manager with the given window manager as parent.
078 *
079 * @param parent
080 * the parent window manager
081 */
082 public WindowManager(WindowManager parent) {
083 Assert.notNull(parent);
084 parent.addWindowManager(this);
085 }
086
087 /**
088 * Adds the given window to the set of windows managed by this window
089 * manager. Does nothing is this window is already managed by this window
090 * manager.
091 *
092 * @param window
093 * the window
094 */
095 public void add(ApplicationWindow window) {
096 if (activeWindow == null) // first window will be set as activeWindow
097 setActiveWindow(window);
098
099 if (!windows.contains(window)) {
100 windows.add(window);
101 window.setWindowManager(this);
102 setChanged();
103 notifyObservers();
104 }
105 }
106
107 /**
108 * Adds the given window manager to the list of window managers that have
109 * this one as a parent.
110 *
111 * @param wm
112 * the child window manager
113 */
114 private void addWindowManager(WindowManager wm) {
115 if (subManagers == null) {
116 subManagers = new ArrayList();
117 }
118 if (!subManagers.contains(wm)) {
119 subManagers.add(wm);
120 wm.parentManager = this;
121 }
122 }
123
124 /**
125 * Attempts to close all windows managed by this window manager, as well as
126 * windows managed by any descendent window managers.
127 *
128 * @return <code>true</code> if all windows were sucessfully closed, and
129 * <code>false</code> if any window refused to close
130 */
131 public boolean close() {
132 List t = (List)((ArrayList)windows).clone();
133 Iterator e = t.iterator();
134 while (e.hasNext()) {
135 ApplicationWindow window = (ApplicationWindow)e.next();
136 if (!window.close()) { return false; }
137 }
138 if (subManagers != null) {
139 e = subManagers.iterator();
140 while (e.hasNext()) {
141 WindowManager wm = (WindowManager)e.next();
142 if (!wm.close()) { return false; }
143 }
144 }
145 return true;
146 }
147
148 /**
149 * Returns this window manager's set of windows.
150 *
151 * @return a possibly empty list of window
152 */
153 public ApplicationWindow[] getWindows() {
154 ApplicationWindow managed[] = new ApplicationWindow[windows.size()];
155 windows.toArray(managed);
156 return managed;
157 }
158
159 /**
160 * @return the parent of this WindowManager
161 */
162 public WindowManager getParent() {
163 return parentManager;
164 }
165
166 /**
167 * Removes the given window from the set of windows managed by this window
168 * manager. Does nothing is this window is not managed by this window
169 * manager.
170 *
171 * @param window
172 * the window
173 */
174 public final void remove(ApplicationWindow window) {
175 if (windows.contains(window)) {
176 windows.remove(window);
177 window.setWindowManager(null);
178 setChanged();
179 notifyObservers();
180 }
181 }
182
183 /**
184 * Set the currently active window. When a window gets focus, it will set itself
185 * as the current window of it's manager.
186 *
187 * @param window
188 */
189 public final void setActiveWindow(ApplicationWindow window)
190 {
191 final ApplicationWindow old = this.activeWindow;
192 this.activeWindow = window;
193 if (getParent() != null) // let things ripple up
194 getParent().setActiveWindow(window);
195 getChangeSupport().firePropertyChange("activeWindow", old, window);
196 }
197
198 /**
199 * @return the active window.
200 */
201 public final ApplicationWindow getActiveWindow()
202 {
203 return this.activeWindow;
204 }
205
206 /**
207 * @return Number of windows managed by this instance.
208 */
209 public int size() {
210 return windows.size();
211 }
212
213
214 protected PropertyChangeSupport getChangeSupport() {
215 return changeSupport;
216 }
217
218
219
220
221 //
222 // METHODS FROM INTERFACE PropertyChangePublisher
223 //
224
225
226 public void addPropertyChangeListener(PropertyChangeListener listener) {
227 getChangeSupport().addPropertyChangeListener(listener);
228 }
229
230 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
231 getChangeSupport().addPropertyChangeListener(propertyName, listener);
232 }
233
234 public void removePropertyChangeListener(PropertyChangeListener listener) {
235 getChangeSupport().removePropertyChangeListener(listener);
236 }
237
238 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
239 getChangeSupport().removePropertyChangeListener(propertyName, listener);
240 }
241 }