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
26package javax.swing;
27
28import java.awt.*;
29
30import java.beans.PropertyVetoException;
31import java.beans.PropertyChangeEvent;
32
33import javax.swing.event.InternalFrameEvent;
34import javax.swing.event.InternalFrameListener;
35import javax.swing.plaf.*;
36
37import javax.accessibility.*;
38
39import java.io.ObjectOutputStream;
40import java.io.IOException;
41import java.lang.StringBuilder;
42import java.beans.PropertyChangeListener;
43import sun.awt.AppContext;
44import 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 */
112public 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}