1/*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.swing.plaf.basic;
27
28import sun.swing.SwingUtilities2;
29import java.awt.*;
30import java.awt.event.*;
31import javax.accessibility.AccessibleContext;
32import javax.swing.*;
33import javax.swing.plaf.*;
34import javax.swing.event.InternalFrameEvent;
35import java.beans.PropertyChangeListener;
36import java.beans.PropertyChangeEvent;
37import java.beans.PropertyVetoException;
38import static java.awt.RenderingHints.KEY_TEXT_ANTIALIASING;
39import static java.awt.RenderingHints.KEY_TEXT_LCD_CONTRAST;
40
41import sun.swing.DefaultLookup;
42
43/**
44 * The class that manages a basic title bar
45 * <p>
46 * <strong>Warning:</strong>
47 * Serialized objects of this class will not be compatible with
48 * future Swing releases. The current serialization support is
49 * appropriate for short term storage or RMI between applications running
50 * the same version of Swing.  As of 1.4, support for long term storage
51 * of all JavaBeans&trade;
52 * has been added to the <code>java.beans</code> package.
53 * Please see {@link java.beans.XMLEncoder}.
54 *
55 * @author David Kloba
56 * @author Steve Wilson
57 */
58@SuppressWarnings("serial") // Same-version serialization only
59public class BasicInternalFrameTitlePane extends JComponent
60{
61    /**
62     * The instance of {@code JMenuBar}.
63     */
64    protected JMenuBar menuBar;
65    /**
66     * The iconify button.
67     */
68    protected JButton iconButton;
69    /**
70     * The maximize button.
71     */
72    protected JButton maxButton;
73    /**
74     * The close button.
75     */
76    protected JButton closeButton;
77
78    /**
79     * The instance of {@code JMenu}.
80     */
81    protected JMenu windowMenu;
82    /**
83     * The instance of {@code JInternalFrame}.
84     */
85    protected JInternalFrame frame;
86
87    /**
88     * The color of a selected title.
89     */
90    protected Color selectedTitleColor;
91    /**
92     * The color of a selected text.
93     */
94    protected Color selectedTextColor;
95    /**
96     * The color of a not selected title.
97     */
98    protected Color notSelectedTitleColor;
99    /**
100     * The color of a not selected text.
101     */
102    protected Color notSelectedTextColor;
103
104    /**
105     * The maximize icon.
106     */
107    protected Icon maxIcon;
108    /**
109     * The minimize icon.
110     */
111    protected Icon minIcon;
112    /**
113     * The iconify icon.
114     */
115    protected Icon iconIcon;
116    /**
117     * The close icon.
118     */
119    protected Icon closeIcon;
120
121    /**
122     * The instance of a {@code PropertyChangeListener}.
123     */
124    protected PropertyChangeListener propertyChangeListener;
125
126    /**
127     * The instance of a {@code CloseAction}.
128     */
129    protected Action closeAction;
130    /**
131     * The instance of a {@code MaximizeAction}.
132     */
133    protected Action maximizeAction;
134    /**
135     * The instance of an {@code IconifyAction}.
136     */
137    protected Action iconifyAction;
138    /**
139     * The instance of a {@code RestoreAction}.
140     */
141    protected Action restoreAction;
142    /**
143     * The instance of a {@code MoveAction}.
144     */
145    protected Action moveAction;
146    /**
147     * The instance of a {@code SizeAction}.
148     */
149    protected Action sizeAction;
150
151    // These constants are not used in JDK code
152    /**
153     * The close button text property.
154     */
155    protected static final String CLOSE_CMD =
156        UIManager.getString("InternalFrameTitlePane.closeButtonText");
157    /**
158     * The minimize button text property.
159     */
160    protected static final String ICONIFY_CMD =
161        UIManager.getString("InternalFrameTitlePane.minimizeButtonText");
162    /**
163     * The restore button text property.
164     */
165    protected static final String RESTORE_CMD =
166        UIManager.getString("InternalFrameTitlePane.restoreButtonText");
167    /**
168     * The maximize button text property.
169     */
170    protected static final String MAXIMIZE_CMD =
171        UIManager.getString("InternalFrameTitlePane.maximizeButtonText");
172    /**
173     * The move button text property.
174     */
175    protected static final String MOVE_CMD =
176        UIManager.getString("InternalFrameTitlePane.moveButtonText");
177    /**
178     * The size button text property.
179     */
180    protected static final String SIZE_CMD =
181        UIManager.getString("InternalFrameTitlePane.sizeButtonText");
182
183    private String closeButtonToolTip;
184    private String iconButtonToolTip;
185    private String restoreButtonToolTip;
186    private String maxButtonToolTip;
187    private Handler handler;
188
189    /**
190     * Constructs a new instance of {@code BasicInternalFrameTitlePane}.
191     *
192     * @param f an instance of {@code JInternalFrame}
193     */
194    public BasicInternalFrameTitlePane(JInternalFrame f) {
195        frame = f;
196        installTitlePane();
197    }
198
199    /**
200     * Installs the title pane.
201     */
202    protected void installTitlePane() {
203        installDefaults();
204        installListeners();
205
206        createActions();
207        enableActions();
208        createActionMap();
209
210        setLayout(createLayout());
211
212        assembleSystemMenu();
213        createButtons();
214        addSubComponents();
215
216        updateProperties();
217    }
218
219    private void updateProperties() {
220        putClientProperty(KEY_TEXT_ANTIALIASING,
221                frame.getClientProperty(KEY_TEXT_ANTIALIASING));
222        putClientProperty(KEY_TEXT_LCD_CONTRAST,
223                frame.getClientProperty(KEY_TEXT_LCD_CONTRAST));
224    }
225
226    /**
227     * Adds subcomponents.
228     */
229    protected void addSubComponents() {
230        add(menuBar);
231        add(iconButton);
232        add(maxButton);
233        add(closeButton);
234    }
235
236    /**
237     * Creates actions.
238     */
239    protected void createActions() {
240        maximizeAction = new MaximizeAction();
241        iconifyAction = new IconifyAction();
242        closeAction = new CloseAction();
243        restoreAction = new RestoreAction();
244        moveAction = new MoveAction();
245        sizeAction = new SizeAction();
246    }
247
248    ActionMap createActionMap() {
249        ActionMap map = new ActionMapUIResource();
250        map.put("showSystemMenu", new ShowSystemMenuAction(true));
251        map.put("hideSystemMenu", new ShowSystemMenuAction(false));
252        return map;
253    }
254
255    /**
256     * Registers listeners.
257     */
258    protected void installListeners() {
259        if( propertyChangeListener == null ) {
260            propertyChangeListener = createPropertyChangeListener();
261        }
262        frame.addPropertyChangeListener(propertyChangeListener);
263    }
264
265    /**
266     * Unregisters listeners.
267     */
268    protected void uninstallListeners() {
269        frame.removePropertyChangeListener(propertyChangeListener);
270        handler = null;
271    }
272
273    /**
274     * Installs default properties.
275     */
276    protected void installDefaults() {
277        maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
278        minIcon = UIManager.getIcon("InternalFrame.minimizeIcon");
279        iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon");
280        closeIcon = UIManager.getIcon("InternalFrame.closeIcon");
281
282        selectedTitleColor = UIManager.getColor("InternalFrame.activeTitleBackground");
283        selectedTextColor = UIManager.getColor("InternalFrame.activeTitleForeground");
284        notSelectedTitleColor = UIManager.getColor("InternalFrame.inactiveTitleBackground");
285        notSelectedTextColor = UIManager.getColor("InternalFrame.inactiveTitleForeground");
286        setFont(UIManager.getFont("InternalFrame.titleFont"));
287        closeButtonToolTip =
288                UIManager.getString("InternalFrame.closeButtonToolTip");
289        iconButtonToolTip =
290                UIManager.getString("InternalFrame.iconButtonToolTip");
291        restoreButtonToolTip =
292                UIManager.getString("InternalFrame.restoreButtonToolTip");
293        maxButtonToolTip =
294                UIManager.getString("InternalFrame.maxButtonToolTip");
295    }
296
297    /**
298     * Uninstalls default properties.
299     */
300    protected void uninstallDefaults() {
301    }
302
303    /**
304     * Creates buttons.
305     */
306    protected void createButtons() {
307        iconButton = new NoFocusButton(
308                     "InternalFrameTitlePane.iconifyButtonAccessibleName",
309                     "InternalFrameTitlePane.iconifyButtonOpacity");
310        iconButton.addActionListener(iconifyAction);
311        if (iconButtonToolTip != null && iconButtonToolTip.length() != 0) {
312            iconButton.setToolTipText(iconButtonToolTip);
313        }
314
315        maxButton = new NoFocusButton(
316                        "InternalFrameTitlePane.maximizeButtonAccessibleName",
317                        "InternalFrameTitlePane.maximizeButtonOpacity");
318        maxButton.addActionListener(maximizeAction);
319
320        closeButton = new NoFocusButton(
321                      "InternalFrameTitlePane.closeButtonAccessibleName",
322                      "InternalFrameTitlePane.closeButtonOpacity");
323        closeButton.addActionListener(closeAction);
324        if (closeButtonToolTip != null && closeButtonToolTip.length() != 0) {
325            closeButton.setToolTipText(closeButtonToolTip);
326        }
327
328        setButtonIcons();
329    }
330
331    /**
332     * Sets the button icons.
333     */
334    protected void setButtonIcons() {
335        if(frame.isIcon()) {
336            if (minIcon != null) {
337                iconButton.setIcon(minIcon);
338            }
339            if (restoreButtonToolTip != null &&
340                    restoreButtonToolTip.length() != 0) {
341                iconButton.setToolTipText(restoreButtonToolTip);
342            }
343            if (maxIcon != null) {
344                maxButton.setIcon(maxIcon);
345            }
346            if (maxButtonToolTip != null && maxButtonToolTip.length() != 0) {
347                maxButton.setToolTipText(maxButtonToolTip);
348            }
349        } else if (frame.isMaximum()) {
350            if (iconIcon != null) {
351                iconButton.setIcon(iconIcon);
352            }
353            if (iconButtonToolTip != null && iconButtonToolTip.length() != 0) {
354                iconButton.setToolTipText(iconButtonToolTip);
355            }
356            if (minIcon != null) {
357                maxButton.setIcon(minIcon);
358            }
359            if (restoreButtonToolTip != null &&
360                    restoreButtonToolTip.length() != 0) {
361                maxButton.setToolTipText(restoreButtonToolTip);
362            }
363        } else {
364            if (iconIcon != null) {
365                iconButton.setIcon(iconIcon);
366            }
367            if (iconButtonToolTip != null && iconButtonToolTip.length() != 0) {
368                iconButton.setToolTipText(iconButtonToolTip);
369            }
370            if (maxIcon != null) {
371                maxButton.setIcon(maxIcon);
372            }
373            if (maxButtonToolTip != null && maxButtonToolTip.length() != 0) {
374                maxButton.setToolTipText(maxButtonToolTip);
375            }
376        }
377        if (closeIcon != null) {
378            closeButton.setIcon(closeIcon);
379        }
380    }
381
382    /**
383     * Assembles system menu.
384     */
385    protected void assembleSystemMenu() {
386        menuBar = createSystemMenuBar();
387        windowMenu = createSystemMenu();
388        menuBar.add(windowMenu);
389        addSystemMenuItems(windowMenu);
390        enableActions();
391    }
392
393    /**
394     * Adds system menu items to {@code systemMenu}.
395     *
396     * @param systemMenu an instance of {@code JMenu}
397     */
398    protected void addSystemMenuItems(JMenu systemMenu) {
399        JMenuItem mi = systemMenu.add(restoreAction);
400        mi.setMnemonic(getButtonMnemonic("restore"));
401        mi = systemMenu.add(moveAction);
402        mi.setMnemonic(getButtonMnemonic("move"));
403        mi = systemMenu.add(sizeAction);
404        mi.setMnemonic(getButtonMnemonic("size"));
405        mi = systemMenu.add(iconifyAction);
406        mi.setMnemonic(getButtonMnemonic("minimize"));
407        mi = systemMenu.add(maximizeAction);
408        mi.setMnemonic(getButtonMnemonic("maximize"));
409        systemMenu.add(new JSeparator());
410        mi = systemMenu.add(closeAction);
411        mi.setMnemonic(getButtonMnemonic("close"));
412    }
413
414    private static int getButtonMnemonic(String button) {
415        try {
416            return Integer.parseInt(UIManager.getString(
417                    "InternalFrameTitlePane." + button + "Button.mnemonic"));
418        } catch (NumberFormatException e) {
419            return -1;
420        }
421    }
422
423    /**
424     * Returns a new instance of {@code JMenu}.
425     *
426     * @return a new instance of {@code JMenu}
427     */
428    protected JMenu createSystemMenu() {
429        return new JMenu("    ");
430    }
431
432    /**
433     * Returns a new instance of {@code JMenuBar}.
434     *
435     * @return a new instance of {@code JMenuBar}
436     */
437    protected JMenuBar createSystemMenuBar() {
438        menuBar = new SystemMenuBar();
439        menuBar.setBorderPainted(false);
440        return menuBar;
441    }
442
443    /**
444     * Shows system menu.
445     */
446    protected void showSystemMenu(){
447        //      windowMenu.setPopupMenuVisible(true);
448      //      windowMenu.setVisible(true);
449      windowMenu.doClick();
450    }
451
452    public void paintComponent(Graphics g)  {
453        paintTitleBackground(g);
454
455        if(frame.getTitle() != null) {
456            boolean isSelected = frame.isSelected();
457            Font f = g.getFont();
458            g.setFont(getFont());
459            if(isSelected)
460                g.setColor(selectedTextColor);
461            else
462                g.setColor(notSelectedTextColor);
463
464            // Center text vertically.
465            FontMetrics fm = SwingUtilities2.getFontMetrics(frame, g);
466            int baseline = (getHeight() + fm.getAscent() - fm.getLeading() -
467                    fm.getDescent()) / 2;
468
469            int titleX;
470            Rectangle r = new Rectangle(0, 0, 0, 0);
471            if (frame.isIconifiable())  r = iconButton.getBounds();
472            else if (frame.isMaximizable())  r = maxButton.getBounds();
473            else if (frame.isClosable())  r = closeButton.getBounds();
474            int titleW;
475
476            String title = frame.getTitle();
477            if( BasicGraphicsUtils.isLeftToRight(frame) ) {
478              if (r.x == 0)  r.x = frame.getWidth()-frame.getInsets().right;
479              titleX = menuBar.getX() + menuBar.getWidth() + 2;
480              titleW = r.x - titleX - 3;
481              title = getTitle(frame.getTitle(), fm, titleW);
482            } else {
483                titleX = menuBar.getX() - 2
484                         - SwingUtilities2.stringWidth(frame,fm,title);
485            }
486
487            SwingUtilities2.drawString(frame, g, title, titleX, baseline);
488            g.setFont(f);
489        }
490    }
491
492   /**
493    * Invoked from paintComponent.
494    * Paints the background of the titlepane.  All text and icons will
495    * then be rendered on top of this background.
496    * @param g the graphics to use to render the background
497    * @since 1.4
498    */
499    protected void paintTitleBackground(Graphics g) {
500        boolean isSelected = frame.isSelected();
501
502        if(isSelected)
503            g.setColor(selectedTitleColor);
504        else
505            g.setColor(notSelectedTitleColor);
506        g.fillRect(0, 0, getWidth(), getHeight());
507    }
508
509    /**
510     * Returns the title.
511     *
512     * @param text a text
513     * @param fm an instance of {@code FontMetrics}
514     * @param availTextWidth an available text width
515     * @return the title.
516     */
517    protected String getTitle(String text, FontMetrics fm, int availTextWidth) {
518        return SwingUtilities2.clipStringIfNecessary(
519                           frame, fm, text, availTextWidth);
520    }
521
522    /**
523     * Post a WINDOW_CLOSING-like event to the frame, so that it can
524     * be treated like a regular {@code Frame}.
525     *
526     * @param frame an instance of {@code JInternalFrame}
527     */
528    protected void postClosingEvent(JInternalFrame frame) {
529        InternalFrameEvent e = new InternalFrameEvent(
530            frame, InternalFrameEvent.INTERNAL_FRAME_CLOSING);
531        // Try posting event, unless there's a SecurityManager.
532        try {
533            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);
534        } catch (SecurityException se) {
535            frame.dispatchEvent(e);
536        }
537    }
538
539    /**
540     * Enables actions.
541     */
542    protected void enableActions() {
543        restoreAction.setEnabled(frame.isMaximum() || frame.isIcon());
544        maximizeAction.setEnabled(
545            (frame.isMaximizable() && !frame.isMaximum() && !frame.isIcon()) ||
546            (frame.isMaximizable() && frame.isIcon()));
547        iconifyAction.setEnabled(frame.isIconifiable() && !frame.isIcon());
548        closeAction.setEnabled(frame.isClosable());
549        sizeAction.setEnabled(false);
550        moveAction.setEnabled(false);
551    }
552
553    private Handler getHandler() {
554        if (handler == null) {
555            handler = new Handler();
556        }
557        return handler;
558    }
559
560    /**
561     * Returns an instance of {@code PropertyChangeListener}.
562     *
563     * @return an instance of {@code PropertyChangeListener}
564     */
565    protected PropertyChangeListener createPropertyChangeListener() {
566        return getHandler();
567    }
568
569    /**
570     * Returns a layout manager.
571     *
572     * @return a layout manager
573     */
574    protected LayoutManager createLayout() {
575        return getHandler();
576    }
577
578
579    private class Handler implements LayoutManager, PropertyChangeListener {
580        //
581        // PropertyChangeListener
582        //
583        public void propertyChange(PropertyChangeEvent evt) {
584            String prop = evt.getPropertyName();
585
586            if (prop == JInternalFrame.IS_SELECTED_PROPERTY) {
587                repaint();
588                return;
589            }
590
591            if (prop == JInternalFrame.IS_ICON_PROPERTY ||
592                    prop == JInternalFrame.IS_MAXIMUM_PROPERTY) {
593                setButtonIcons();
594                enableActions();
595                return;
596            }
597
598            if ("closable" == prop) {
599                if (evt.getNewValue() == Boolean.TRUE) {
600                    add(closeButton);
601                } else {
602                    remove(closeButton);
603                }
604            } else if ("maximizable" == prop) {
605                if (evt.getNewValue() == Boolean.TRUE) {
606                    add(maxButton);
607                } else {
608                    remove(maxButton);
609                }
610            } else if ("iconable" == prop) {
611                if (evt.getNewValue() == Boolean.TRUE) {
612                    add(iconButton);
613                } else {
614                    remove(iconButton);
615                }
616            }
617            enableActions();
618
619            revalidate();
620            repaint();
621        }
622
623
624        //
625        // LayoutManager
626        //
627        public void addLayoutComponent(String name, Component c) {}
628        public void removeLayoutComponent(Component c) {}
629        public Dimension preferredLayoutSize(Container c) {
630            return minimumLayoutSize(c);
631        }
632
633        public Dimension minimumLayoutSize(Container c) {
634            // Calculate width.
635            int width = 22;
636
637            if (frame.isClosable()) {
638                width += 19;
639            }
640            if (frame.isMaximizable()) {
641                width += 19;
642            }
643            if (frame.isIconifiable()) {
644                width += 19;
645            }
646
647            FontMetrics fm = frame.getFontMetrics(getFont());
648            String frameTitle = frame.getTitle();
649            int title_w = frameTitle != null ? SwingUtilities2.stringWidth(
650                               frame, fm, frameTitle) : 0;
651            int title_length = frameTitle != null ? frameTitle.length() : 0;
652
653            // Leave room for three characters in the title.
654            if (title_length > 3) {
655                int subtitle_w = SwingUtilities2.stringWidth(
656                    frame, fm, frameTitle.substring(0, 3) + "...");
657                width += (title_w < subtitle_w) ? title_w : subtitle_w;
658            } else {
659                width += title_w;
660            }
661
662            // Calculate height.
663            Icon icon = frame.getFrameIcon();
664            int fontHeight = fm.getHeight();
665            fontHeight += 2;
666            int iconHeight = 0;
667            if (icon != null) {
668                // SystemMenuBar forces the icon to be 16x16 or less.
669                iconHeight = Math.min(icon.getIconHeight(), 16);
670            }
671            iconHeight += 2;
672
673            int height = Math.max( fontHeight, iconHeight );
674
675            Dimension dim = new Dimension(width, height);
676
677            // Take into account the border insets if any.
678            if (getBorder() != null) {
679                Insets insets = getBorder().getBorderInsets(c);
680                dim.height += insets.top + insets.bottom;
681                dim.width += insets.left + insets.right;
682            }
683            return dim;
684        }
685
686        public void layoutContainer(Container c) {
687            boolean leftToRight = BasicGraphicsUtils.isLeftToRight(frame);
688
689            int w = getWidth();
690            int h = getHeight();
691            int x;
692
693            int buttonHeight = closeButton.getIcon().getIconHeight();
694
695            Icon icon = frame.getFrameIcon();
696            int iconHeight = 0;
697            if (icon != null) {
698                iconHeight = icon.getIconHeight();
699            }
700            x = (leftToRight) ? 2 : w - 16 - 2;
701            menuBar.setBounds(x, (h - iconHeight) / 2, 16, 16);
702
703            x = (leftToRight) ? w - 16 - 2 : 2;
704
705            if (frame.isClosable()) {
706                closeButton.setBounds(x, (h - buttonHeight) / 2, 16, 14);
707                x += (leftToRight) ? -(16 + 2) : 16 + 2;
708            }
709
710            if (frame.isMaximizable()) {
711                maxButton.setBounds(x, (h - buttonHeight) / 2, 16, 14);
712                x += (leftToRight) ? -(16 + 2) : 16 + 2;
713            }
714
715            if (frame.isIconifiable()) {
716                iconButton.setBounds(x, (h - buttonHeight) / 2, 16, 14);
717            }
718        }
719    }
720
721    /**
722     * This class should be treated as a &quot;protected&quot; inner class.
723     * Instantiate it only within subclasses of <code>Foo</code>.
724     */
725    public class PropertyChangeHandler implements PropertyChangeListener {
726        // NOTE: This class exists only for backward compatibility. All
727        // its functionality has been moved into Handler. If you need to add
728        // new functionality add it to the Handler, but make sure this
729        // class calls into the Handler.
730        public void propertyChange(PropertyChangeEvent evt) {
731            getHandler().propertyChange(evt);
732        }
733    }
734
735    /**
736     * This class should be treated as a &quot;protected&quot; inner class.
737     * Instantiate it only within subclasses of <code>Foo</code>.
738     */
739    public class TitlePaneLayout implements LayoutManager {
740        // NOTE: This class exists only for backward compatibility. All
741        // its functionality has been moved into Handler. If you need to add
742        // new functionality add it to the Handler, but make sure this
743        // class calls into the Handler.
744        public void addLayoutComponent(String name, Component c) {
745            getHandler().addLayoutComponent(name, c);
746        }
747
748        public void removeLayoutComponent(Component c) {
749            getHandler().removeLayoutComponent(c);
750        }
751
752        public Dimension preferredLayoutSize(Container c)  {
753            return getHandler().preferredLayoutSize(c);
754        }
755
756        public Dimension minimumLayoutSize(Container c) {
757            return getHandler().minimumLayoutSize(c);
758        }
759
760        public void layoutContainer(Container c) {
761            getHandler().layoutContainer(c);
762        }
763    }
764
765    /**
766     * This class should be treated as a &quot;protected&quot; inner class.
767     * Instantiate it only within subclasses of <code>Foo</code>.
768     */
769    public class CloseAction extends AbstractAction {
770        /**
771         * Constructs a new instance of a {@code CloseAction}.
772         */
773        public CloseAction() {
774            super(UIManager.getString(
775                    "InternalFrameTitlePane.closeButtonText"));
776        }
777
778        public void actionPerformed(ActionEvent e) {
779            if(frame.isClosable()) {
780                frame.doDefaultCloseAction();
781            }
782        }
783    } // end CloseAction
784
785    /**
786     * This class should be treated as a &quot;protected&quot; inner class.
787     * Instantiate it only within subclasses of <code>Foo</code>.
788     */
789    public class MaximizeAction extends AbstractAction {
790        /**
791         * Constructs a new instance of a {@code MaximizeAction}.
792         */
793        public MaximizeAction() {
794            super(UIManager.getString(
795                    "InternalFrameTitlePane.maximizeButtonText"));
796        }
797
798        public void actionPerformed(ActionEvent evt) {
799            if (frame.isMaximizable()) {
800                if (frame.isMaximum() && frame.isIcon()) {
801                    try {
802                        frame.setIcon(false);
803                    } catch (PropertyVetoException e) { }
804                } else if (!frame.isMaximum()) {
805                    try {
806                        frame.setMaximum(true);
807                    } catch (PropertyVetoException e) { }
808                } else {
809                    try {
810                        frame.setMaximum(false);
811                    } catch (PropertyVetoException e) { }
812                }
813            }
814        }
815    }
816
817    /**
818     * This class should be treated as a &quot;protected&quot; inner class.
819     * Instantiate it only within subclasses of <code>Foo</code>.
820     */
821    public class IconifyAction extends AbstractAction {
822        /**
823         * Constructs a new instance of an {@code IconifyAction}.
824         */
825        public IconifyAction() {
826            super(UIManager.getString(
827                    "InternalFrameTitlePane.minimizeButtonText"));
828        }
829
830        public void actionPerformed(ActionEvent e) {
831            if(frame.isIconifiable()) {
832              if(!frame.isIcon()) {
833                try { frame.setIcon(true); } catch (PropertyVetoException e1) { }
834              } else{
835                try { frame.setIcon(false); } catch (PropertyVetoException e1) { }
836              }
837            }
838        }
839    } // end IconifyAction
840
841    /**
842     * This class should be treated as a &quot;protected&quot; inner class.
843     * Instantiate it only within subclasses of <code>Foo</code>.
844     */
845    public class RestoreAction extends AbstractAction {
846        /**
847         * Constructs a new instance of a {@code RestoreAction}.
848         */
849        public RestoreAction() {
850            super(UIManager.getString(
851                    "InternalFrameTitlePane.restoreButtonText"));
852        }
853
854        public void actionPerformed(ActionEvent evt) {
855            if (frame.isMaximizable() && frame.isMaximum() && frame.isIcon()) {
856                try {
857                    frame.setIcon(false);
858                } catch (PropertyVetoException e) { }
859            } else if (frame.isMaximizable() && frame.isMaximum()) {
860                try {
861                    frame.setMaximum(false);
862                } catch (PropertyVetoException e) { }
863            } else if (frame.isIconifiable() && frame.isIcon()) {
864                try {
865                    frame.setIcon(false);
866                } catch (PropertyVetoException e) { }
867            }
868        }
869    }
870
871    /**
872     * This class should be treated as a &quot;protected&quot; inner class.
873     * Instantiate it only within subclasses of <code>Foo</code>.
874     */
875    public class MoveAction extends AbstractAction {
876        /**
877         * Constructs a new instance of a {@code MoveAction}.
878         */
879        public MoveAction() {
880            super(UIManager.getString(
881                    "InternalFrameTitlePane.moveButtonText"));
882        }
883
884        public void actionPerformed(ActionEvent e) {
885            // This action is currently undefined
886        }
887    } // end MoveAction
888
889    /*
890     * Handles showing and hiding the system menu.
891     */
892    private class ShowSystemMenuAction extends AbstractAction {
893        private boolean show;   // whether to show the menu
894
895        public ShowSystemMenuAction(boolean show) {
896            this.show = show;
897        }
898
899        public void actionPerformed(ActionEvent e) {
900            if (show) {
901                windowMenu.doClick();
902            } else {
903                windowMenu.setVisible(false);
904            }
905        }
906    }
907
908    /**
909     * This class should be treated as a &quot;protected&quot; inner class.
910     * Instantiate it only within subclasses of <code>Foo</code>.
911     */
912    public class SizeAction extends AbstractAction {
913        /**
914         * Constructs a new instance of a {@code SizeAction}.
915         */
916        public SizeAction() {
917            super(UIManager.getString(
918                    "InternalFrameTitlePane.sizeButtonText"));
919        }
920
921        public void actionPerformed(ActionEvent e) {
922            // This action is currently undefined
923        }
924    } // end SizeAction
925
926
927    /**
928     * This class should be treated as a &quot;protected&quot; inner class.
929     * Instantiate it only within subclasses of <code>Foo</code>.
930     */
931    @SuppressWarnings("deprecation")
932    public class SystemMenuBar extends JMenuBar {
933        public boolean isFocusTraversable() { return false; }
934        public void requestFocus() {}
935        public void paint(Graphics g) {
936            Icon icon = frame.getFrameIcon();
937            if (icon == null) {
938              icon = (Icon)DefaultLookup.get(frame, frame.getUI(),
939                      "InternalFrame.icon");
940            }
941            if (icon != null) {
942                // Resize to 16x16 if necessary.
943                if (icon instanceof ImageIcon && (icon.getIconWidth() > 16 || icon.getIconHeight() > 16)) {
944                    Image img = ((ImageIcon)icon).getImage();
945                    ((ImageIcon)icon).setImage(img.getScaledInstance(16, 16, Image.SCALE_SMOOTH));
946                }
947                icon.paintIcon(this, g, 0, 0);
948            }
949        }
950
951        public boolean isOpaque() {
952            return true;
953        }
954    } // end SystemMenuBar
955
956
957    private class NoFocusButton extends JButton {
958        private String uiKey;
959        public NoFocusButton(String uiKey, String opacityKey) {
960            setFocusPainted(false);
961            setMargin(new Insets(0,0,0,0));
962            this.uiKey = uiKey;
963
964            Object opacity = UIManager.get(opacityKey);
965            if (opacity instanceof Boolean) {
966                setOpaque(((Boolean)opacity).booleanValue());
967            }
968        }
969        @SuppressWarnings("deprecation")
970        public boolean isFocusTraversable() { return false; }
971        public void requestFocus() {}
972        public AccessibleContext getAccessibleContext() {
973            AccessibleContext ac = super.getAccessibleContext();
974            if (uiKey != null) {
975                ac.setAccessibleName(UIManager.getString(uiKey));
976                uiKey = null;
977            }
978            return ac;
979        }
980    }  // end NoFocusButton
981
982}   // End Title Pane Class
983