1   // Copyright (C) 2000, 2001, 2002, 2003 Philip Aston
2   // All rights reserved.
3   //
4   // This file is part of The Grinder software distribution. Refer to
5   // the file LICENSE which is part of The Grinder distribution for
6   // licensing details. The Grinder distribution is available on the
7   // Internet at http://grinder.sourceforge.net/
8   //
9   // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12  // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
13  // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
14  // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15  // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17  // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
18  // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
20  // OF THE POSSIBILITY OF SUCH DAMAGE.
21  
22  package net.grinder.console.swingui;
23  
24  import java.awt.BorderLayout;
25  import java.awt.Container;
26  import java.awt.Cursor;
27  import java.awt.event.WindowAdapter;
28  import java.awt.event.WindowEvent;
29  import java.beans.PropertyChangeEvent;
30  import java.beans.PropertyChangeListener;
31  import javax.swing.JDialog;
32  import javax.swing.JFrame;
33  import javax.swing.JOptionPane;
34  
35  
36  /**
37   * <code>JDialog</code> that is more useful than that returned by
38   * <code>JOptionPane.createDialog()</code>.
39   *
40   * @author Philip Aston
41   */
42  public class JOptionPaneDialog extends JDialog {
43  
44    /**
45     * Constructor.
46     *
47     * @param frame Parent frame.
48     * @param title The title.
49     * @param modal <code>true</code> => dialog should be modal.
50     * @param optionPane JOptionPane to wrap.
51     */
52    public JOptionPaneDialog(JFrame frame, String title, boolean modal,
53                             JOptionPane optionPane) {
54  
55      super(frame, title, modal);
56      setOptionPane(optionPane);
57    }
58  
59    /**
60     * Constructor.
61     *
62     * @param dialog Parent dialog.
63     * @param title The title.
64     * @param modal <code>true</code> => dialog should be modal.
65     * @param optionPane JOptionPane to wrap.
66     */
67    public JOptionPaneDialog(JDialog dialog, String title, boolean modal,
68                             JOptionPane optionPane) {
69  
70      super(dialog, title, modal);
71      setOptionPane(optionPane);
72    }
73  
74    /**
75     * Common initialistion. We need separate constructors because
76     * JDialog does not allow us to treat parentComponent
77     * polymorphically.
78     *
79     * @param optionPane JOptionPane to wrap.
80     */
81    private void setOptionPane(final JOptionPane optionPane) {
82  
83      setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
84  
85      final Container contentPane = getContentPane();
86      contentPane.setLayout(new BorderLayout());
87      contentPane.add(optionPane, BorderLayout.CENTER);
88      pack();
89      setLocationRelativeTo(getOwner());
90  
91      addWindowListener(
92        new WindowAdapter() {
93          private boolean m_gotFocus = false;
94  
95          public void windowClosing(WindowEvent e) {
96            optionPane.setValue(null);
97          }
98  
99          public void windowActivated(WindowEvent e) {
100           // Once window gets focus, set initial focus
101           if (!m_gotFocus) {
102             optionPane.selectInitialValue();
103             m_gotFocus = true;
104           }
105         }
106       });
107 
108     optionPane.addPropertyChangeListener(
109       new PropertyChangeListener() {
110 
111         private boolean m_disable = false;
112 
113         public void propertyChange(PropertyChangeEvent e) {
114           if (isVisible() &&
115               e.getSource() == optionPane &&
116               !m_disable &&
117               (e.getPropertyName().equals(JOptionPane.VALUE_PROPERTY) ||
118                e.getPropertyName().equals(JOptionPane.INPUT_VALUE_PROPERTY))) {
119 
120             final Cursor oldCursor = getCursor();
121             setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
122 
123             try {
124               if (shouldClose()) {
125                 setVisible(false);
126                 dispose();
127               }
128             }
129             finally {
130               m_disable = true;
131               optionPane.setValue(null);
132               m_disable = false;
133               setCursor(oldCursor);
134             }
135           }
136         }
137       });
138 
139     optionPane.setValue(null);
140   }
141 
142   /**
143    * Whether dialog should be closed on a property change.
144    *
145    * @return <code>true</code> => it should.
146    */
147   protected boolean shouldClose() {
148     return true;
149   }
150 }