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 }