001    /* JDialog.java --
002       Copyright (C) 2002, 2004 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing;
040    
041    import java.awt.AWTEvent;
042    import java.awt.Component;
043    import java.awt.Container;
044    import java.awt.Dialog;
045    import java.awt.Dimension;
046    import java.awt.Frame;
047    import java.awt.Graphics;
048    import java.awt.GraphicsConfiguration;
049    import java.awt.IllegalComponentStateException;
050    import java.awt.LayoutManager;
051    import java.awt.event.WindowEvent;
052    
053    import javax.accessibility.Accessible;
054    import javax.accessibility.AccessibleContext;
055    
056    /**
057     * A dialog window. This is an extension of {@link java.awt.Dialog} that
058     * provides support for the Swing architecture. Most importantly it contains a
059     * {@link JRootPane} as it's only top-level child, that manages the content
060     * pane, the menu and a glass pane.
061     *
062     * Also, unlike <code>java.awt.Dialog</code>s, JDialogs support the
063     * Swing Pluggable Look &amp; Feel architecture.
064     *
065     * @author Ronald Veldema (rveldema@cs.vu.nl)
066     */
067    public class JDialog extends Dialog implements Accessible, WindowConstants,
068                                                   RootPaneContainer
069    {
070      /**
071       * Provides accessibility support for <code>JDialog</code>s.
072       */
073      protected class AccessibleJDialog extends Dialog.AccessibleAWTDialog
074      {
075        /**
076         * Creates a new instance of <code>AccessibleJDialog</code>.
077         */
078        protected AccessibleJDialog()
079        {
080          super();
081          // Nothing to do here.
082        }
083      }
084    
085      private static final long serialVersionUID = -864070866424508218L;
086    
087      /** DOCUMENT ME! */
088      protected AccessibleContext accessibleContext;
089    
090      /** The single RootPane in the Dialog. */
091      protected JRootPane rootPane;
092    
093      /**
094       * Whether checking is enabled on the RootPane.
095       *
096       * @specnote Should be false to comply with J2SE 5.0
097       */
098      protected boolean rootPaneCheckingEnabled = false;
099    
100      /** The default action taken when closed. */
101      private int closeAction = HIDE_ON_CLOSE;
102    
103      /** Whether JDialogs are decorated by the Look and Feel. */
104      private static boolean decorated;
105    
106      /* Creates a new non-modal JDialog with no title
107       * using a shared Frame as the owner.
108       */
109      public JDialog()
110      {
111        this((Frame) SwingUtilities.getOwnerFrame(null), "", false, null);
112      }
113    
114      /**
115       * Creates a new non-modal JDialog with no title
116       * using the given owner.
117       *
118       * @param owner The owner of the JDialog.
119       */
120      public JDialog(Dialog owner)
121      {
122        this(owner, "", false, null);
123      }
124    
125      /**
126       * Creates a new JDialog with no title using the
127       * given modal setting and owner.
128       *
129       * @param owner The owner of the JDialog.
130       * @param modal Whether the JDialog is modal.
131       */
132      public JDialog(Dialog owner, boolean modal)
133      {
134        this(owner, "", modal, null);
135      }
136    
137      /**
138       * Creates a new non-modal JDialog using the
139       * given title and owner.
140       *
141       * @param owner The owner of the JDialog.
142       * @param title The title of the JDialog.
143       */
144      public JDialog(Dialog owner, String title)
145      {
146        this(owner, title, false, null);
147      }
148    
149      /**
150       * Creates a new JDialog using the given modal
151       * settings, title, and owner.
152       *
153       * @param owner The owner of the JDialog.
154       * @param title The title of the JDialog.
155       * @param modal Whether the JDialog is modal.
156       */
157      public JDialog(Dialog owner, String title, boolean modal)
158      {
159        this(owner, title, modal, null);
160      }
161    
162      /**
163       * Creates a new JDialog using the given modal
164       * settings, title, owner and graphics configuration.
165       *
166       * @param owner The owner of the JDialog.
167       * @param title The title of the JDialog.
168       * @param modal Whether the JDialog is modal.
169       * @param gc The Graphics Configuration to use.
170       */
171      public JDialog(Dialog owner, String title, boolean modal,
172                     GraphicsConfiguration gc)
173      {
174        super(owner, title, modal, gc);
175        dialogInit();
176      }
177    
178      /**
179       * Creates a new non-modal JDialog with no title
180       * using the given owner.
181       *
182       * @param owner The owner of the JDialog.
183       */
184      public JDialog(Frame owner)
185      {
186        this(owner, "", false, null);
187      }
188    
189      /**
190       * Creates a new JDialog with no title using the
191       * given modal setting and owner.
192       *
193       * @param owner The owner of the JDialog.
194       * @param modal Whether the JDialog is modal.
195       */
196      public JDialog(Frame owner, boolean modal)
197      {
198        this(owner, "", modal, null);
199      }
200    
201      /**
202       * Creates a new non-modal JDialog using the
203       * given title and owner.
204       *
205       * @param owner The owner of the JDialog.
206       * @param title The title of the JDialog.
207       */
208      public JDialog(Frame owner, String title)
209      {
210        this(owner, title, false, null);
211      }
212    
213      /**
214       * Creates a new JDialog using the given modal
215       * settings, title, and owner.
216       *
217       * @param owner The owner of the JDialog.
218       * @param title The title of the JDialog.
219       * @param modal Whether the JDialog is modal.
220       */
221      public JDialog(Frame owner, String title, boolean modal)
222      {
223        this(owner, title, modal, null);
224      }
225    
226      /**
227       * Creates a new JDialog using the given modal
228       * settings, title, owner and graphics configuration.
229       *
230       * @param owner The owner of the JDialog.
231       * @param title The title of the JDialog.
232       * @param modal Whether the JDialog is modal.
233       * @param gc The Graphics Configuration to use.
234       */
235      public JDialog(Frame owner, String title, boolean modal,
236                     GraphicsConfiguration gc)
237      {
238        super((Frame) SwingUtilities.getOwnerFrame(owner), title, modal, gc);
239        dialogInit();
240      }
241    
242      /**
243       * This method is called to initialize the
244       * JDialog. It sets the layout used, the locale,
245       * and creates the RootPane.
246       */
247      protected void dialogInit()
248      {
249        // We need to explicitly enable events here so that our processKeyEvent()
250        // and processWindowEvent() gets called.
251        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
252    
253        // FIXME: Do a check on GraphicsEnvironment.isHeadless()
254        setLocale(JComponent.getDefaultLocale());
255        getRootPane(); // Will do set/create.
256        invalidate();
257        // Now that initStageDone is true, adds and layouts apply to contentPane,
258        // not top-level.
259        setRootPaneCheckingEnabled(true);
260      }
261    
262      /**
263       * This method returns whether JDialogs will have their
264       * window decorations provided by the Look and Feel.
265       *
266       * @return Whether the window decorations are Look and Feel provided.
267       */
268      public static boolean isDefaultLookAndFeelDecorated()
269      {
270        return decorated;
271      }
272    
273      /**
274       * This method sets whether JDialogs will have their
275       * window decorations provided by the Look and Feel.
276       *
277       * @param defaultLookAndFeelDecorated Whether the window
278       * decorations are Look and Feel provided.
279       */
280      public static void setDefaultLookAndFeelDecorated(boolean defaultLookAndFeelDecorated)
281      {
282        decorated = defaultLookAndFeelDecorated;
283      }
284    
285      /**
286       * This method returns the preferred size of
287       * the JDialog.
288       *
289       * @return The preferred size.
290       */
291      public Dimension getPreferredSize()
292      {
293        Dimension d = super.getPreferredSize();
294        return d;
295      }
296    
297      /**
298       * This method returns the JMenuBar used
299       * in this JDialog.
300       *
301       * @return The JMenuBar in the JDialog.
302       */
303      public JMenuBar getJMenuBar()
304      {
305        return getRootPane().getJMenuBar();
306      }
307    
308      /**
309       * This method sets the JMenuBar used
310       * in this JDialog.
311       *
312       * @param menubar The JMenuBar to use.
313       */
314      public void setJMenuBar(JMenuBar menubar)
315      {
316        getRootPane().setJMenuBar(menubar);
317      }
318    
319      /**
320       * This method sets the LayoutManager used in the JDialog.
321       * This method will throw an Error if rootPaneChecking is
322       * enabled.
323       *
324       * @param manager The LayoutManager to use.
325       */
326      public void setLayout(LayoutManager manager)
327      {
328        // Check if we're in initialization stage. If so, call super.setLayout
329        // otherwise, valid calls go to the content pane.
330        if (isRootPaneCheckingEnabled())
331          getContentPane().setLayout(manager);
332        else
333          super.setLayout(manager);
334      }
335    
336      /**
337       * This method sets the JLayeredPane used in the JDialog.
338       * If the given JLayeredPane is null, then this method
339       * will throw an Error.
340       *
341       * @param layeredPane The JLayeredPane to use.
342       */
343      public void setLayeredPane(JLayeredPane layeredPane)
344      {
345        if (layeredPane == null)
346          throw new IllegalComponentStateException("layeredPane cannot be null.");
347        getRootPane().setLayeredPane(layeredPane);
348      }
349    
350      /**
351       * This method returns the JLayeredPane used with this JDialog.
352       *
353       * @return The JLayeredPane used with this JDialog.
354       */
355      public JLayeredPane getLayeredPane()
356      {
357        return getRootPane().getLayeredPane();
358      }
359    
360      /**
361       * This method returns the JRootPane used with this JDialog.
362       *
363       * @return The JRootPane used with this JDialog.
364       */
365      public JRootPane getRootPane()
366      {
367        if (rootPane == null)
368          setRootPane(createRootPane());
369        return rootPane;
370      }
371    
372      /**
373       * This method sets the JRootPane used with this JDialog.
374       *
375       * @param root The JRootPane to use.
376       */
377      protected void setRootPane(JRootPane root)
378      {
379        if (rootPane != null)
380          remove(rootPane);
381    
382        rootPane = root;
383        rootPane.show();
384        add(rootPane);
385      }
386    
387      /**
388       * This method creates a new JRootPane.
389       *
390       * @return A new JRootPane.
391       */
392      protected JRootPane createRootPane()
393      {
394        return new JRootPane();
395      }
396    
397      /**
398       * This method returns the ContentPane
399       * in the JRootPane.
400       *
401       * @return The ContentPane in the JRootPane.
402       */
403      public Container getContentPane()
404      {
405        return getRootPane().getContentPane();
406      }
407    
408      /**
409       * This method sets the ContentPane to use with this
410       * JDialog. If the ContentPane given is null, this method
411       * will throw an exception.
412       *
413       * @param contentPane The ContentPane to use with the JDialog.
414       */
415      public void setContentPane(Container contentPane)
416      {
417        if (contentPane == null)
418          throw new IllegalComponentStateException("contentPane cannot be null.");
419        getRootPane().setContentPane(contentPane);
420      }
421    
422      /**
423       * This method returns the GlassPane for this JDialog.
424       *
425       * @return The GlassPane for this JDialog.
426       */
427      public Component getGlassPane()
428      {
429        return getRootPane().getGlassPane();
430      }
431    
432      /**
433       * This method sets the GlassPane for this JDialog.
434       *
435       * @param glassPane The GlassPane for this JDialog.
436       */
437      public void setGlassPane(Component glassPane)
438      {
439        getRootPane().setGlassPane(glassPane);
440      }
441    
442      /**
443       * This method is called when a component is added to the
444       * the JDialog. Calling this method with rootPaneCheckingEnabled
445       * will cause an Error to be thrown.
446       *
447       * @param comp The component to add.
448       * @param constraints The constraints.
449       * @param index The position of the component.
450       */
451      protected void addImpl(Component comp, Object constraints, int index)
452      {
453        // If we're adding in the initialization stage use super.add.
454        // Otherwise pass the add onto the content pane.
455        if (isRootPaneCheckingEnabled())
456          getContentPane().add(comp, constraints, index);
457        else
458          super.addImpl(comp, constraints, index);
459      }
460    
461      /**
462       * This method removes a component from the JDialog.
463       *
464       * @param comp The component to remove.
465       */
466      public void remove(Component comp)
467      {
468        // If we're removing the root pane, use super.remove. Otherwise
469        // pass it on to the content pane instead.
470        if (comp == rootPane)
471          super.remove(rootPane);
472        else
473          getContentPane().remove(comp);
474      }
475    
476      /**
477       * This method returns whether rootPane checking is enabled.
478       *
479       * @return Whether rootPane checking is enabled.
480       */
481      protected boolean isRootPaneCheckingEnabled()
482      {
483        return rootPaneCheckingEnabled;
484      }
485    
486      /**
487       * This method sets whether rootPane checking is enabled.
488       *
489       * @param enabled Whether rootPane checking is enabled.
490       */
491      protected void setRootPaneCheckingEnabled(boolean enabled)
492      {
493        rootPaneCheckingEnabled = enabled;
494      }
495    
496      /**
497       * This method simply calls paint and returns.
498       *
499       * @param g The Graphics object to paint with.
500       */
501      public void update(Graphics g)
502      {
503        paint(g);
504      }
505    
506    
507      /**
508       * This method handles window events. This allows the JDialog
509       * to honour its default close operation.
510       *
511       * @param e The WindowEvent.
512       */
513      protected void processWindowEvent(WindowEvent e)
514      {
515        super.processWindowEvent(e);
516        if (e.getID() == WindowEvent.WINDOW_CLOSING)
517          {
518            switch (closeAction)
519              {
520              case EXIT_ON_CLOSE:
521                System.exit(0);
522                break;
523              case DISPOSE_ON_CLOSE:
524                dispose();
525                break;
526              case HIDE_ON_CLOSE:
527                setVisible(false);
528                break;
529              case DO_NOTHING_ON_CLOSE:
530                break;
531              }
532          }
533      }
534    
535      /**
536       * This method sets the action to take
537       * when the JDialog is closed.
538       *
539       * @param operation The action to take.
540       */
541      public void setDefaultCloseOperation(int operation)
542      {
543        /* Reference implementation allows invalid operations
544           to be specified.  If so, getDefaultCloseOperation
545           must return the invalid code, and the behaviour
546           defaults to DO_NOTHING_ON_CLOSE.  processWindowEvent
547           above handles this */
548        closeAction = operation;
549      }
550    
551      /**
552       * This method returns the action taken when
553       * the JDialog is closed.
554       *
555       * @return The action to take.
556       */
557      public int getDefaultCloseOperation()
558      {
559        return closeAction;
560      }
561    
562      /**
563       * This method returns a String describing the JDialog.
564       *
565       * @return A String describing the JDialog.
566       */
567      protected String paramString()
568      {
569        return "JDialog";
570      }
571    
572      /**
573       * DOCUMENT ME!
574       *
575       * @return DOCUMENT ME!
576       */
577      public AccessibleContext getAccessibleContext()
578      {
579        if (accessibleContext == null)
580          accessibleContext = new AccessibleJDialog();
581        return accessibleContext;
582      }
583    }