1 /*
2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package javax.swing;
27 
28 import java.awt.*;
29 
30 import java.beans.*;
31 
32 import javax.swing.event.InternalFrameEvent;
33 import javax.swing.event.InternalFrameListener;
34 import javax.swing.plaf.*;
35 
36 import javax.accessibility.*;
37 
38 import java.io.ObjectOutputStream;
39 import java.io.IOException;
40 
41 import sun.awt.AppContext;
42 import sun.swing.SwingUtilities2;
43 
44 
45 /**
46  * A lightweight object that provides many of the features of
47  * a native frame, including dragging, closing, becoming an icon,
48  * resizing, title display, and support for a menu bar.
49  * For task-oriented documentation and examples of using internal frames,
50  * see <a
51  href="https://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html" target="_top">How to Use Internal Frames</a>,
52  * a section in <em>The Java Tutorial</em>.
53  *
54  * <p>
55  *
56  * Generally,
57  * you add <code>JInternalFrame</code>s to a <code>JDesktopPane</code>. The UI
58  * delegates the look-and-feel-specific actions to the
59  * <code>DesktopManager</code>
60  * object maintained by the <code>JDesktopPane</code>.
61  * <p>
62  * The <code>JInternalFrame</code> content pane
63  * is where you add child components.
64  * As a convenience, the {@code add}, {@code remove}, and {@code setLayout}
65  * methods of this class are overridden, so that they delegate calls
66  * to the corresponding methods of the {@code ContentPane}.
67  * For example, you can add a child component to an internal frame as follows:
68  * <pre>
69  *       internalFrame.add(child);
70  * </pre>
71  * And the child will be added to the contentPane.
72  * The content pane is actually managed by an instance of
73  * <code>JRootPane</code>,
74  * which also manages a layout pane, glass pane, and
75  * optional menu bar for the internal frame. Please see the
76  * <code>JRootPane</code>
77  * documentation for a complete description of these components.
78  * Refer to {@link javax.swing.RootPaneContainer}
79  * for details on adding, removing and setting the <code>LayoutManager</code>
80  * of a <code>JInternalFrame</code>.
81  * <p>
82  * <strong>Warning:</strong> Swing is not thread safe. For more
83  * information see <a
84  * href="package-summary.html#threading">Swing's Threading
85  * Policy</a>.
86  * <p>
87  * <strong>Warning:</strong>
88  * Serialized objects of this class will not be compatible with
89  * future Swing releases. The current serialization support is
90  * appropriate for short term storage or RMI between applications running
91  * the same version of Swing.  As of 1.4, support for long term storage
92  * of all JavaBeans&trade;
93  * has been added to the <code>java.beans</code> package.
94  * Please see {@link java.beans.XMLEncoder}.
95  *
96  * @see InternalFrameEvent
97  * @see JDesktopPane
98  * @see DesktopManager
99  * @see JInternalFrame.JDesktopIcon
100  * @see JRootPane
101  * @see javax.swing.RootPaneContainer
102  *
103  * @author David Kloba
104  * @author Rich Schiavi
105  * @since 1.2
106  */
107 @JavaBean(defaultProperty = "JMenuBar", description = "A frame container which is contained within another window.")
108 @SwingContainer(delegate = "getContentPane")
109 @SuppressWarnings("serial") // Same-version serialization only
110 public class JInternalFrame extends JComponent implements
111         Accessible, WindowConstants,
112         RootPaneContainer
113 {
114     /**
115      * @see #getUIClassID
116      * @see #readObject
117      */
118     private static final String uiClassID = "InternalFrameUI";
119 
120     /**
121      * The <code>JRootPane</code> instance that manages the
122      * content pane
123      * and optional menu bar for this internal frame, as well as the
124      * glass pane.
125      *
126      * @see JRootPane
127      * @see RootPaneContainer
128      */
129     protected JRootPane rootPane;
130 
131     /**
132      * If true then calls to <code>add</code> and <code>setLayout</code>
133      * will be forwarded to the <code>contentPane</code>. This is initially
134      * false, but is set to true when the <code>JInternalFrame</code> is
135      * constructed.
136      *
137      * @see #isRootPaneCheckingEnabled
138      * @see #setRootPaneCheckingEnabled
139      * @see javax.swing.RootPaneContainer
140      */
141     protected boolean rootPaneCheckingEnabled = false;
142 
143     /** The frame can be closed. */
144     protected boolean closable;
145     /** The frame has been closed. */
146     protected boolean isClosed;
147     /** The frame can be expanded to the size of the desktop pane. */
148     protected boolean maximizable;
149     /**
150      * The frame has been expanded to its maximum size.
151      * @see #maximizable
152      */
153     protected boolean isMaximum;
154     /**
155      * The frame can "iconified" (shrunk down and displayed as
156      * an icon-image).
157      * @see JInternalFrame.JDesktopIcon
158      * @see #setIconifiable
159      */
160     protected boolean iconable;
161     /**
162      * The frame has been iconified.
163      * @see #isIcon()
164      */
165     protected boolean isIcon;
166     /** The frame's size can be changed. */
167     protected boolean resizable;
168     /** The frame is currently selected. */
169     protected boolean isSelected;
170     /** The icon shown in the top-left corner of this internal frame. */
171     protected Icon frameIcon;
172     /** The title displayed in this internal frame's title bar. */
173     protected String  title;
174     /**
175      * The icon that is displayed when this internal frame is iconified.
176      * @see #iconable
177      */
178     protected JDesktopIcon desktopIcon;
179 
180     private Cursor lastCursor;
181 
182     private boolean opened;
183 
184     private Rectangle normalBounds = null;
185 
186     private int defaultCloseOperation = DISPOSE_ON_CLOSE;
187 
188     /**
189      * Contains the Component that focus is to go when
190      * <code>restoreSubcomponentFocus</code> is invoked, that is,
191      * <code>restoreSubcomponentFocus</code> sets this to the value returned
192      * from <code>getMostRecentFocusOwner</code>.
193      */
194     private Component lastFocusOwner;
195 
196     /** Bound property name. */
197     public static final String CONTENT_PANE_PROPERTY = "contentPane";
198     /** Bound property name. */
199     public static final String MENU_BAR_PROPERTY = "JMenuBar";
200     /** Bound property name. */
201     public static final String TITLE_PROPERTY = "title";
202     /** Bound property name. */
203     public static final String LAYERED_PANE_PROPERTY = "layeredPane";
204     /** Bound property name. */
205     public static final String ROOT_PANE_PROPERTY = "rootPane";
206     /** Bound property name. */
207     public static final String GLASS_PANE_PROPERTY = "glassPane";
208     /** Bound property name. */
209     public static final String FRAME_ICON_PROPERTY = "frameIcon";
210 
211     /**
212      * Constrained property name indicated that this frame has
213      * selected status.
214      */
215     public static final String IS_SELECTED_PROPERTY = "selected";
216     /** Constrained property name indicating that the internal frame is closed. */
217     public static final String IS_CLOSED_PROPERTY = "closed";
218     /** Constrained property name indicating that the internal frame is maximized. */
219     public static final String IS_MAXIMUM_PROPERTY = "maximum";
220     /** Constrained property name indicating that the internal frame is iconified. */
221     public static final String IS_ICON_PROPERTY = "icon";
222 
223     private static final Object PROPERTY_CHANGE_LISTENER_KEY =
224         new StringBuilder("InternalFramePropertyChangeListener");
225 
addPropertyChangeListenerIfNecessary()226     private static void addPropertyChangeListenerIfNecessary() {
227         if (AppContext.getAppContext().get(PROPERTY_CHANGE_LISTENER_KEY) ==
228             null) {
229             PropertyChangeListener focusListener =
230                 new FocusPropertyChangeListener();
231 
232             AppContext.getAppContext().put(PROPERTY_CHANGE_LISTENER_KEY,
233                 focusListener);
234 
235             KeyboardFocusManager.getCurrentKeyboardFocusManager().
236                 addPropertyChangeListener(focusListener);
237         }
238     }
239 
240     private static class FocusPropertyChangeListener implements
241         PropertyChangeListener {
propertyChange(PropertyChangeEvent e)242         public void propertyChange(PropertyChangeEvent e) {
243             if (e.getPropertyName() == "permanentFocusOwner") {
244                 updateLastFocusOwner((Component)e.getNewValue());
245             }
246         }
247     }
248 
updateLastFocusOwner(Component component)249     private static void updateLastFocusOwner(Component component) {
250         if (component != null) {
251             Component parent = component;
252             while (parent != null && !(parent instanceof Window)) {
253                 if (parent instanceof JInternalFrame) {
254                     // Update lastFocusOwner for parent.
255                     ((JInternalFrame)parent).setLastFocusOwner(component);
256                 }
257                 parent = parent.getParent();
258             }
259         }
260     }
261 
262     /**
263      * Creates a non-resizable, non-closable, non-maximizable,
264      * non-iconifiable <code>JInternalFrame</code> with no title.
265      */
JInternalFrame()266     public JInternalFrame() {
267         this("", false, false, false, false);
268     }
269 
270     /**
271      * Creates a non-resizable, non-closable, non-maximizable,
272      * non-iconifiable <code>JInternalFrame</code> with the specified title.
273      * Note that passing in a <code>null</code> <code>title</code> results in
274      * unspecified behavior and possibly an exception.
275      *
276      * @param title  the non-<code>null</code> <code>String</code>
277      *     to display in the title bar
278      */
JInternalFrame(String title)279     public JInternalFrame(String title) {
280         this(title, false, false, false, false);
281     }
282 
283     /**
284      * Creates a non-closable, non-maximizable, non-iconifiable
285      * <code>JInternalFrame</code> with the specified title
286      * and resizability.
287      *
288      * @param title      the <code>String</code> to display in the title bar
289      * @param resizable  if <code>true</code>, the internal frame can be resized
290      */
JInternalFrame(String title, boolean resizable)291     public JInternalFrame(String title, boolean resizable) {
292         this(title, resizable, false, false, false);
293     }
294 
295     /**
296      * Creates a non-maximizable, non-iconifiable <code>JInternalFrame</code>
297      * with the specified title, resizability, and
298      * closability.
299      *
300      * @param title      the <code>String</code> to display in the title bar
301      * @param resizable  if <code>true</code>, the internal frame can be resized
302      * @param closable   if <code>true</code>, the internal frame can be closed
303      */
JInternalFrame(String title, boolean resizable, boolean closable)304     public JInternalFrame(String title, boolean resizable, boolean closable) {
305         this(title, resizable, closable, false, false);
306     }
307 
308     /**
309      * Creates a non-iconifiable <code>JInternalFrame</code>
310      * with the specified title,
311      * resizability, closability, and maximizability.
312      *
313      * @param title       the <code>String</code> to display in the title bar
314      * @param resizable   if <code>true</code>, the internal frame can be resized
315      * @param closable    if <code>true</code>, the internal frame can be closed
316      * @param maximizable if <code>true</code>, the internal frame can be maximized
317      */
JInternalFrame(String title, boolean resizable, boolean closable, boolean maximizable)318     public JInternalFrame(String title, boolean resizable, boolean closable,
319                           boolean maximizable) {
320         this(title, resizable, closable, maximizable, false);
321     }
322 
323     /**
324      * Creates a <code>JInternalFrame</code> with the specified title,
325      * resizability, closability, maximizability, and iconifiability.
326      * All <code>JInternalFrame</code> constructors use this one.
327      *
328      * @param title       the <code>String</code> to display in the title bar
329      * @param resizable   if <code>true</code>, the internal frame can be resized
330      * @param closable    if <code>true</code>, the internal frame can be closed
331      * @param maximizable if <code>true</code>, the internal frame can be maximized
332      * @param iconifiable if <code>true</code>, the internal frame can be iconified
333      */
JInternalFrame(String title, boolean resizable, boolean closable, boolean maximizable, boolean iconifiable)334     public JInternalFrame(String title, boolean resizable, boolean closable,
335                                 boolean maximizable, boolean iconifiable) {
336 
337         setRootPane(createRootPane());
338         setLayout(new BorderLayout());
339         this.title = title;
340         this.resizable = resizable;
341         this.closable = closable;
342         this.maximizable = maximizable;
343         isMaximum = false;
344         this.iconable = iconifiable;
345         isIcon = false;
346         setVisible(false);
347         setRootPaneCheckingEnabled(true);
348         desktopIcon = new JDesktopIcon(this);
349         updateUI();
350         sun.awt.SunToolkit.checkAndSetPolicy(this);
351         addPropertyChangeListenerIfNecessary();
352     }
353 
354     /**
355      * Called by the constructor to set up the <code>JRootPane</code>.
356      * @return  a new <code>JRootPane</code>
357      * @see JRootPane
358      */
createRootPane()359     protected JRootPane createRootPane() {
360         return new JRootPane();
361     }
362 
363     /**
364      * Returns the look-and-feel object that renders this component.
365      *
366      * @return the <code>InternalFrameUI</code> object that renders
367      *          this component
368      */
getUI()369     public InternalFrameUI getUI() {
370         return (InternalFrameUI)ui;
371     }
372 
373     /**
374      * Sets the UI delegate for this <code>JInternalFrame</code>.
375      * @param ui  the UI delegate
376      */
377     @BeanProperty(hidden = true, visualUpdate = true, description
378             = "The UI object that implements the Component's LookAndFeel.")
setUI(InternalFrameUI ui)379     public void setUI(InternalFrameUI ui) {
380         boolean checkingEnabled = isRootPaneCheckingEnabled();
381         try {
382             setRootPaneCheckingEnabled(false);
383             super.setUI(ui);
384         }
385         finally {
386             setRootPaneCheckingEnabled(checkingEnabled);
387         }
388     }
389 
390     /**
391      * Notification from the <code>UIManager</code> that the look and feel
392      * has changed.
393      * Replaces the current UI object with the latest version from the
394      * <code>UIManager</code>.
395      *
396      * @see JComponent#updateUI
397      */
updateUI()398     public void updateUI() {
399         setUI((InternalFrameUI)UIManager.getUI(this));
400         invalidate();
401         if (desktopIcon != null) {
402             desktopIcon.updateUIWhenHidden();
403         }
404     }
405 
406     /* This method is called if <code>updateUI</code> was called
407      * on the associated
408      * JDesktopIcon.  It's necessary to avoid infinite recursion.
409      */
updateUIWhenHidden()410     void updateUIWhenHidden() {
411         setUI((InternalFrameUI)UIManager.getUI(this));
412         invalidate();
413         Component[] children = getComponents();
414         if (children != null) {
415             for (Component child : children) {
416                 SwingUtilities.updateComponentTreeUI(child);
417             }
418         }
419     }
420 
421 
422     /**
423      * Returns the name of the look-and-feel
424      * class that renders this component.
425      *
426      * @return the string "InternalFrameUI"
427      *
428      * @see JComponent#getUIClassID
429      * @see UIDefaults#getUI
430      */
431     @BeanProperty(bound = false, description
432             = "UIClassID")
getUIClassID()433     public String getUIClassID() {
434         return uiClassID;
435     }
436 
437     /**
438      * Returns whether calls to <code>add</code> and
439      * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
440      *
441      * @return true if <code>add</code> and <code>setLayout</code>
442      *         are forwarded; false otherwise
443      *
444      * @see #addImpl
445      * @see #setLayout
446      * @see #setRootPaneCheckingEnabled
447      * @see javax.swing.RootPaneContainer
448      */
isRootPaneCheckingEnabled()449     protected boolean isRootPaneCheckingEnabled() {
450         return rootPaneCheckingEnabled;
451     }
452 
453     /**
454      * Sets whether calls to <code>add</code> and
455      * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
456      *
457      * @param enabled  true if <code>add</code> and <code>setLayout</code>
458      *        are forwarded, false if they should operate directly on the
459      *        <code>JInternalFrame</code>.
460      *
461      * @see #addImpl
462      * @see #setLayout
463      * @see #isRootPaneCheckingEnabled
464      * @see javax.swing.RootPaneContainer
465      */
466     @BeanProperty(hidden = true, description
467             = "Whether the add and setLayout methods are forwarded")
setRootPaneCheckingEnabled(boolean enabled)468     protected void setRootPaneCheckingEnabled(boolean enabled) {
469         rootPaneCheckingEnabled = enabled;
470     }
471 
472     /**
473      * Adds the specified child <code>Component</code>.
474      * This method is overridden to conditionally forward calls to the
475      * <code>contentPane</code>.
476      * By default, children are added to the <code>contentPane</code> instead
477      * of the frame, refer to {@link javax.swing.RootPaneContainer} for
478      * details.
479      *
480      * @param comp the component to be enhanced
481      * @param constraints the constraints to be respected
482      * @param index the index
483      * @exception IllegalArgumentException if <code>index</code> is invalid
484      * @exception IllegalArgumentException if adding the container's parent
485      *                  to itself
486      * @exception IllegalArgumentException if adding a window to a container
487      *
488      * @see #setRootPaneCheckingEnabled
489      * @see javax.swing.RootPaneContainer
490      */
addImpl(Component comp, Object constraints, int index)491     protected void addImpl(Component comp, Object constraints, int index) {
492         if(isRootPaneCheckingEnabled()) {
493             getContentPane().add(comp, constraints, index);
494         }
495         else {
496             super.addImpl(comp, constraints, index);
497         }
498     }
499 
500     /**
501      * Removes the specified component from the container. If
502      * <code>comp</code> is not a child of the <code>JInternalFrame</code>
503      * this will forward the call to the <code>contentPane</code>.
504      *
505      * @param comp the component to be removed
506      * @throws NullPointerException if <code>comp</code> is null
507      * @see #add
508      * @see javax.swing.RootPaneContainer
509      */
remove(Component comp)510     public void remove(Component comp) {
511         int oldCount = getComponentCount();
512         super.remove(comp);
513         if (oldCount == getComponentCount()) {
514             getContentPane().remove(comp);
515         }
516     }
517 
518 
519     /**
520      * Ensures that, by default, the layout of this component cannot be set.
521      * Overridden to conditionally forward the call to the
522      * <code>contentPane</code>.
523      * Refer to {@link javax.swing.RootPaneContainer} for
524      * more information.
525      *
526      * @param manager the <code>LayoutManager</code>
527      * @see #setRootPaneCheckingEnabled
528      */
setLayout(LayoutManager manager)529     public void setLayout(LayoutManager manager) {
530         if(isRootPaneCheckingEnabled()) {
531             getContentPane().setLayout(manager);
532         }
533         else {
534             super.setLayout(manager);
535         }
536     }
537 
538 
539 //////////////////////////////////////////////////////////////////////////
540 /// Property Methods
541 //////////////////////////////////////////////////////////////////////////
542 
543     /**
544      * Returns the current <code>JMenuBar</code> for this
545      * <code>JInternalFrame</code>, or <code>null</code>
546      * if no menu bar has been set.
547      * @return the current menu bar, or <code>null</code> if none has been set
548      *
549      * @deprecated As of Swing version 1.0.3,
550      * replaced by <code>getJMenuBar()</code>.
551      */
552     @Deprecated
getMenuBar()553     public JMenuBar getMenuBar() {
554       return getRootPane().getMenuBar();
555     }
556 
557     /**
558      * Returns the current <code>JMenuBar</code> for this
559      * <code>JInternalFrame</code>, or <code>null</code>
560      * if no menu bar has been set.
561      *
562      * @return  the <code>JMenuBar</code> used by this internal frame
563      * @see #setJMenuBar
564      */
getJMenuBar()565     public JMenuBar getJMenuBar() {
566         return getRootPane().getJMenuBar();
567     }
568 
569     /**
570      * Sets the <code>menuBar</code> property for this <code>JInternalFrame</code>.
571      *
572      * @param m  the <code>JMenuBar</code> to use in this internal frame
573      * @see #getJMenuBar
574      * @deprecated As of Swing version 1.0.3
575      *  replaced by <code>setJMenuBar(JMenuBar m)</code>.
576      */
577     @Deprecated
setMenuBar(JMenuBar m)578     public void setMenuBar(JMenuBar m) {
579         JMenuBar oldValue = getMenuBar();
580         getRootPane().setJMenuBar(m);
581         firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);
582     }
583 
584     /**
585      * Sets the <code>menuBar</code> property for this <code>JInternalFrame</code>.
586      *
587      * @param m  the <code>JMenuBar</code> to use in this internal frame
588      * @see #getJMenuBar
589      */
590     @BeanProperty(preferred = true, description
591             = "The menu bar for accessing pulldown menus from this internal frame.")
setJMenuBar(JMenuBar m)592     public void setJMenuBar(JMenuBar m){
593         JMenuBar oldValue = getMenuBar();
594         getRootPane().setJMenuBar(m);
595         firePropertyChange(MENU_BAR_PROPERTY, oldValue, m);
596     }
597 
598     // implements javax.swing.RootPaneContainer
599     /**
600      * Returns the content pane for this internal frame.
601      * @return the content pane
602      */
getContentPane()603     public Container getContentPane() {
604         return getRootPane().getContentPane();
605     }
606 
607 
608     /**
609      * Sets this <code>JInternalFrame</code>'s <code>contentPane</code>
610      * property.
611      *
612      * @param c  the content pane for this internal frame
613      *
614      * @exception java.awt.IllegalComponentStateException (a runtime
615      *           exception) if the content pane parameter is <code>null</code>
616      * @see RootPaneContainer#getContentPane
617      */
618     @BeanProperty(hidden = true, description
619             = "The client area of the internal frame where child components are normally inserted.")
setContentPane(Container c)620     public void setContentPane(Container c) {
621         Container oldValue = getContentPane();
622         getRootPane().setContentPane(c);
623         firePropertyChange(CONTENT_PANE_PROPERTY, oldValue, c);
624     }
625 
626     /**
627      * Returns the layered pane for this internal frame.
628      *
629      * @return a <code>JLayeredPane</code> object
630      * @see RootPaneContainer#setLayeredPane
631      * @see RootPaneContainer#getLayeredPane
632      */
getLayeredPane()633     public JLayeredPane getLayeredPane() {
634         return getRootPane().getLayeredPane();
635     }
636 
637     /**
638      * Sets this <code>JInternalFrame</code>'s
639      * <code>layeredPane</code> property.
640      *
641      * @param layered the <code>JLayeredPane</code> for this internal frame
642      *
643      * @exception java.awt.IllegalComponentStateException (a runtime
644      *           exception) if the layered pane parameter is <code>null</code>
645      * @see RootPaneContainer#setLayeredPane
646      */
647     @BeanProperty(hidden = true, description
648             = "The pane which holds the various desktop layers.")
setLayeredPane(JLayeredPane layered)649     public void setLayeredPane(JLayeredPane layered) {
650         JLayeredPane oldValue = getLayeredPane();
651         getRootPane().setLayeredPane(layered);
652         firePropertyChange(LAYERED_PANE_PROPERTY, oldValue, layered);
653     }
654 
655     /**
656      * Returns the glass pane for this internal frame.
657      *
658      * @return the glass pane
659      * @see RootPaneContainer#setGlassPane
660      */
getGlassPane()661     public Component getGlassPane() {
662         return getRootPane().getGlassPane();
663     }
664 
665     /**
666      * Sets this <code>JInternalFrame</code>'s
667      * <code>glassPane</code> property.
668      *
669      * @param glass the glass pane for this internal frame
670      * @see RootPaneContainer#getGlassPane
671      */
672     @BeanProperty(hidden = true, description
673             = "A transparent pane used for menu rendering.")
setGlassPane(Component glass)674     public void setGlassPane(Component glass) {
675         Component oldValue = getGlassPane();
676         getRootPane().setGlassPane(glass);
677         firePropertyChange(GLASS_PANE_PROPERTY, oldValue, glass);
678     }
679 
680     /**
681      * Returns the <code>rootPane</code> object for this internal frame.
682      *
683      * @return the <code>rootPane</code> property
684      * @see RootPaneContainer#getRootPane
685      */
686     @BeanProperty(hidden = true, description
687             = "The root pane used by this internal frame.")
getRootPane()688     public JRootPane getRootPane() {
689         return rootPane;
690     }
691 
692 
693     /**
694      * Sets the <code>rootPane</code> property
695      * for this <code>JInternalFrame</code>.
696      * This method is called by the constructor.
697      *
698      * @param root  the new <code>JRootPane</code> object
699      */
setRootPane(JRootPane root)700     protected void setRootPane(JRootPane root) {
701         if(rootPane != null) {
702             remove(rootPane);
703         }
704         JRootPane oldValue = getRootPane();
705         rootPane = root;
706         if(rootPane != null) {
707             boolean checkingEnabled = isRootPaneCheckingEnabled();
708             try {
709                 setRootPaneCheckingEnabled(false);
710                 add(rootPane, BorderLayout.CENTER);
711             }
712             finally {
713                 setRootPaneCheckingEnabled(checkingEnabled);
714             }
715         }
716         firePropertyChange(ROOT_PANE_PROPERTY, oldValue, root);
717     }
718 
719     /**
720      * Sets whether this <code>JInternalFrame</code> can be closed by
721      * some user action.
722      * @param b a boolean value, where <code>true</code> means this internal frame can be closed
723      */
724     @BeanProperty(preferred = true, description
725             = "Indicates whether this internal frame can be closed.")
setClosable(boolean b)726     public void setClosable(boolean b) {
727         Boolean oldValue = closable ? Boolean.TRUE : Boolean.FALSE;
728         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
729         closable = b;
730         firePropertyChange("closable", oldValue, newValue);
731     }
732 
733     /**
734      * Returns whether this <code>JInternalFrame</code> can be closed by
735      * some user action.
736      * @return <code>true</code> if this internal frame can be closed
737      */
isClosable()738     public boolean isClosable() {
739         return closable;
740     }
741 
742     /**
743      * Returns whether this <code>JInternalFrame</code> is currently closed.
744      * @return <code>true</code> if this internal frame is closed, <code>false</code> otherwise
745      */
isClosed()746     public boolean isClosed() {
747         return isClosed;
748     }
749 
750     /**
751      * Closes this internal frame if the argument is <code>true</code>.
752      * Do not invoke this method with a <code>false</code> argument;
753      * the result of invoking <code>setClosed(false)</code>
754      * is unspecified.
755      *
756      * <p>
757      *
758      * If the internal frame is already closed,
759      * this method does nothing and returns immediately.
760      * Otherwise,
761      * this method begins by firing
762      * an <code>INTERNAL_FRAME_CLOSING</code> event.
763      * Then this method sets the <code>closed</code> property to <code>true</code>
764      * unless a listener vetoes the property change.
765      * This method finishes by making the internal frame
766      * invisible and unselected,
767      * and then firing an <code>INTERNAL_FRAME_CLOSED</code> event.
768      *
769      * <p>
770      *
771      * <b>Note:</b>
772      * To reuse an internal frame that has been closed,
773      * you must add it to a container
774      * (even if you never removed it from its previous container).
775      * Typically, this container will be the <code>JDesktopPane</code>
776      * that previously contained the internal frame.
777      *
778      * @param b must be <code>true</code>
779      *
780      * @exception PropertyVetoException when the attempt to set the
781      *            property is vetoed by the <code>JInternalFrame</code>
782      *
783      * @see #isClosed()
784      * @see #setDefaultCloseOperation
785      * @see #dispose
786      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING
787      */
788     @BeanProperty(description
789             = "Indicates whether this internal frame has been closed.")
setClosed(boolean b)790     public void setClosed(boolean b) throws PropertyVetoException {
791         if (isClosed == b) {
792             return;
793         }
794 
795         Boolean oldValue = isClosed ? Boolean.TRUE : Boolean.FALSE;
796         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
797         if (b) {
798           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
799         }
800         fireVetoableChange(IS_CLOSED_PROPERTY, oldValue, newValue);
801         isClosed = b;
802         if (isClosed) {
803           setVisible(false);
804         }
805         firePropertyChange(IS_CLOSED_PROPERTY, oldValue, newValue);
806         if (isClosed) {
807           dispose();
808         } else if (!opened) {
809           /* this bogus -- we haven't defined what
810              setClosed(false) means. */
811           //        fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
812           //            opened = true;
813         }
814     }
815 
816     /**
817      * Sets whether the <code>JInternalFrame</code> can be resized by some
818      * user action.
819      *
820      * @param b  a boolean, where <code>true</code> means this internal frame can be resized
821      */
822     @BeanProperty(preferred = true, description
823             = "Determines whether this internal frame can be resized by the user.")
setResizable(boolean b)824     public void setResizable(boolean b) {
825         Boolean oldValue = resizable ? Boolean.TRUE : Boolean.FALSE;
826         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
827         resizable = b;
828         firePropertyChange("resizable", oldValue, newValue);
829     }
830 
831     /**
832      * Returns whether the <code>JInternalFrame</code> can be resized
833      * by some user action.
834      *
835      * @return <code>true</code> if this internal frame can be resized, <code>false</code> otherwise
836      */
isResizable()837     public boolean isResizable() {
838         // don't allow resizing when maximized.
839         return isMaximum ? false : resizable;
840     }
841 
842     /**
843      * Sets the <code>iconable</code> property,
844      * which must be <code>true</code>
845      * for the user to be able to
846      * make the <code>JInternalFrame</code> an icon.
847      * Some look and feels might not implement iconification;
848      * they will ignore this property.
849      *
850      * @param b  a boolean, where <code>true</code> means this internal frame can be iconified
851      */
852     @BeanProperty(preferred = true, description
853             = "Determines whether this internal frame can be iconified.")
setIconifiable(boolean b)854     public void setIconifiable(boolean b) {
855         Boolean oldValue = iconable ? Boolean.TRUE : Boolean.FALSE;
856         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
857         iconable = b;
858         firePropertyChange("iconable", oldValue, newValue);
859     }
860 
861     /**
862      * Gets the <code>iconable</code> property,
863      * which by default is <code>false</code>.
864      *
865      * @return the value of the <code>iconable</code> property.
866      *
867      * @see #setIconifiable
868      */
isIconifiable()869     public boolean isIconifiable() {
870         return iconable;
871     }
872 
873     /**
874      * Returns whether the <code>JInternalFrame</code> is currently iconified.
875      *
876      * @return <code>true</code> if this internal frame is iconified
877      */
isIcon()878     public boolean isIcon() {
879         return isIcon;
880     }
881 
882     /**
883      * Iconifies or de-iconifies this internal frame,
884      * if the look and feel supports iconification.
885      * If the internal frame's state changes to iconified,
886      * this method fires an <code>INTERNAL_FRAME_ICONIFIED</code> event.
887      * If the state changes to de-iconified,
888      * an <code>INTERNAL_FRAME_DEICONIFIED</code> event is fired.
889      *
890      * @param b a boolean, where <code>true</code> means to iconify this internal frame and
891      *          <code>false</code> means to de-iconify it
892      * @exception PropertyVetoException when the attempt to set the
893      *            property is vetoed by the <code>JInternalFrame</code>
894      *
895      * @see InternalFrameEvent#INTERNAL_FRAME_ICONIFIED
896      * @see InternalFrameEvent#INTERNAL_FRAME_DEICONIFIED
897      */
898     @BeanProperty(description
899             = "The image displayed when this internal frame is minimized.")
setIcon(boolean b)900     public void setIcon(boolean b) throws PropertyVetoException {
901         if (isIcon == b) {
902             return;
903         }
904 
905         /* If an internal frame is being iconified before it has a
906            parent, (e.g., client wants it to start iconic), create the
907            parent if possible so that we can place the icon in its
908            proper place on the desktop. I am not sure the call to
909            validate() is necessary, since we are not going to display
910            this frame yet */
911         firePropertyChange("ancestor", null, getParent());
912 
913         Boolean oldValue = isIcon ? Boolean.TRUE : Boolean.FALSE;
914         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
915         fireVetoableChange(IS_ICON_PROPERTY, oldValue, newValue);
916         isIcon = b;
917         firePropertyChange(IS_ICON_PROPERTY, oldValue, newValue);
918         if (b)
919           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ICONIFIED);
920         else
921           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED);
922     }
923 
924     /**
925      * Sets the <code>maximizable</code> property,
926      * which determines whether the <code>JInternalFrame</code>
927      * can be maximized by
928      * some user action.
929      * Some look and feels might not support maximizing internal frames;
930      * they will ignore this property.
931      *
932      * @param b <code>true</code> to specify that this internal frame should be maximizable; <code>false</code> to specify that it should not be
933      */
934     @BeanProperty(preferred = true, description
935             = "Determines whether this internal frame can be maximized.")
setMaximizable(boolean b)936     public void setMaximizable(boolean b) {
937         Boolean oldValue = maximizable ? Boolean.TRUE : Boolean.FALSE;
938         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
939         maximizable = b;
940         firePropertyChange("maximizable", oldValue, newValue);
941     }
942 
943     /**
944      * Gets the value of the <code>maximizable</code> property.
945      *
946      * @return the value of the <code>maximizable</code> property
947      * @see #setMaximizable
948      */
isMaximizable()949     public boolean isMaximizable() {
950         return maximizable;
951     }
952 
953     /**
954      * Returns whether the <code>JInternalFrame</code> is currently maximized.
955      *
956      * @return <code>true</code> if this internal frame is maximized, <code>false</code> otherwise
957      */
isMaximum()958     public boolean isMaximum() {
959         return isMaximum;
960     }
961 
962     /**
963      * Maximizes and restores this internal frame.  A maximized frame is resized to
964      * fully fit the <code>JDesktopPane</code> area associated with the
965      * <code>JInternalFrame</code>.
966      * A restored frame's size is set to the <code>JInternalFrame</code>'s
967      * actual size.
968      *
969      * @param b  a boolean, where <code>true</code> maximizes this internal frame and <code>false</code>
970      *           restores it
971      * @exception PropertyVetoException when the attempt to set the
972      *            property is vetoed by the <code>JInternalFrame</code>
973      */
974     @BeanProperty(description
975             = "Indicates whether this internal frame is maximized.")
setMaximum(boolean b)976     public void setMaximum(boolean b) throws PropertyVetoException {
977         if (isMaximum == b) {
978             return;
979         }
980 
981         Boolean oldValue = isMaximum ? Boolean.TRUE : Boolean.FALSE;
982         Boolean newValue = b ? Boolean.TRUE : Boolean.FALSE;
983         fireVetoableChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
984         /* setting isMaximum above the event firing means that
985            property listeners that, for some reason, test it will
986            get it wrong... See, for example, getNormalBounds() */
987         isMaximum = b;
988         firePropertyChange(IS_MAXIMUM_PROPERTY, oldValue, newValue);
989     }
990 
991     /**
992      * Returns the title of the <code>JInternalFrame</code>.
993      *
994      * @return a <code>String</code> containing this internal frame's title
995      * @see #setTitle
996      */
getTitle()997     public String getTitle() {
998         return title;
999     }
1000 
1001     /**
1002      * Sets the <code>JInternalFrame</code> title. <code>title</code>
1003      * may have a <code>null</code> value.
1004      * @see #getTitle
1005      *
1006      * @param title  the <code>String</code> to display in the title bar
1007      */
1008     @BeanProperty(preferred = true, description
1009             = "The text displayed in the title bar.")
setTitle(String title)1010     public void setTitle(String title) {
1011         String oldValue = this.title;
1012         this.title = title;
1013         firePropertyChange(TITLE_PROPERTY, oldValue, title);
1014     }
1015 
1016     /**
1017      * Selects or deselects the internal frame
1018      * if it's showing.
1019      * A <code>JInternalFrame</code> normally draws its title bar
1020      * differently if it is
1021      * the selected frame, which indicates to the user that this
1022      * internal frame has the focus.
1023      * When this method changes the state of the internal frame
1024      * from deselected to selected, it fires an
1025      * <code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code> event.
1026      * If the change is from selected to deselected,
1027      * an <code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code> event
1028      * is fired.
1029      *
1030      * @param selected  a boolean, where <code>true</code> means this internal frame
1031      *                  should become selected (currently active)
1032      *                  and <code>false</code> means it should become deselected
1033      * @exception PropertyVetoException when the attempt to set the
1034      *            property is vetoed by the <code>JInternalFrame</code>
1035      *
1036      * @see #isShowing
1037      * @see InternalFrameEvent#INTERNAL_FRAME_ACTIVATED
1038      * @see InternalFrameEvent#INTERNAL_FRAME_DEACTIVATED
1039      */
1040     @BeanProperty(description
1041             = "Indicates whether this internal frame is currently the active frame.")
setSelected(boolean selected)1042     public void setSelected(boolean selected) throws PropertyVetoException {
1043        // The InternalFrame may already be selected, but the focus
1044        // may be outside it, so restore the focus to the subcomponent
1045        // which previously had it. See Bug 4302764.
1046         if (selected && isSelected) {
1047             restoreSubcomponentFocus();
1048             return;
1049         }
1050         // The internal frame or the desktop icon must be showing to allow
1051         // selection.  We may deselect even if neither is showing.
1052         if ((isSelected == selected) || (selected &&
1053             (isIcon ? !desktopIcon.isShowing() : !isShowing()))) {
1054             return;
1055         }
1056 
1057         Boolean oldValue = isSelected ? Boolean.TRUE : Boolean.FALSE;
1058         Boolean newValue = selected ? Boolean.TRUE : Boolean.FALSE;
1059         fireVetoableChange(IS_SELECTED_PROPERTY, oldValue, newValue);
1060 
1061         /* We don't want to leave focus in the previously selected
1062            frame, so we have to set it to *something* in case it
1063            doesn't get set in some other way (as if a user clicked on
1064            a component that doesn't request focus).  If this call is
1065            happening because the user clicked on a component that will
1066            want focus, then it will get transfered there later.
1067 
1068            We test for parent.isShowing() above, because AWT throws a
1069            NPE if you try to request focus on a lightweight before its
1070            parent has been made visible */
1071 
1072         if (selected) {
1073             restoreSubcomponentFocus();
1074         }
1075 
1076         isSelected = selected;
1077         firePropertyChange(IS_SELECTED_PROPERTY, oldValue, newValue);
1078         if (isSelected)
1079           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ACTIVATED);
1080         else {
1081           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED);
1082           try {
1083               java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(
1084                                                new sun.awt.UngrabEvent(this));
1085           } catch (SecurityException e) {
1086               this.dispatchEvent(new sun.awt.UngrabEvent(this));
1087           }
1088         }
1089         repaint();
1090     }
1091 
1092     /**
1093      * Returns whether the <code>JInternalFrame</code> is the
1094      * currently "selected" or active frame.
1095      *
1096      * @return <code>true</code> if this internal frame is currently selected (active)
1097      * @see #setSelected
1098      */
isSelected()1099     public boolean isSelected() {
1100         return isSelected;
1101     }
1102 
1103     /**
1104      * Sets an image to be displayed in the titlebar of this internal frame (usually
1105      * in the top-left corner).
1106      * Some look and feels might not support displaying an icon in the titlebar.
1107      *
1108      * This image is not the <code>desktopIcon</code> object, which
1109      * is the image displayed in the <code>JDesktop</code> when
1110      * this internal frame is iconified.
1111      *
1112      * Passing <code>null</code> to this function is valid,
1113      * but the look and feel can choose the appropriate behavior
1114      * for that situation, such as displaying no icon
1115      * or a default icon for the look and feel.
1116      *
1117      * @param icon the <code>Icon</code> to display in the title bar
1118      * @see #getFrameIcon
1119      */
1120     @BeanProperty(description
1121             = "The icon shown in the top-left corner of this internal frame.")
setFrameIcon(Icon icon)1122   public void setFrameIcon(Icon icon) {
1123         Icon oldIcon = frameIcon;
1124         frameIcon = icon;
1125         firePropertyChange(FRAME_ICON_PROPERTY, oldIcon, icon);
1126     }
1127 
1128     /**
1129      * Returns the image displayed in the title bar of this internal frame (usually
1130      * in the top-left corner).
1131      *
1132      * @return the <code>Icon</code> displayed in the title bar
1133      * @see #setFrameIcon
1134      */
getFrameIcon()1135     public Icon getFrameIcon()  {
1136         return frameIcon;
1137     }
1138 
1139     /**
1140       * Convenience method that moves this component to position 0 if its
1141       * parent is a <code>JLayeredPane</code>.
1142       */
moveToFront()1143     public void moveToFront() {
1144         if (isIcon()) {
1145             if (getDesktopIcon().getParent() instanceof JLayeredPane) {
1146                 ((JLayeredPane)getDesktopIcon().getParent()).
1147                     moveToFront(getDesktopIcon());
1148             }
1149         }
1150         else if (getParent() instanceof JLayeredPane) {
1151             ((JLayeredPane)getParent()).moveToFront(this);
1152         }
1153     }
1154 
1155     /**
1156       * Convenience method that moves this component to position -1 if its
1157       * parent is a <code>JLayeredPane</code>.
1158       */
moveToBack()1159     public void moveToBack() {
1160         if (isIcon()) {
1161             if (getDesktopIcon().getParent() instanceof JLayeredPane) {
1162                 ((JLayeredPane)getDesktopIcon().getParent()).
1163                     moveToBack(getDesktopIcon());
1164             }
1165         }
1166         else if (getParent() instanceof JLayeredPane) {
1167             ((JLayeredPane)getParent()).moveToBack(this);
1168         }
1169     }
1170 
1171     /**
1172      * Returns the last <code>Cursor</code> that was set by the
1173      * <code>setCursor</code> method that is not a resizable
1174      * <code>Cursor</code>.
1175      *
1176      * @return the last non-resizable <code>Cursor</code>
1177      * @since 1.6
1178      */
1179     @BeanProperty(bound = false)
getLastCursor()1180     public Cursor getLastCursor() {
1181         return lastCursor;
1182     }
1183 
1184     /**
1185      * {@inheritDoc}
1186      * @since 1.6
1187      */
setCursor(Cursor cursor)1188     public void setCursor(Cursor cursor) {
1189         if (cursor == null) {
1190             lastCursor = null;
1191             super.setCursor(cursor);
1192             return;
1193         }
1194         int type = cursor.getType();
1195         if (!(type == Cursor.SW_RESIZE_CURSOR  ||
1196               type == Cursor.SE_RESIZE_CURSOR  ||
1197               type == Cursor.NW_RESIZE_CURSOR  ||
1198               type == Cursor.NE_RESIZE_CURSOR  ||
1199               type == Cursor.N_RESIZE_CURSOR   ||
1200               type == Cursor.S_RESIZE_CURSOR   ||
1201               type == Cursor.W_RESIZE_CURSOR   ||
1202               type == Cursor.E_RESIZE_CURSOR)) {
1203             lastCursor = cursor;
1204         }
1205         super.setCursor(cursor);
1206     }
1207 
1208     /**
1209      * Convenience method for setting the layer attribute of this component.
1210      *
1211      * @param layer  an <code>Integer</code> object specifying this
1212      *          frame's desktop layer
1213      * @throws NullPointerException if {@code layer} is {@code null}
1214      * @see JLayeredPane
1215      */
1216     @BeanProperty(bound = false, expert = true, description
1217             = "Specifies what desktop layer is used.")
setLayer(Integer layer)1218     public void setLayer(Integer layer) {
1219         if(getParent() != null && getParent() instanceof JLayeredPane) {
1220             // Normally we want to do this, as it causes the LayeredPane
1221             // to draw properly.
1222             JLayeredPane p = (JLayeredPane)getParent();
1223             p.setLayer(this, layer.intValue(), p.getPosition(this));
1224         } else {
1225              // Try to do the right thing
1226              JLayeredPane.putLayer(this, layer.intValue());
1227              if(getParent() != null)
1228                  getParent().repaint(getX(), getY(), getWidth(), getHeight());
1229         }
1230     }
1231 
1232     /**
1233      * Convenience method for setting the layer attribute of this component.
1234      * The method <code>setLayer(Integer)</code> should be used for
1235      * layer values predefined in <code>JLayeredPane</code>.
1236      * When using <code>setLayer(int)</code>, care must be taken not to
1237      * accidentally clash with those values.
1238      *
1239      * @param layer  an integer specifying this internal frame's desktop layer
1240      *
1241      * @since 1.3
1242      *
1243      * @see #setLayer(Integer)
1244      * @see JLayeredPane
1245      */
1246     @BeanProperty(bound = false, expert = true, description
1247             = "Specifies what desktop layer is used.")
setLayer(int layer)1248     public void setLayer(int layer) {
1249       this.setLayer(Integer.valueOf(layer));
1250     }
1251 
1252     /**
1253      * Convenience method for getting the layer attribute of this component.
1254      *
1255      * @return  an <code>Integer</code> object specifying this
1256      *          frame's desktop layer
1257      * @see JLayeredPane
1258       */
getLayer()1259     public int getLayer() {
1260         return JLayeredPane.getLayer(this);
1261     }
1262 
1263     /**
1264       * Convenience method that searches the ancestor hierarchy for a
1265       * <code>JDesktop</code> instance. If <code>JInternalFrame</code>
1266       * finds none, the <code>desktopIcon</code> tree is searched.
1267       *
1268       * @return the <code>JDesktopPane</code> this internal frame belongs to,
1269       *         or <code>null</code> if none is found
1270       */
1271     @BeanProperty(bound = false)
getDesktopPane()1272     public JDesktopPane getDesktopPane() {
1273         Container p;
1274 
1275         // Search upward for desktop
1276         p = getParent();
1277         while(p != null && !(p instanceof JDesktopPane))
1278             p = p.getParent();
1279 
1280         if(p == null) {
1281            // search its icon parent for desktop
1282            p = getDesktopIcon().getParent();
1283            while(p != null && !(p instanceof JDesktopPane))
1284                 p = p.getParent();
1285         }
1286 
1287         return (JDesktopPane)p;
1288     }
1289 
1290     /**
1291      * Sets the <code>JDesktopIcon</code> associated with this
1292      * <code>JInternalFrame</code>.
1293      *
1294      * @param d the <code>JDesktopIcon</code> to display on the desktop
1295      * @see #getDesktopIcon
1296      */
1297     @BeanProperty(description
1298             = "The icon shown when this internal frame is minimized.")
setDesktopIcon(JDesktopIcon d)1299     public void setDesktopIcon(JDesktopIcon d) {
1300         JDesktopIcon oldValue = getDesktopIcon();
1301         desktopIcon = d;
1302         firePropertyChange("desktopIcon", oldValue, d);
1303     }
1304 
1305     /**
1306      * Returns the <code>JDesktopIcon</code> used when this
1307      * <code>JInternalFrame</code> is iconified.
1308      *
1309      * @return the <code>JDesktopIcon</code> displayed on the desktop
1310      * @see #setDesktopIcon
1311      */
getDesktopIcon()1312     public JDesktopIcon getDesktopIcon() {
1313         return desktopIcon;
1314     }
1315 
1316     /**
1317      * If the <code>JInternalFrame</code> is not in maximized state, returns
1318      * <code>getBounds()</code>; otherwise, returns the bounds that the
1319      * <code>JInternalFrame</code> would be restored to.
1320      *
1321      * @return a <code>Rectangle</code> containing the bounds of this
1322      *          frame when in the normal state
1323      * @since 1.3
1324      */
getNormalBounds()1325     public Rectangle getNormalBounds() {
1326 
1327       /* we used to test (!isMaximum) here, but since this
1328          method is used by the property listener for the
1329          IS_MAXIMUM_PROPERTY, it ended up getting the wrong
1330          answer... Since normalBounds get set to null when the
1331          frame is restored, this should work better */
1332 
1333       if (normalBounds != null) {
1334         return normalBounds;
1335       } else {
1336         return getBounds();
1337       }
1338     }
1339 
1340     /**
1341      * Sets the normal bounds for this internal frame, the bounds that
1342      * this internal frame would be restored to from its maximized state.
1343      * This method is intended for use only by desktop managers.
1344      *
1345      * @param r the bounds that this internal frame should be restored to
1346      * @since 1.3
1347      */
setNormalBounds(Rectangle r)1348     public void setNormalBounds(Rectangle r) {
1349         normalBounds = r;
1350     }
1351 
1352     /**
1353      * If this <code>JInternalFrame</code> is active,
1354      * returns the child that has focus.
1355      * Otherwise, returns <code>null</code>.
1356      *
1357      * @return the component with focus, or <code>null</code> if no children have focus
1358      * @since 1.3
1359      */
getFocusOwner()1360     public Component getFocusOwner() {
1361         if (isSelected()) {
1362             return lastFocusOwner;
1363         }
1364         return null;
1365     }
1366 
1367     /**
1368      * Returns the child component of this <code>JInternalFrame</code>
1369      * that will receive the
1370      * focus when this <code>JInternalFrame</code> is selected.
1371      * If this <code>JInternalFrame</code> is
1372      * currently selected, this method returns the same component as
1373      * the <code>getFocusOwner</code> method.
1374      * If this <code>JInternalFrame</code> is not selected,
1375      * then the child component that most recently requested focus will be
1376      * returned. If no child component has ever requested focus, then this
1377      * <code>JInternalFrame</code>'s initial focusable component is returned.
1378      * If no such
1379      * child exists, then this <code>JInternalFrame</code>'s default component
1380      * to focus is returned.
1381      *
1382      * @return the child component that will receive focus when this
1383      *         <code>JInternalFrame</code> is selected
1384      * @see #getFocusOwner
1385      * @see #isSelected
1386      * @since 1.4
1387      */
1388     @BeanProperty(bound = false)
getMostRecentFocusOwner()1389     public Component getMostRecentFocusOwner() {
1390         if (isSelected()) {
1391             return getFocusOwner();
1392         }
1393 
1394         if (lastFocusOwner != null) {
1395             return lastFocusOwner;
1396         }
1397 
1398         FocusTraversalPolicy policy = getFocusTraversalPolicy();
1399         if (policy instanceof InternalFrameFocusTraversalPolicy) {
1400             return ((InternalFrameFocusTraversalPolicy)policy).
1401                 getInitialComponent(this);
1402         }
1403 
1404         Component toFocus = policy.getDefaultComponent(this);
1405         if (toFocus != null) {
1406             return toFocus;
1407         }
1408         return getContentPane();
1409     }
1410 
1411     /**
1412      * Requests the internal frame to restore focus to the
1413      * last subcomponent that had focus. This is used by the UI when
1414      * the user selected this internal frame --
1415      * for example, by clicking on the title bar.
1416      *
1417      * @since 1.3
1418      */
restoreSubcomponentFocus()1419     public void restoreSubcomponentFocus() {
1420         if (isIcon()) {
1421             SwingUtilities2.compositeRequestFocus(getDesktopIcon());
1422         }
1423         else {
1424             Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
1425             if ((component == null) || !SwingUtilities.isDescendingFrom(component, this)) {
1426                 // FocusPropertyChangeListener will eventually update
1427                 // lastFocusOwner. As focus requests are asynchronous
1428                 // lastFocusOwner may be accessed before it has been correctly
1429                 // updated. To avoid any problems, lastFocusOwner is immediately
1430                 // set, assuming the request will succeed.
1431                 setLastFocusOwner(getMostRecentFocusOwner());
1432                 if (lastFocusOwner == null) {
1433                     // Make sure focus is restored somewhere, so that
1434                     // we don't leave a focused component in another frame while
1435                     // this frame is selected.
1436                     setLastFocusOwner(getContentPane());
1437                 }
1438                 lastFocusOwner.requestFocus();
1439             }
1440         }
1441     }
1442 
setLastFocusOwner(Component component)1443     private void setLastFocusOwner(Component component) {
1444         lastFocusOwner = component;
1445     }
1446 
1447     /**
1448      * Moves and resizes this component.  Unlike other components,
1449      * this implementation also forces re-layout, so that frame
1450      * decorations such as the title bar are always redisplayed.
1451      *
1452      * @param x  an integer giving the component's new horizontal position
1453      *           measured in pixels from the left of its container
1454      * @param y  an integer giving the component's new vertical position,
1455      *           measured in pixels from the bottom of its container
1456      * @param width  an integer giving the component's new width in pixels
1457      * @param height an integer giving the component's new height in pixels
1458      */
1459     @SuppressWarnings("deprecation")
reshape(int x, int y, int width, int height)1460     public void reshape(int x, int y, int width, int height) {
1461         super.reshape(x, y, width, height);
1462         validate();
1463         repaint();
1464     }
1465 
1466 ///////////////////////////
1467 // Frame/Window equivalents
1468 ///////////////////////////
1469 
1470     /**
1471      * Adds the specified listener to receive internal
1472      * frame events from this internal frame.
1473      *
1474      * @param l the internal frame listener
1475      */
addInternalFrameListener(InternalFrameListener l)1476     public void addInternalFrameListener(InternalFrameListener l) {  // remind: sync ??
1477       listenerList.add(InternalFrameListener.class, l);
1478       // remind: needed?
1479       enableEvents(0);   // turn on the newEventsOnly flag in Component.
1480     }
1481 
1482     /**
1483      * Removes the specified internal frame listener so that it no longer
1484      * receives internal frame events from this internal frame.
1485      *
1486      * @param l the internal frame listener
1487      */
removeInternalFrameListener(InternalFrameListener l)1488     public void removeInternalFrameListener(InternalFrameListener l) {  // remind: sync??
1489       listenerList.remove(InternalFrameListener.class, l);
1490     }
1491 
1492     /**
1493      * Returns an array of all the <code>InternalFrameListener</code>s added
1494      * to this <code>JInternalFrame</code> with
1495      * <code>addInternalFrameListener</code>.
1496      *
1497      * @return all of the <code>InternalFrameListener</code>s added or an empty
1498      *         array if no listeners have been added
1499      * @since 1.4
1500      *
1501      * @see #addInternalFrameListener
1502      */
1503     @BeanProperty(bound = false)
getInternalFrameListeners()1504     public InternalFrameListener[] getInternalFrameListeners() {
1505         return listenerList.getListeners(InternalFrameListener.class);
1506     }
1507 
1508     // remind: name ok? all one method ok? need to be synchronized?
1509     /**
1510      * Fires an internal frame event.
1511      *
1512      * @param id  the type of the event being fired; one of the following:
1513      * <ul>
1514      * <li><code>InternalFrameEvent.INTERNAL_FRAME_OPENED</code>
1515      * <li><code>InternalFrameEvent.INTERNAL_FRAME_CLOSING</code>
1516      * <li><code>InternalFrameEvent.INTERNAL_FRAME_CLOSED</code>
1517      * <li><code>InternalFrameEvent.INTERNAL_FRAME_ICONIFIED</code>
1518      * <li><code>InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED</code>
1519      * <li><code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code>
1520      * <li><code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code>
1521      * </ul>
1522      * If the event type is not one of the above, nothing happens.
1523      */
fireInternalFrameEvent(int id)1524     protected void fireInternalFrameEvent(int id){
1525       Object[] listeners = listenerList.getListenerList();
1526       InternalFrameEvent e = null;
1527       for (int i = listeners.length -2; i >=0; i -= 2){
1528         if (listeners[i] == InternalFrameListener.class){
1529           if (e == null){
1530             e = new InternalFrameEvent(this, id);
1531             //      System.out.println("InternalFrameEvent: " + e.paramString());
1532           }
1533           switch(e.getID()) {
1534           case InternalFrameEvent.INTERNAL_FRAME_OPENED:
1535             ((InternalFrameListener)listeners[i+1]).internalFrameOpened(e);
1536             break;
1537           case InternalFrameEvent.INTERNAL_FRAME_CLOSING:
1538             ((InternalFrameListener)listeners[i+1]).internalFrameClosing(e);
1539             break;
1540           case InternalFrameEvent.INTERNAL_FRAME_CLOSED:
1541             ((InternalFrameListener)listeners[i+1]).internalFrameClosed(e);
1542             break;
1543           case InternalFrameEvent.INTERNAL_FRAME_ICONIFIED:
1544             ((InternalFrameListener)listeners[i+1]).internalFrameIconified(e);
1545             break;
1546           case InternalFrameEvent.INTERNAL_FRAME_DEICONIFIED:
1547             ((InternalFrameListener)listeners[i+1]).internalFrameDeiconified(e);
1548             break;
1549           case InternalFrameEvent.INTERNAL_FRAME_ACTIVATED:
1550             ((InternalFrameListener)listeners[i+1]).internalFrameActivated(e);
1551             break;
1552           case InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED:
1553             ((InternalFrameListener)listeners[i+1]).internalFrameDeactivated(e);
1554             break;
1555           default:
1556             break;
1557           }
1558         }
1559       }
1560       /* we could do it off the event, but at the moment, that's not how
1561          I'm implementing it */
1562       //      if (id == InternalFrameEvent.INTERNAL_FRAME_CLOSING) {
1563       //          doDefaultCloseAction();
1564       //      }
1565     }
1566 
1567     /**
1568      * Fires an
1569      * <code>INTERNAL_FRAME_CLOSING</code> event
1570      * and then performs the action specified by
1571      * the internal frame's default close operation.
1572      * This method is typically invoked by the
1573      * look-and-feel-implemented action handler
1574      * for the internal frame's close button.
1575      *
1576      * @since 1.3
1577      * @see #setDefaultCloseOperation
1578      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSING
1579      */
doDefaultCloseAction()1580     public void doDefaultCloseAction() {
1581         fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSING);
1582         switch(defaultCloseOperation) {
1583           case DO_NOTHING_ON_CLOSE:
1584             break;
1585           case HIDE_ON_CLOSE:
1586             setVisible(false);
1587             if (isSelected())
1588                 try {
1589                     setSelected(false);
1590                 } catch (PropertyVetoException pve) {}
1591 
1592             /* should this activate the next frame? that's really
1593                desktopmanager's policy... */
1594             break;
1595           case DISPOSE_ON_CLOSE:
1596               try {
1597                 fireVetoableChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
1598                                    Boolean.TRUE);
1599                 isClosed = true;
1600                 setVisible(false);
1601                 firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE,
1602                                    Boolean.TRUE);
1603                 dispose();
1604               } catch (PropertyVetoException pve) {}
1605               break;
1606           default:
1607               break;
1608         }
1609     }
1610 
1611     /**
1612      * Sets the operation that will happen by default when
1613      * the user initiates a "close" on this internal frame.
1614      * The possible choices are:
1615      * <br><br>
1616      * <dl>
1617      * <dt><code>DO_NOTHING_ON_CLOSE</code>
1618      * <dd> Do nothing.
1619      *      This requires the program to handle the operation
1620      *      in the <code>internalFrameClosing</code> method
1621      *      of a registered <code>InternalFrameListener</code> object.
1622      * <dt><code>HIDE_ON_CLOSE</code>
1623      * <dd> Automatically make the internal frame invisible.
1624      * <dt><code>DISPOSE_ON_CLOSE</code>
1625      * <dd> Automatically dispose of the internal frame.
1626      * </dl>
1627      * <p>
1628      * The default value is <code>DISPOSE_ON_CLOSE</code>.
1629      * Before performing the specified close operation,
1630      * the internal frame fires
1631      * an <code>INTERNAL_FRAME_CLOSING</code> event.
1632      *
1633      * @param operation one of the following constants defined in
1634      *                  <code>javax.swing.WindowConstants</code>
1635      *                  (an interface implemented by
1636      *                  <code>JInternalFrame</code>):
1637      *                  <code>DO_NOTHING_ON_CLOSE</code>,
1638      *                  <code>HIDE_ON_CLOSE</code>, or
1639      *                  <code>DISPOSE_ON_CLOSE</code>
1640      *
1641      * @see #addInternalFrameListener
1642      * @see #getDefaultCloseOperation
1643      * @see #setVisible
1644      * @see #dispose
1645      * @see InternalFrameEvent#INTERNAL_FRAME_CLOSING
1646      */
setDefaultCloseOperation(int operation)1647     public void setDefaultCloseOperation(int operation) {
1648         this.defaultCloseOperation = operation;
1649     }
1650 
1651    /**
1652     * Returns the default operation that occurs when the user
1653     * initiates a "close" on this internal frame.
1654     * @return the operation that will occur when the user closes the internal
1655     *         frame
1656     * @see #setDefaultCloseOperation
1657     */
getDefaultCloseOperation()1658     public int getDefaultCloseOperation() {
1659         return defaultCloseOperation;
1660     }
1661 
1662     /**
1663      * Causes subcomponents of this <code>JInternalFrame</code>
1664      * to be laid out at their preferred size.  Internal frames that are
1665      * iconized or maximized are first restored and then packed.  If the
1666      * internal frame is unable to be restored its state is not changed
1667      * and will not be packed.
1668      *
1669      * @see       java.awt.Window#pack
1670      */
pack()1671     public void pack() {
1672         try {
1673             if (isIcon()) {
1674                 setIcon(false);
1675             } else if (isMaximum()) {
1676                 setMaximum(false);
1677             }
1678         } catch(PropertyVetoException e) {
1679             return;
1680         }
1681         setSize(getPreferredSize());
1682         validate();
1683     }
1684 
1685     /**
1686      * If the internal frame is not visible,
1687      * brings the internal frame to the front,
1688      * makes it visible,
1689      * and attempts to select it.
1690      * The first time the internal frame is made visible,
1691      * this method also fires an <code>INTERNAL_FRAME_OPENED</code> event.
1692      * This method does nothing if the internal frame is already visible.
1693      * Invoking this method
1694      * has the same result as invoking
1695      * <code>setVisible(true)</code>.
1696      *
1697      * @see #moveToFront
1698      * @see #setSelected
1699      * @see InternalFrameEvent#INTERNAL_FRAME_OPENED
1700      * @see #setVisible
1701      */
1702     @SuppressWarnings("deprecation")
show()1703     public void show() {
1704         // bug 4312922
1705         if (isVisible()) {
1706             //match the behavior of setVisible(true): do nothing
1707             return;
1708         }
1709 
1710         // bug 4149505
1711         if (!opened) {
1712           fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_OPENED);
1713           opened = true;
1714         }
1715 
1716         /* icon default visibility is false; set it to true so that it shows
1717            up when user iconifies frame */
1718         getDesktopIcon().setVisible(true);
1719 
1720         toFront();
1721         super.show();
1722 
1723         if (isIcon) {
1724             return;
1725         }
1726 
1727         if (!isSelected()) {
1728             try {
1729                 setSelected(true);
1730             } catch (PropertyVetoException pve) {}
1731         }
1732     }
1733 
1734     @SuppressWarnings("deprecation")
hide()1735     public void hide() {
1736         if (isIcon()) {
1737             getDesktopIcon().setVisible(false);
1738         }
1739         super.hide();
1740     }
1741 
1742     /**
1743      * Makes this internal frame
1744      * invisible, unselected, and closed.
1745      * If the frame is not already closed,
1746      * this method fires an
1747      * <code>INTERNAL_FRAME_CLOSED</code> event.
1748      * The results of invoking this method are similar to
1749      * <code>setClosed(true)</code>,
1750      * but <code>dispose</code> always succeeds in closing
1751      * the internal frame and does not fire
1752      * an <code>INTERNAL_FRAME_CLOSING</code> event.
1753      *
1754      * @see javax.swing.event.InternalFrameEvent#INTERNAL_FRAME_CLOSED
1755      * @see #setVisible
1756      * @see #setSelected
1757      * @see #setClosed
1758      */
dispose()1759     public void dispose() {
1760         if (isVisible()) {
1761             setVisible(false);
1762         }
1763         if (!isClosed) {
1764           firePropertyChange(IS_CLOSED_PROPERTY, Boolean.FALSE, Boolean.TRUE);
1765           isClosed = true;
1766         }
1767         fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_CLOSED);
1768         try {
1769             java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(
1770                     new sun.awt.UngrabEvent(this));
1771         } catch (SecurityException e) {
1772             this.dispatchEvent(new sun.awt.UngrabEvent(this));
1773         }
1774     }
1775 
1776     /**
1777      * Brings this internal frame to the front.
1778      * Places this internal frame  at the top of the stacking order
1779      * and makes the corresponding adjustment to other visible internal
1780      * frames.
1781      *
1782      * @see       java.awt.Window#toFront
1783      * @see       #moveToFront
1784      */
toFront()1785     public void toFront() {
1786         moveToFront();
1787     }
1788 
1789     /**
1790      * Sends this internal frame to the back.
1791      * Places this internal frame at the bottom of the stacking order
1792      * and makes the corresponding adjustment to other visible
1793      * internal frames.
1794      *
1795      * @see       java.awt.Window#toBack
1796      * @see       #moveToBack
1797      */
toBack()1798     public void toBack() {
1799         moveToBack();
1800     }
1801 
1802     /**
1803      * Does nothing because <code>JInternalFrame</code>s must always be roots of a focus
1804      * traversal cycle.
1805      *
1806      * @param focusCycleRoot this value is ignored
1807      * @see #isFocusCycleRoot
1808      * @see java.awt.Container#setFocusTraversalPolicy
1809      * @see java.awt.Container#getFocusTraversalPolicy
1810      * @since 1.4
1811      */
setFocusCycleRoot(boolean focusCycleRoot)1812     public final void setFocusCycleRoot(boolean focusCycleRoot) {
1813     }
1814 
1815     /**
1816      * Always returns <code>true</code> because all <code>JInternalFrame</code>s must be
1817      * roots of a focus traversal cycle.
1818      *
1819      * @return <code>true</code>
1820      * @see #setFocusCycleRoot
1821      * @see java.awt.Container#setFocusTraversalPolicy
1822      * @see java.awt.Container#getFocusTraversalPolicy
1823      * @since 1.4
1824      */
isFocusCycleRoot()1825     public final boolean isFocusCycleRoot() {
1826         return true;
1827     }
1828 
1829     /**
1830      * Always returns <code>null</code> because <code>JInternalFrame</code>s
1831      * must always be roots of a focus
1832      * traversal cycle.
1833      *
1834      * @return <code>null</code>
1835      * @see java.awt.Container#isFocusCycleRoot()
1836      * @since 1.4
1837      */
1838     @BeanProperty(bound = false)
getFocusCycleRootAncestor()1839     public final Container getFocusCycleRootAncestor() {
1840         return null;
1841     }
1842 
1843     /**
1844      * Gets the warning string that is displayed with this internal frame.
1845      * Since an internal frame is always secure (since it's fully
1846      * contained within a window that might need a warning string)
1847      * this method always returns <code>null</code>.
1848      * @return    <code>null</code>
1849      * @see       java.awt.Window#getWarningString
1850      */
1851     @BeanProperty(bound = false)
getWarningString()1852     public final String getWarningString() {
1853         return null;
1854     }
1855 
1856     /**
1857      * See <code>readObject</code> and <code>writeObject</code>
1858      * in <code>JComponent</code> for more
1859      * information about serialization in Swing.
1860      */
writeObject(ObjectOutputStream s)1861     private void writeObject(ObjectOutputStream s) throws IOException {
1862         s.defaultWriteObject();
1863         if (getUIClassID().equals(uiClassID)) {
1864             byte count = JComponent.getWriteObjCounter(this);
1865             JComponent.setWriteObjCounter(this, --count);
1866             if (count == 0 && ui != null) {
1867                 boolean old = isRootPaneCheckingEnabled();
1868                 try {
1869                     setRootPaneCheckingEnabled(false);
1870                     ui.installUI(this);
1871                 } finally {
1872                     setRootPaneCheckingEnabled(old);
1873                 }
1874             }
1875         }
1876     }
1877 
1878     /* Called from the JComponent's EnableSerializationFocusListener to
1879      * do any Swing-specific pre-serialization configuration.
1880      */
compWriteObjectNotify()1881     void compWriteObjectNotify() {
1882       // need to disable rootpane checking for InternalFrame: 4172083
1883       boolean old = isRootPaneCheckingEnabled();
1884       try {
1885         setRootPaneCheckingEnabled(false);
1886         super.compWriteObjectNotify();
1887       }
1888       finally {
1889         setRootPaneCheckingEnabled(old);
1890       }
1891     }
1892 
1893     /**
1894      * Returns a string representation of this <code>JInternalFrame</code>.
1895      * This method
1896      * is intended to be used only for debugging purposes, and the
1897      * content and format of the returned string may vary between
1898      * implementations. The returned string may be empty but may not
1899      * be <code>null</code>.
1900      *
1901      * @return  a string representation of this <code>JInternalFrame</code>
1902      */
paramString()1903     protected String paramString() {
1904         String rootPaneString = (rootPane != null ?
1905                                  rootPane.toString() : "");
1906         String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ?
1907                                                 "true" : "false");
1908         String closableString = (closable ? "true" : "false");
1909         String isClosedString = (isClosed ? "true" : "false");
1910         String maximizableString = (maximizable ? "true" : "false");
1911         String isMaximumString = (isMaximum ? "true" : "false");
1912         String iconableString = (iconable ? "true" : "false");
1913         String isIconString = (isIcon ? "true" : "false");
1914         String resizableString = (resizable ? "true" : "false");
1915         String isSelectedString = (isSelected ? "true" : "false");
1916         String frameIconString = (frameIcon != null ?
1917                                   frameIcon.toString() : "");
1918         String titleString = (title != null ?
1919                               title : "");
1920         String desktopIconString = (desktopIcon != null ?
1921                                     desktopIcon.toString() : "");
1922         String openedString = (opened ? "true" : "false");
1923         String defaultCloseOperationString;
1924         if (defaultCloseOperation == HIDE_ON_CLOSE) {
1925             defaultCloseOperationString = "HIDE_ON_CLOSE";
1926         } else if (defaultCloseOperation == DISPOSE_ON_CLOSE) {
1927             defaultCloseOperationString = "DISPOSE_ON_CLOSE";
1928         } else if (defaultCloseOperation == DO_NOTHING_ON_CLOSE) {
1929             defaultCloseOperationString = "DO_NOTHING_ON_CLOSE";
1930         } else defaultCloseOperationString = "";
1931 
1932         return super.paramString() +
1933         ",closable=" + closableString +
1934         ",defaultCloseOperation=" + defaultCloseOperationString +
1935         ",desktopIcon=" + desktopIconString +
1936         ",frameIcon=" + frameIconString +
1937         ",iconable=" + iconableString +
1938         ",isClosed=" + isClosedString +
1939         ",isIcon=" + isIconString +
1940         ",isMaximum=" + isMaximumString +
1941         ",isSelected=" + isSelectedString +
1942         ",maximizable=" + maximizableString +
1943         ",opened=" + openedString +
1944         ",resizable=" + resizableString +
1945         ",rootPane=" + rootPaneString +
1946         ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString +
1947         ",title=" + titleString;
1948     }
1949 
1950     // ======= begin optimized frame dragging defence code ==============
1951 
1952     boolean isDragging = false;
1953     boolean danger = false;
1954 
1955     /**
1956      * Overridden to allow optimized painting when the
1957      * internal frame is being dragged.
1958      */
paintComponent(Graphics g)1959     protected void paintComponent(Graphics g) {
1960       if (isDragging) {
1961         //         System.out.println("ouch");
1962          danger = true;
1963       }
1964 
1965       super.paintComponent(g);
1966    }
1967 
1968     // ======= end optimized frame dragging defence code ==============
1969 
1970 /////////////////
1971 // Accessibility support
1972 ////////////////
1973 
1974     /**
1975      * Gets the <code>AccessibleContext</code> associated with this
1976      * <code>JInternalFrame</code>.
1977      * For internal frames, the <code>AccessibleContext</code>
1978      * takes the form of an
1979      * <code>AccessibleJInternalFrame</code> object.
1980      * A new <code>AccessibleJInternalFrame</code> instance is created if necessary.
1981      *
1982      * @return an <code>AccessibleJInternalFrame</code> that serves as the
1983      *         <code>AccessibleContext</code> of this
1984      *         <code>JInternalFrame</code>
1985      * @see AccessibleJInternalFrame
1986      */
1987     @BeanProperty(bound = false)
getAccessibleContext()1988     public AccessibleContext getAccessibleContext() {
1989         if (accessibleContext == null) {
1990             accessibleContext = new AccessibleJInternalFrame();
1991         }
1992         return accessibleContext;
1993     }
1994 
1995     /**
1996      * This class implements accessibility support for the
1997      * <code>JInternalFrame</code> class.  It provides an implementation of the
1998      * Java Accessibility API appropriate to internal frame user-interface
1999      * elements.
2000      * <p>
2001      * <strong>Warning:</strong>
2002      * Serialized objects of this class will not be compatible with
2003      * future Swing releases. The current serialization support is
2004      * appropriate for short term storage or RMI between applications running
2005      * the same version of Swing.  As of 1.4, support for long term storage
2006      * of all JavaBeans&trade;
2007      * has been added to the <code>java.beans</code> package.
2008      * Please see {@link java.beans.XMLEncoder}.
2009      */
2010     @SuppressWarnings("serial") // Same-version serialization only
2011     protected class AccessibleJInternalFrame extends AccessibleJComponent
2012         implements AccessibleValue {
2013 
2014         /**
2015          * Get the accessible name of this object.
2016          *
2017          * @return the localized name of the object -- can be <code>null</code> if this
2018          * object does not have a name
2019          * @see #setAccessibleName
2020          */
getAccessibleName()2021         public String getAccessibleName() {
2022             String name = accessibleName;
2023 
2024             if (name == null) {
2025                 name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
2026             }
2027             if (name == null) {
2028                 name = getTitle();
2029             }
2030             return name;
2031         }
2032 
2033         /**
2034          * Get the role of this object.
2035          *
2036          * @return an instance of AccessibleRole describing the role of the
2037          * object
2038          * @see AccessibleRole
2039          */
getAccessibleRole()2040         public AccessibleRole getAccessibleRole() {
2041             return AccessibleRole.INTERNAL_FRAME;
2042         }
2043 
2044         /**
2045          * Gets the AccessibleValue associated with this object.  In the
2046          * implementation of the Java Accessibility API for this class,
2047          * returns this object, which is responsible for implementing the
2048          * <code>AccessibleValue</code> interface on behalf of itself.
2049          *
2050          * @return this object
2051          */
getAccessibleValue()2052         public AccessibleValue getAccessibleValue() {
2053             return this;
2054         }
2055 
2056 
2057         //
2058         // AccessibleValue methods
2059         //
2060 
2061         /**
2062          * Get the value of this object as a Number.
2063          *
2064          * @return value of the object -- can be <code>null</code> if this object does not
2065          * have a value
2066          */
getCurrentAccessibleValue()2067         public Number getCurrentAccessibleValue() {
2068             return Integer.valueOf(getLayer());
2069         }
2070 
2071         /**
2072          * Set the value of this object as a Number.
2073          *
2074          * @return <code>true</code> if the value was set
2075          */
setCurrentAccessibleValue(Number n)2076         public boolean setCurrentAccessibleValue(Number n) {
2077             // TIGER - 4422535
2078             if (n == null) {
2079                 return false;
2080             }
2081             setLayer(Integer.valueOf(n.intValue()));
2082             return true;
2083         }
2084 
2085         /**
2086          * Get the minimum value of this object as a Number.
2087          *
2088          * @return Minimum value of the object; <code>null</code> if this object does not
2089          * have a minimum value
2090          */
getMinimumAccessibleValue()2091         public Number getMinimumAccessibleValue() {
2092             return Integer.MIN_VALUE;
2093         }
2094 
2095         /**
2096          * Get the maximum value of this object as a Number.
2097          *
2098          * @return Maximum value of the object; <code>null</code> if this object does not
2099          * have a maximum value
2100          */
getMaximumAccessibleValue()2101         public Number getMaximumAccessibleValue() {
2102             return Integer.MAX_VALUE;
2103         }
2104 
2105     } // AccessibleJInternalFrame
2106 
2107     /**
2108      * This component represents an iconified version of a
2109      * <code>JInternalFrame</code>.
2110      * This API should NOT BE USED by Swing applications, as it will go
2111      * away in future versions of Swing as its functionality is moved into
2112      * <code>JInternalFrame</code>.  This class is public only so that
2113      * UI objects can display a desktop icon.  If an application
2114      * wants to display a desktop icon, it should create a
2115      * <code>JInternalFrame</code> instance and iconify it.
2116      * <p>
2117      * <strong>Warning:</strong>
2118      * Serialized objects of this class will not be compatible with
2119      * future Swing releases. The current serialization support is
2120      * appropriate for short term storage or RMI between applications running
2121      * the same version of Swing.  As of 1.4, support for long term storage
2122      * of all JavaBeans&trade;
2123      * has been added to the <code>java.beans</code> package.
2124      * Please see {@link java.beans.XMLEncoder}.
2125      *
2126      * @author David Kloba
2127      */
2128     @SuppressWarnings("serial") // Same-version serialization only
2129     public static class JDesktopIcon extends JComponent implements Accessible
2130     {
2131         JInternalFrame internalFrame;
2132 
2133         /**
2134          * Creates an icon for an internal frame.
2135          *
2136          * @param f  the <code>JInternalFrame</code>
2137          *              for which the icon is created
2138          */
JDesktopIcon(JInternalFrame f)2139         public JDesktopIcon(JInternalFrame f) {
2140             setVisible(false);
2141             setInternalFrame(f);
2142             updateUI();
2143         }
2144 
2145         /**
2146          * Returns the look-and-feel object that renders this component.
2147          *
2148          * @return the <code>DesktopIconUI</code> object that renders
2149          *              this component
2150          */
getUI()2151         public DesktopIconUI getUI() {
2152             return (DesktopIconUI)ui;
2153         }
2154 
2155         /**
2156          * Sets the look-and-feel object that renders this component.
2157          *
2158          * @param ui  the <code>DesktopIconUI</code> look-and-feel object
2159          * @see UIDefaults#getUI
2160          */
setUI(DesktopIconUI ui)2161         public void setUI(DesktopIconUI ui) {
2162             super.setUI(ui);
2163         }
2164 
2165         /**
2166          * Returns the <code>JInternalFrame</code> that this
2167          * <code>DesktopIcon</code> is associated with.
2168          *
2169          * @return the <code>JInternalFrame</code> with which this icon
2170          *              is associated
2171          */
getInternalFrame()2172         public JInternalFrame getInternalFrame() {
2173             return internalFrame;
2174         }
2175 
2176         /**
2177          * Sets the <code>JInternalFrame</code> with which this
2178          * <code>DesktopIcon</code> is associated.
2179          *
2180          * @param f  the <code>JInternalFrame</code> with which this icon
2181          *              is associated
2182          */
setInternalFrame(JInternalFrame f)2183         public void setInternalFrame(JInternalFrame f) {
2184             internalFrame = f;
2185         }
2186 
2187         /**
2188          * Convenience method to ask the icon for the <code>Desktop</code>
2189          * object it belongs to.
2190          *
2191          * @return the <code>JDesktopPane</code> that contains this
2192          *           icon's internal frame, or <code>null</code> if none found
2193          */
getDesktopPane()2194         public JDesktopPane getDesktopPane() {
2195             if(getInternalFrame() != null)
2196                 return getInternalFrame().getDesktopPane();
2197             return null;
2198         }
2199 
2200         /**
2201          * Notification from the <code>UIManager</code> that the look and feel
2202          * has changed.
2203          * Replaces the current UI object with the latest version from the
2204          * <code>UIManager</code>.
2205          *
2206          * @see JComponent#updateUI
2207          */
updateUI()2208         public void updateUI() {
2209             boolean hadUI = (ui != null);
2210             setUI((DesktopIconUI)UIManager.getUI(this));
2211             invalidate();
2212 
2213             Dimension r = getPreferredSize();
2214             setSize(r.width, r.height);
2215 
2216 
2217             if (internalFrame != null && internalFrame.getUI() != null) {  // don't do this if UI not created yet
2218                 SwingUtilities.updateComponentTreeUI(internalFrame);
2219             }
2220         }
2221 
2222         /* This method is called if updateUI was called on the associated
2223          * JInternalFrame.  It's necessary to avoid infinite recursion.
2224          */
updateUIWhenHidden()2225         void updateUIWhenHidden() {
2226             /* Update this UI and any associated internal frame */
2227             setUI((DesktopIconUI)UIManager.getUI(this));
2228 
2229             Dimension r = getPreferredSize();
2230             setSize(r.width, r.height);
2231 
2232             invalidate();
2233             Component[] children = getComponents();
2234             if (children != null) {
2235                 for (Component child : children) {
2236                     SwingUtilities.updateComponentTreeUI(child);
2237                 }
2238             }
2239         }
2240 
2241         /**
2242          * Returns the name of the look-and-feel
2243          * class that renders this component.
2244          *
2245          * @return the string "DesktopIconUI"
2246          * @see JComponent#getUIClassID
2247          * @see UIDefaults#getUI
2248          */
getUIClassID()2249         public String getUIClassID() {
2250             return "DesktopIconUI";
2251         }
2252         ////////////////
2253         // Serialization support
2254         ////////////////
writeObject(ObjectOutputStream s)2255         private void writeObject(ObjectOutputStream s) throws IOException {
2256             s.defaultWriteObject();
2257             if (getUIClassID().equals("DesktopIconUI")) {
2258                 byte count = JComponent.getWriteObjCounter(this);
2259                 JComponent.setWriteObjCounter(this, --count);
2260                 if (count == 0 && ui != null) {
2261                     ui.installUI(this);
2262                 }
2263             }
2264         }
2265 
2266        /////////////////
2267        // Accessibility support
2268        ////////////////
2269 
2270         /**
2271          * Gets the AccessibleContext associated with this JDesktopIcon.
2272          * For desktop icons, the AccessibleContext takes the form of an
2273          * AccessibleJDesktopIcon.
2274          * A new AccessibleJDesktopIcon instance is created if necessary.
2275          *
2276          * @return an AccessibleJDesktopIcon that serves as the
2277          *         AccessibleContext of this JDesktopIcon
2278          */
getAccessibleContext()2279         public AccessibleContext getAccessibleContext() {
2280             if (accessibleContext == null) {
2281                 accessibleContext = new AccessibleJDesktopIcon();
2282             }
2283             return accessibleContext;
2284         }
2285 
2286         /**
2287          * This class implements accessibility support for the
2288          * <code>JInternalFrame.JDesktopIcon</code> class.  It provides an
2289          * implementation of the Java Accessibility API appropriate to
2290          * desktop icon user-interface elements.
2291          * <p>
2292          * <strong>Warning:</strong>
2293          * Serialized objects of this class will not be compatible with
2294          * future Swing releases. The current serialization support is
2295          * appropriate for short term storage or RMI between applications running
2296          * the same version of Swing.  As of 1.4, support for long term storage
2297          * of all JavaBeans&trade;
2298          * has been added to the <code>java.beans</code> package.
2299          * Please see {@link java.beans.XMLEncoder}.
2300          */
2301         @SuppressWarnings("serial") // Same-version serialization only
2302         protected class AccessibleJDesktopIcon extends AccessibleJComponent
2303             implements AccessibleValue {
2304 
2305             /**
2306              * Gets the role of this object.
2307              *
2308              * @return an instance of AccessibleRole describing the role of the
2309              * object
2310              * @see AccessibleRole
2311              */
getAccessibleRole()2312             public AccessibleRole getAccessibleRole() {
2313                 return AccessibleRole.DESKTOP_ICON;
2314             }
2315 
2316             /**
2317              * Gets the AccessibleValue associated with this object.  In the
2318              * implementation of the Java Accessibility API for this class,
2319              * returns this object, which is responsible for implementing the
2320              * <code>AccessibleValue</code> interface on behalf of itself.
2321              *
2322              * @return this object
2323              */
getAccessibleValue()2324             public AccessibleValue getAccessibleValue() {
2325                 return this;
2326             }
2327 
2328             //
2329             // AccessibleValue methods
2330             //
2331 
2332             /**
2333              * Gets the value of this object as a <code>Number</code>.
2334              *
2335              * @return value of the object -- can be <code>null</code> if this object does not
2336              * have a value
2337              */
getCurrentAccessibleValue()2338             public Number getCurrentAccessibleValue() {
2339                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
2340                 AccessibleValue v = a.getAccessibleValue();
2341                 if (v != null) {
2342                     return v.getCurrentAccessibleValue();
2343                 } else {
2344                     return null;
2345                 }
2346             }
2347 
2348             /**
2349              * Sets the value of this object as a <code>Number</code>.
2350              *
2351              * @return <code>true</code> if the value was set
2352              */
setCurrentAccessibleValue(Number n)2353             public boolean setCurrentAccessibleValue(Number n) {
2354                 // TIGER - 4422535
2355                 if (n == null) {
2356                     return false;
2357                 }
2358                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
2359                 AccessibleValue v = a.getAccessibleValue();
2360                 if (v != null) {
2361                     return v.setCurrentAccessibleValue(n);
2362                 } else {
2363                     return false;
2364                 }
2365             }
2366 
2367             /**
2368              * Gets the minimum value of this object as a <code>Number</code>.
2369              *
2370              * @return minimum value of the object; <code>null</code> if this object does not
2371              * have a minimum value
2372              */
getMinimumAccessibleValue()2373             public Number getMinimumAccessibleValue() {
2374                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
2375                 if (a instanceof AccessibleValue) {
2376                     return ((AccessibleValue)a).getMinimumAccessibleValue();
2377                 } else {
2378                     return null;
2379                 }
2380             }
2381 
2382             /**
2383              * Gets the maximum value of this object as a <code>Number</code>.
2384              *
2385              * @return maximum value of the object; <code>null</code> if this object does not
2386              * have a maximum value
2387              */
getMaximumAccessibleValue()2388             public Number getMaximumAccessibleValue() {
2389                 AccessibleContext a = JDesktopIcon.this.getInternalFrame().getAccessibleContext();
2390                 if (a instanceof AccessibleValue) {
2391                     return ((AccessibleValue)a).getMaximumAccessibleValue();
2392                 } else {
2393                     return null;
2394                 }
2395             }
2396 
2397         } // AccessibleJDesktopIcon
2398     }
2399 }
2400