History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/JInternalFrame.java (1 of 18352 files). Show all

Unified · Split

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