001         package com.croftsoft.core.gui;
002    
003         import java.awt.*;
004         import java.awt.event.*;
005         import javax.swing.JOptionPane;
006    
007         import com.croftsoft.core.lang.lifecycle.Destroyable;
008    
009         /*********************************************************************
010         * Performs a graceful shutdown of a program when the window is closed.
011         *
012         * <p>
013         * <ol>
014         * <li> Prompts for shutdown confirmation.
015         * <li> Calls the window hide() method.
016         * <li> Calls the destroy() method, in array order, of each of the
017         *      Destroyable instances passed via the constructor argument.
018         *      Any exceptions are caught, printed, and ignored.
019         * <li> Calls the window dispose() method.
020         * <li> Calls System.exit(0).
021         * </ol>
022         * </p>
023         *
024         * <p>
025         * Example:
026         * <code>
027         * <pre>
028         * jFrame.setDefaultCloseOperation (
029         *   javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE );
030         *
031         * jFrame.addWindowListener (
032         *   new ShutdownWindowAdapter ( this, "Exit Program?" ) );
033         * </pre>
034         * </code>
035         * </p>
036         *
037         * @version
038         *   $Date: 2006/01/13 18:47:08 $
039         * @version
040         *   2001-03-06
041         * @author
042         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
043         *********************************************************************/
044    
045         public class  ShutdownWindowAdapter
046           extends WindowAdapter
047         //////////////////////////////////////////////////////////////////////
048         //////////////////////////////////////////////////////////////////////
049         {
050    
051         private final Destroyable [ ]  destroyables;
052    
053         private final String           shutdownConfirmationPrompt;
054    
055         private final String           shutdownConfirmationTitle;
056    
057         //////////////////////////////////////////////////////////////////////
058         //////////////////////////////////////////////////////////////////////
059    
060         /*********************************************************************
061         * Main constructor.
062         *
063         * @param  destroyables
064         *   May be null.
065         * @param  shutdownConfirmationPrompt
066         *   If null, no shutdown confirmation prompt dialog will be given.
067         * @param  shutdownConfirmationTitle
068         *   If null, the shutdownConfirmationPrompt value will be used.
069         *********************************************************************/
070         public  ShutdownWindowAdapter (
071           Destroyable [ ]  destroyables,
072           String           shutdownConfirmationPrompt,
073           String           shutdownConfirmationTitle )
074         //////////////////////////////////////////////////////////////////////
075         {
076           this.destroyables               = destroyables;
077    
078           this.shutdownConfirmationPrompt = shutdownConfirmationPrompt;
079    
080           this.shutdownConfirmationTitle  = shutdownConfirmationTitle;
081         }
082    
083         /*********************************************************************
084         * Convenience constructor.
085         *
086         * <code>
087         * <pre>
088         * this ( destroyables, shutdownConfirmationPrompt, null );
089         * </pre>
090         * </code>
091         *********************************************************************/
092         public  ShutdownWindowAdapter (
093           Destroyable [ ]  destroyables,
094           String           shutdownConfirmationPrompt )
095         //////////////////////////////////////////////////////////////////////
096         {
097           this ( destroyables, shutdownConfirmationPrompt, null );
098         }
099    
100         /*********************************************************************
101         * Convenience constructor.
102         *
103         * <code>
104         * <pre>
105         * this (
106         *   new Destroyable [ ] { destroyable },
107         *   shutdownConfirmationPrompt );
108         * </pre>
109         * </code>
110         *********************************************************************/
111         public  ShutdownWindowAdapter (
112           Destroyable  destroyable,
113           String       shutdownConfirmationPrompt )
114         //////////////////////////////////////////////////////////////////////
115         {
116           this (
117             new Destroyable [ ] { destroyable },
118             shutdownConfirmationPrompt );
119         }
120    
121         /*********************************************************************
122         * Convenience constructor.
123         *
124         * <code>
125         * <pre>
126         * this ( destroyables, null );
127         * </pre>
128         * </code>
129         *********************************************************************/
130         public  ShutdownWindowAdapter ( Destroyable [ ]  destroyables )
131         //////////////////////////////////////////////////////////////////////
132         {
133           this ( destroyables, null );
134         }
135    
136         /*********************************************************************
137         * Convenience constructor.
138         *
139         * <code>
140         * <pre>
141         * this ( new Destroyable [ ] { destroyable } );
142         * </pre>
143         * </code>
144         *********************************************************************/
145         public  ShutdownWindowAdapter ( Destroyable  destroyable )
146         //////////////////////////////////////////////////////////////////////
147         {
148           this ( new Destroyable [ ] { destroyable } );
149         }
150    
151         public  ShutdownWindowAdapter ( )
152         //////////////////////////////////////////////////////////////////////
153         {
154           this ( ( Destroyable [ ] ) null );
155         }
156    
157         //////////////////////////////////////////////////////////////////////
158         //////////////////////////////////////////////////////////////////////
159    
160         public void  windowClosing ( WindowEvent  windowEvent )
161         //////////////////////////////////////////////////////////////////////
162         {
163           Window  window = windowEvent.getWindow ( );
164    
165           if ( shutdownConfirmationPrompt != null )
166           {
167             int  confirm = JOptionPane.showOptionDialog ( window,
168               shutdownConfirmationPrompt, 
169               shutdownConfirmationTitle != null
170                 ? shutdownConfirmationTitle : shutdownConfirmationPrompt,
171               JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
172               null, null, null );
173    
174             if ( confirm != JOptionPane.YES_OPTION )
175             {
176               return;
177             }
178           }
179    
180           window.setVisible ( false );
181    
182           if ( destroyables != null )
183           {
184             for ( int  i = 0; i < destroyables.length; i++ )
185             {
186               Destroyable  destroyable = destroyables [ i ];
187    
188               if ( destroyable != null )
189               {
190                 try
191                 {
192                   destroyable.destroy ( );
193                 }
194                 catch ( Exception  ex )
195                 {
196                   ex.printStackTrace ( );
197                 }
198               }
199             }
200           }
201    
202           window.dispose ( );
203    
204           System.exit ( 0 );
205         }
206    
207         //////////////////////////////////////////////////////////////////////
208         //////////////////////////////////////////////////////////////////////
209         }