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