001 package com.croftsoft.core.gui;
002
003 import java.awt.*;
004 import java.awt.event.*;
005 import javax.swing.*;
006
007 import com.croftsoft.core.awt.image.ImageLib;
008 import com.croftsoft.core.gui.FullScreenToggler;
009 import com.croftsoft.core.lang.NullArgumentException;
010 import com.croftsoft.core.lang.lifecycle.AppletLifecycle;
011 import com.croftsoft.core.lang.lifecycle.Lifecycle;
012 import com.croftsoft.core.lang.lifecycle.LifecycleLib;
013
014 /*********************************************************************
015 * Calls the lifecycle methods in response to windowing events.
016 *
017 * <p>
018 * When the window is activated, calls the start() methods.
019 * When the window is deactivated, calls the stop() methods.
020 * The first time the window is activated, the init() method
021 * will be called.
022 * </p>
023 *
024 * <p>
025 * Performs the following upon the window closing event:
026 * <ol>
027 * <li> Prompts for shutdown confirmation.
028 * <li> Calls the window hide() method.
029 * <li> Calls the stop and destroy() method, in array order, of each of
030 * the Lifecycle instances passed via the constructor argument.
031 * Any exceptions are caught, printed, and ignored.
032 * <li> Calls the window dispose() method.
033 * <li> Calls System.exit(0).
034 * </ol>
035 * </p>
036 *
037 * <p>
038 * Example:
039 * <code>
040 * <pre>
041 * jFrame.setDefaultCloseOperation (
042 * javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE );
043 *
044 * jFrame.addWindowListener (
045 * new LifecycleWindowListener ( this, "Exit Program?" ) );
046 * </pre>
047 * </code>
048 * </p>
049 *
050 * @version
051 * $Date: 2006/01/03 20:05:54 $
052 * @since
053 * 2002-12-24
054 * @author
055 * <a href="https://www.croftsoft.com/">David Wallace Croft</a>
056 *********************************************************************/
057
058 public final class LifecycleWindowListener
059 implements WindowListener
060 //////////////////////////////////////////////////////////////////////
061 //////////////////////////////////////////////////////////////////////
062 {
063
064 private final Lifecycle [ ] lifecycles;
065
066 private final String shutdownConfirmationPrompt;
067
068 private final String shutdownConfirmationTitle;
069
070 //
071
072 private boolean initialized;
073
074 //////////////////////////////////////////////////////////////////////
075 // Static methods
076 //////////////////////////////////////////////////////////////////////
077
078 /*********************************************************************
079 * Test and demonstration method.
080 *********************************************************************/
081 public static void main ( String [ ] args )
082 //////////////////////////////////////////////////////////////////////
083 {
084 launchFrameAsDesktopApp (
085 new JFrame ( "Test" ),
086 new Lifecycle [ ] {
087 new Lifecycle ( )
088 {
089 public void init ( ) { System.out.println ( "init" ); }
090 public void start ( ) { System.out.println ( "start" ); }
091 public void stop ( ) { System.out.println ( "stop" ); }
092 public void destroy ( ) { System.out.println ( "destroy" ); }
093 } },
094 null, // frameSize
095 "Exit Test?" );
096 }
097
098 /*********************************************************************
099 * Associates a LifecycleWindowListener with the JFrame and launches.
100 *
101 * <p>
102 * In order to create a flexible JFrame subclass that can be run either
103 * as a stand-alone desktop application by itself or as a pop-up frame
104 * called from a currently running program, you will need to maintain
105 * the logic for handling these different modes of operation outside of
106 * the subclass itself. This method provides the logic for running a
107 * JFrame subclass as an independent desktop application.
108 * </p>
109 *
110 * <p>
111 * This method associates a LifecycleWindowAdapter with the JFrame which
112 * will call the lifecycle methods in response to windowing events.
113 * It then launches the JFrame on the center of the screen.
114 * </p>
115 *
116 * @see
117 * Lifecycle
118 *
119 * @param lifecycles
120 *
121 * An optional array of Lifecycle objects to initialized upon
122 * startup, started upon window activation, stopped upon window
123 * deactivation, and destroyed upon shutdown. May be null.
124 *
125 * @param frameSize
126 *
127 * If null, a default value will be used based upon screen size.
128 *
129 * @param shutdownConfirmationPrompt
130 *
131 * If null, no confirmation prompt will be given.
132 *********************************************************************/
133 public static void launchFrameAsDesktopApp (
134 JFrame jFrame,
135 final Lifecycle [ ] lifecycles,
136 Dimension frameSize,
137 String shutdownConfirmationPrompt )
138 //////////////////////////////////////////////////////////////////////
139 {
140 NullArgumentException.check ( jFrame );
141
142 jFrame.setDefaultCloseOperation (
143 WindowConstants.DO_NOTHING_ON_CLOSE );
144
145 jFrame.addWindowListener ( new LifecycleWindowListener (
146 lifecycles, shutdownConfirmationPrompt ) );
147
148 if ( frameSize != null )
149 {
150 WindowLib.centerOnScreen ( jFrame, frameSize );
151 }
152 else
153 {
154 WindowLib.centerOnScreen ( jFrame, 0.8 );
155 }
156
157 jFrame.setVisible ( true );
158 }
159
160 public static void launchFrameAsDesktopApp (
161 final JFrame jFrame,
162 final Lifecycle lifecycle,
163 final Dimension frameSize,
164 final String shutdownConfirmationPrompt )
165 //////////////////////////////////////////////////////////////////////
166 {
167 launchFrameAsDesktopApp (
168 jFrame,
169 new Lifecycle [ ] { lifecycle },
170 frameSize,
171 shutdownConfirmationPrompt );
172 }
173
174 public static void launchAppletAsDesktopApp (
175 JApplet applet,
176 String frameTitle,
177 String frameIconFilename,
178 ClassLoader classLoader,
179 boolean useFullScreenToggler,
180 Dimension frameSize,
181 String shutdownConfirmationPrompt )
182 //////////////////////////////////////////////////////////////////////
183 {
184 NullArgumentException.check ( applet );
185
186 if ( frameTitle == null )
187 {
188 frameTitle = "";
189 }
190
191 JFrame jFrame = new JFrame ( frameTitle );
192
193 if ( frameIconFilename != null )
194 {
195 try
196 {
197 jFrame.setIconImage ( ImageLib.loadBufferedImage (
198 frameIconFilename, classLoader ) );
199 }
200 catch ( Exception ex )
201 {
202 }
203 }
204
205 jFrame.setContentPane ( applet );
206
207 if ( useFullScreenToggler )
208 {
209 FullScreenToggler.monitor ( jFrame );
210 }
211
212 LifecycleWindowListener.launchFrameAsDesktopApp (
213 jFrame,
214 new Lifecycle [ ] { new AppletLifecycle ( applet ) },
215 frameSize,
216 shutdownConfirmationPrompt );
217 }
218
219 //////////////////////////////////////////////////////////////////////
220 // constructor methods
221 //////////////////////////////////////////////////////////////////////
222
223 /*********************************************************************
224 * Main constructor.
225 *
226 * @param lifecycles
227 * May be null.
228 * @param shutdownConfirmationPrompt
229 * If null, no shutdown confirmation prompt dialog will be given.
230 * @param shutdownConfirmationTitle
231 * If null, the shutdownConfirmationPrompt value will be used.
232 *********************************************************************/
233 public LifecycleWindowListener (
234 Lifecycle [ ] lifecycles,
235 String shutdownConfirmationPrompt,
236 String shutdownConfirmationTitle )
237 //////////////////////////////////////////////////////////////////////
238 {
239 this.lifecycles = lifecycles;
240
241 this.shutdownConfirmationPrompt = shutdownConfirmationPrompt;
242
243 this.shutdownConfirmationTitle = shutdownConfirmationTitle;
244 }
245
246 /*********************************************************************
247 * Convenience constructor.
248 *
249 * <code>
250 * <pre>
251 * this ( lifecycles, shutdownConfirmationPrompt, null );
252 * </pre>
253 * </code>
254 *********************************************************************/
255 public LifecycleWindowListener (
256 Lifecycle [ ] lifecycles,
257 String shutdownConfirmationPrompt )
258 //////////////////////////////////////////////////////////////////////
259 {
260 this ( lifecycles, shutdownConfirmationPrompt, null );
261 }
262
263 /*********************************************************************
264 * Convenience constructor.
265 *
266 * <code>
267 * <pre>
268 * this (
269 * new Lifecycle [ ] { lifecycle },
270 * shutdownConfirmationPrompt );
271 * </pre>
272 * </code>
273 *********************************************************************/
274 public LifecycleWindowListener (
275 Lifecycle lifecycle,
276 String shutdownConfirmationPrompt )
277 //////////////////////////////////////////////////////////////////////
278 {
279 this (
280 new Lifecycle [ ] { lifecycle },
281 shutdownConfirmationPrompt );
282 }
283
284 /*********************************************************************
285 * Convenience constructor.
286 *
287 * <code>
288 * <pre>
289 * this ( lifecycles, null );
290 * </pre>
291 * </code>
292 *********************************************************************/
293 public LifecycleWindowListener ( Lifecycle [ ] lifecycles )
294 //////////////////////////////////////////////////////////////////////
295 {
296 this ( lifecycles, null );
297 }
298
299 /*********************************************************************
300 * Convenience constructor.
301 *
302 * <code>
303 * <pre>
304 * this ( new Lifecycle [ ] { lifecycle } );
305 * </pre>
306 * </code>
307 *********************************************************************/
308 public LifecycleWindowListener ( Lifecycle lifecycle )
309 //////////////////////////////////////////////////////////////////////
310 {
311 this ( new Lifecycle [ ] { lifecycle } );
312 }
313
314 //////////////////////////////////////////////////////////////////////
315 //////////////////////////////////////////////////////////////////////
316
317 public void windowActivated ( WindowEvent windowEvent )
318 //////////////////////////////////////////////////////////////////////
319 {
320 if ( !initialized )
321 {
322 LifecycleLib.init ( lifecycles );
323
324 initialized = true;
325 }
326
327 LifecycleLib.start ( lifecycles );
328 }
329
330 public void windowClosed ( WindowEvent windowEvent )
331 //////////////////////////////////////////////////////////////////////
332 {
333 }
334
335 public void windowClosing ( WindowEvent windowEvent )
336 //////////////////////////////////////////////////////////////////////
337 {
338 Window window = windowEvent.getWindow ( );
339
340 if ( shutdownConfirmationPrompt != null )
341 {
342 int confirm = JOptionPane.showOptionDialog ( window,
343 shutdownConfirmationPrompt,
344 shutdownConfirmationTitle != null
345 ? shutdownConfirmationTitle : shutdownConfirmationPrompt,
346 JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
347 null, null, null );
348
349 if ( confirm != JOptionPane.YES_OPTION )
350 {
351 return;
352 }
353 }
354
355 window.setVisible ( false );
356
357 if ( shutdownConfirmationPrompt == null )
358 {
359 LifecycleLib.stop ( lifecycles );
360 }
361
362 LifecycleLib.destroy ( lifecycles );
363
364 window.dispose ( );
365
366 System.exit ( 0 );
367 }
368
369 public void windowDeactivated ( WindowEvent windowEvent )
370 //////////////////////////////////////////////////////////////////////
371 {
372 LifecycleLib.stop ( lifecycles );
373 }
374
375 public void windowDeiconified ( WindowEvent windowEvent )
376 //////////////////////////////////////////////////////////////////////
377 {
378 }
379
380 public void windowIconified ( WindowEvent windowEvent )
381 //////////////////////////////////////////////////////////////////////
382 {
383 }
384
385 public void windowOpened ( WindowEvent windowEvent )
386 //////////////////////////////////////////////////////////////////////
387 {
388 }
389
390 //////////////////////////////////////////////////////////////////////
391 //////////////////////////////////////////////////////////////////////
392 }