KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > plaf > metal > MetalTitlePane


1 /*
2  * @(#)MetalTitlePane.java 1.17 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.swing.plaf.metal;
9
10 import com.sun.java.swing.SwingUtilities2;
11 import java.awt.*;
12 import java.awt.event.*;
13 import java.beans.*;
14 import javax.swing.*;
15 import javax.swing.border.*;
16 import javax.swing.event.InternalFrameEvent JavaDoc;
17 import javax.swing.plaf.*;
18 import javax.swing.plaf.basic.*;
19 import java.util.Locale JavaDoc;
20
21
22 /**
23  * Class that manages a JLF awt.Window-descendant class's title bar.
24  * <p>
25  * This class assumes it will be created with a particular window
26  * decoration style, and that if the style changes, a new one will
27  * be created.
28  *
29  * @version 1.17 12/19/03
30  * @author Terry Kellerman
31  * @since 1.4
32  */

33 class MetalTitlePane extends JComponent {
34     private static final Border handyEmptyBorder = new EmptyBorder(0,0,0,0);
35     private static final int IMAGE_HEIGHT = 16;
36     private static final int IMAGE_WIDTH = 16;
37
38     /**
39      * PropertyChangeListener added to the JRootPane.
40      */

41     private PropertyChangeListener propertyChangeListener;
42
43     /**
44      * JMenuBar, typically renders the system menu items.
45      */

46     private JMenuBar menuBar;
47     /**
48      * Action used to close the Window.
49      */

50     private Action closeAction;
51
52     /**
53      * Action used to iconify the Frame.
54      */

55     private Action iconifyAction;
56
57     /**
58      * Action to restore the Frame size.
59      */

60     private Action restoreAction;
61
62     /**
63      * Action to restore the Frame size.
64      */

65     private Action maximizeAction;
66
67     /**
68      * Button used to maximize or restore the Frame.
69      */

70     private JButton toggleButton;
71
72     /**
73      * Button used to maximize or restore the Frame.
74      */

75     private JButton iconifyButton;
76
77     /**
78      * Button used to maximize or restore the Frame.
79      */

80     private JButton closeButton;
81
82     /**
83      * Icon used for toggleButton when window is normal size.
84      */

85     private Icon maximizeIcon;
86
87     /**
88      * Icon used for toggleButton when window is maximized.
89      */

90     private Icon minimizeIcon;
91
92     /**
93      * Listens for changes in the state of the Window listener to update
94      * the state of the widgets.
95      */

96     private WindowListener windowListener;
97
98     /**
99      * Window we're currently in.
100      */

101     private Window window;
102
103     /**
104      * JRootPane rendering for.
105      */

106     private JRootPane rootPane;
107
108     /**
109      * Room remaining in title for bumps.
110      */

111     private int buttonsWidth;
112
113     /**
114      * Buffered Frame.state property. As state isn't bound, this is kept
115      * to determine when to avoid updating widgets.
116      */

117     private int state;
118
119     /**
120      * MetalRootPaneUI that created us.
121      */

122     private MetalRootPaneUI JavaDoc rootPaneUI;
123     
124
125     // Colors
126
private Color inactiveBackground = UIManager.getColor("inactiveCaption");
127     private Color inactiveForeground = UIManager.getColor("inactiveCaptionText");
128     private Color inactiveShadow = UIManager.getColor("inactiveCaptionBorder");
129     private Color activeBumpsHighlight = MetalLookAndFeel.getPrimaryControlHighlight();
130     private Color activeBumpsShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
131     private Color activeBackground = null;
132     private Color activeForeground = null;
133     private Color activeShadow = null;
134
135     // Bumps
136
private MetalBumps JavaDoc activeBumps
137         = new MetalBumps JavaDoc( 0, 0,
138                           activeBumpsHighlight,
139                           activeBumpsShadow,
140                           MetalLookAndFeel.getPrimaryControl() );
141     private MetalBumps JavaDoc inactiveBumps
142         = new MetalBumps JavaDoc( 0, 0,
143                           MetalLookAndFeel.getControlHighlight(),
144                           MetalLookAndFeel.getControlDarkShadow(),
145                           MetalLookAndFeel.getControl() );
146
147
148     public MetalTitlePane(JRootPane root, MetalRootPaneUI JavaDoc ui) {
149         this.rootPane = root;
150         rootPaneUI = ui;
151
152         state = -1;
153
154         installSubcomponents();
155         determineColors();
156         installDefaults();
157
158         setLayout(createLayout());
159     }
160
161     /**
162      * Uninstalls the necessary state.
163      */

164     private void uninstall() {
165         uninstallListeners();
166         window = null;
167         removeAll();
168     }
169
170     /**
171      * Installs the necessary listeners.
172      */

173     private void installListeners() {
174         if (window != null) {
175             windowListener = createWindowListener();
176             window.addWindowListener(windowListener);
177             propertyChangeListener = createWindowPropertyChangeListener();
178             window.addPropertyChangeListener(propertyChangeListener);
179         }
180     }
181
182     /**
183      * Uninstalls the necessary listeners.
184      */

185     private void uninstallListeners() {
186         if (window != null) {
187             window.removeWindowListener(windowListener);
188             window.removePropertyChangeListener(propertyChangeListener);
189         }
190     }
191
192     /**
193      * Returns the <code>WindowListener</code> to add to the
194      * <code>Window</code>.
195      */

196     private WindowListener createWindowListener() {
197         return new WindowHandler();
198     }
199
200     /**
201      * Returns the <code>PropertyChangeListener</code> to install on
202      * the <code>Window</code>.
203      */

204     private PropertyChangeListener createWindowPropertyChangeListener() {
205         return new PropertyChangeHandler();
206     }
207
208     /**
209      * Returns the <code>JRootPane</code> this was created for.
210      */

211     public JRootPane getRootPane() {
212         return rootPane;
213     }
214
215     /**
216      * Returns the decoration style of the <code>JRootPane</code>.
217      */

218     private int getWindowDecorationStyle() {
219         return getRootPane().getWindowDecorationStyle();
220     }
221
222     public void addNotify() {
223         super.addNotify();
224
225         uninstallListeners();
226
227         window = SwingUtilities.getWindowAncestor(this);
228         if (window != null) {
229             if (window instanceof Frame) {
230                 setState(((Frame)window).getExtendedState());
231             }
232             else {
233                 setState(0);
234             }
235             setActive(window.isActive());
236             installListeners();
237         }
238     }
239
240     public void removeNotify() {
241         super.removeNotify();
242
243         uninstallListeners();
244         window = null;
245     }
246
247     /**
248      * Adds any sub-Components contained in the <code>MetalTitlePane</code>.
249      */

250     private void installSubcomponents() {
251         int decorationStyle = getWindowDecorationStyle();
252         if (decorationStyle == JRootPane.FRAME) {
253             createActions();
254             menuBar = createMenuBar();
255             add(menuBar);
256             createButtons();
257             add(iconifyButton);
258             add(toggleButton);
259             add(closeButton);
260         } else if (decorationStyle == JRootPane.PLAIN_DIALOG ||
261                 decorationStyle == JRootPane.INFORMATION_DIALOG ||
262                 decorationStyle == JRootPane.ERROR_DIALOG ||
263                 decorationStyle == JRootPane.COLOR_CHOOSER_DIALOG ||
264                 decorationStyle == JRootPane.FILE_CHOOSER_DIALOG ||
265                 decorationStyle == JRootPane.QUESTION_DIALOG ||
266                 decorationStyle == JRootPane.WARNING_DIALOG) {
267             createActions();
268             createButtons();
269             add(closeButton);
270         }
271     }
272
273     /**
274      * Determines the Colors to draw with.
275      */

276     private void determineColors() {
277         switch (getWindowDecorationStyle()) {
278         case JRootPane.FRAME:
279             activeBackground = UIManager.getColor("activeCaption");
280             activeForeground = UIManager.getColor("activeCaptionText");
281             activeShadow = UIManager.getColor("activeCaptionBorder");
282             break;
283         case JRootPane.ERROR_DIALOG:
284             activeBackground = UIManager.getColor(
285                 "OptionPane.errorDialog.titlePane.background");
286             activeForeground = UIManager.getColor(
287                 "OptionPane.errorDialog.titlePane.foreground");
288             activeShadow = UIManager.getColor(
289                 "OptionPane.errorDialog.titlePane.shadow");
290             break;
291         case JRootPane.QUESTION_DIALOG:
292         case JRootPane.COLOR_CHOOSER_DIALOG:
293         case JRootPane.FILE_CHOOSER_DIALOG:
294             activeBackground = UIManager.getColor(
295                 "OptionPane.questionDialog.titlePane.background");
296             activeForeground = UIManager.getColor(
297                 "OptionPane.questionDialog.titlePane.foreground");
298             activeShadow = UIManager.getColor(
299                 "OptionPane.questionDialog.titlePane.shadow");
300             break;
301         case JRootPane.WARNING_DIALOG:
302             activeBackground = UIManager.getColor(
303                 "OptionPane.warningDialog.titlePane.background");
304             activeForeground = UIManager.getColor(
305                 "OptionPane.warningDialog.titlePane.foreground");
306             activeShadow = UIManager.getColor(
307                 "OptionPane.warningDialog.titlePane.shadow");
308             break;
309         case JRootPane.PLAIN_DIALOG:
310         case JRootPane.INFORMATION_DIALOG:
311         default:
312             activeBackground = UIManager.getColor("activeCaption");
313             activeForeground = UIManager.getColor("activeCaptionText");
314             activeShadow = UIManager.getColor("activeCaptionBorder");
315             break;
316         }
317         activeBumps.setBumpColors(activeBumpsHighlight, activeBumpsShadow,
318                                   activeBackground);
319     }
320
321     /**
322      * Installs the fonts and necessary properties on the MetalTitlePane.
323      */

324     private void installDefaults() {
325         setFont(UIManager.getFont("InternalFrame.titleFont", getLocale()));
326     }
327     
328     /**
329      * Uninstalls any previously installed UI values.
330      */

331     private void uninstallDefaults() {
332     }
333
334     /**
335      * Returns the <code>JMenuBar</code> displaying the appropriate
336      * system menu items.
337      */

338     protected JMenuBar createMenuBar() {
339         menuBar = new SystemMenuBar();
340         menuBar.setFocusable(false);
341         menuBar.setBorderPainted(true);
342         menuBar.add(createMenu());
343         return menuBar;
344     }
345
346     /**
347      * Closes the Window.
348      */

349     private void close() {
350         Window window = getWindow();
351
352         if (window != null) {
353             window.dispatchEvent(new WindowEvent(
354                                  window, WindowEvent.WINDOW_CLOSING));
355         }
356     }
357
358     /**
359      * Iconifies the Frame.
360      */

361     private void iconify() {
362         Frame frame = getFrame();
363         if (frame != null) {
364             frame.setExtendedState(state | Frame.ICONIFIED);
365         }
366     }
367
368     /**
369      * Maximizes the Frame.
370      */

371     private void maximize() {
372         Frame frame = getFrame();
373         if (frame != null) {
374             frame.setExtendedState(state | Frame.MAXIMIZED_BOTH);
375         }
376     }
377
378     /**
379      * Restores the Frame size.
380      */

381     private void restore() {
382         Frame frame = getFrame();
383
384         if (frame == null) {
385             return;
386         }
387
388         if ((state & Frame.ICONIFIED) != 0) {
389             frame.setExtendedState(state & ~Frame.ICONIFIED);
390         } else {
391             frame.setExtendedState(state & ~Frame.MAXIMIZED_BOTH);
392         }
393     }
394
395     /**
396      * Create the <code>Action</code>s that get associated with the
397      * buttons and menu items.
398      */

399     private void createActions() {
400         closeAction = new CloseAction();
401         if (getWindowDecorationStyle() == JRootPane.FRAME) {
402             iconifyAction = new IconifyAction();
403             restoreAction = new RestoreAction();
404             maximizeAction = new MaximizeAction();
405         }
406     }
407
408     /**
409      * Returns the <code>JMenu</code> displaying the appropriate menu items
410      * for manipulating the Frame.
411      */

412     private JMenu createMenu() {
413         JMenu menu = new JMenu("");
414         if (getWindowDecorationStyle() == JRootPane.FRAME) {
415             addMenuItems(menu);
416         }
417         return menu;
418     }
419
420     /**
421      * Adds the necessary <code>JMenuItem</code>s to the passed in menu.
422      */

423     private void addMenuItems(JMenu menu) {
424         Locale JavaDoc locale = getRootPane().getLocale();
425         JMenuItem mi = menu.add(restoreAction);
426         int mnemonic = MetalUtils.getInt("MetalTitlePane.restoreMnemonic", -1);
427
428         if (mnemonic != -1) {
429             mi.setMnemonic(mnemonic);
430         }
431
432         mi = menu.add(iconifyAction);
433         mnemonic = MetalUtils.getInt("MetalTitlePane.iconifyMnemonic", -1);
434         if (mnemonic != -1) {
435             mi.setMnemonic(mnemonic);
436         }
437
438         if (Toolkit.getDefaultToolkit().isFrameStateSupported(
439                 Frame.MAXIMIZED_BOTH)) {
440             mi = menu.add(maximizeAction);
441             mnemonic =
442                 MetalUtils.getInt("MetalTitlePane.maximizeMnemonic", -1);
443             if (mnemonic != -1) {
444                 mi.setMnemonic(mnemonic);
445             }
446         }
447
448         menu.add(new JSeparator());
449
450         mi = menu.add(closeAction);
451         mnemonic = MetalUtils.getInt("MetalTitlePane.closeMnemonic", -1);
452         if (mnemonic != -1) {
453             mi.setMnemonic(mnemonic);
454         }
455     }
456
457     /**
458      * Returns a <code>JButton</code> appropriate for placement on the
459      * TitlePane.
460      */

461     private JButton createTitleButton() {
462         JButton button = new JButton();
463
464         button.setFocusPainted(false);
465         button.setFocusable(false);
466         button.setOpaque(true);
467         return button;
468     }
469
470     /**
471      * Creates the Buttons that will be placed on the TitlePane.
472      */

473     private void createButtons() {
474         closeButton = createTitleButton();
475         closeButton.setAction(closeAction);
476         closeButton.setText(null);
477         closeButton.putClientProperty("paintActive", Boolean.TRUE);
478         closeButton.setBorder(handyEmptyBorder);
479         closeButton.getAccessibleContext().setAccessibleName("Close");
480         closeButton.setIcon(UIManager.getIcon("InternalFrame.closeIcon"));
481
482         if (getWindowDecorationStyle() == JRootPane.FRAME) {
483             maximizeIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
484             minimizeIcon = UIManager.getIcon("InternalFrame.minimizeIcon");
485
486             iconifyButton = createTitleButton();
487             iconifyButton.setAction(iconifyAction);
488             iconifyButton.setText(null);
489             iconifyButton.putClientProperty("paintActive", Boolean.TRUE);
490             iconifyButton.setBorder(handyEmptyBorder);
491             iconifyButton.getAccessibleContext().setAccessibleName("Iconify");
492             iconifyButton.setIcon(UIManager.getIcon("InternalFrame.iconifyIcon"));
493
494             toggleButton = createTitleButton();
495             toggleButton.setAction(restoreAction);
496             toggleButton.putClientProperty("paintActive", Boolean.TRUE);
497             toggleButton.setBorder(handyEmptyBorder);
498             toggleButton.getAccessibleContext().setAccessibleName("Maximize");
499             toggleButton.setIcon(maximizeIcon);
500         }
501     }
502
503     /**
504      * Returns the <code>LayoutManager</code> that should be installed on
505      * the <code>MetalTitlePane</code>.
506      */

507     private LayoutManager createLayout() {
508         return new TitlePaneLayout();
509     }
510
511     /**
512      * Updates state dependant upon the Window's active state.
513      */

514     private void setActive(boolean isActive) {
515         Boolean JavaDoc activeB = isActive ? Boolean.TRUE : Boolean.FALSE;
516
517         closeButton.putClientProperty("paintActive", activeB);
518         if (getWindowDecorationStyle() == JRootPane.FRAME) {
519             iconifyButton.putClientProperty("paintActive", activeB);
520             toggleButton.putClientProperty("paintActive", activeB);
521         }
522         // Repaint the whole thing as the Borders that are used have
523
// different colors for active vs inactive
524
getRootPane().repaint();
525     }
526
527     /**
528      * Sets the state of the Window.
529      */

530     private void setState(int state) {
531         setState(state, false);
532     }
533
534     /**
535      * Sets the state of the window. If <code>updateRegardless</code> is
536      * true and the state has not changed, this will update anyway.
537      */

538     private void setState(int state, boolean updateRegardless) {
539         Window w = getWindow();
540
541         if (w != null && getWindowDecorationStyle() == JRootPane.FRAME) {
542             if (this.state == state && !updateRegardless) {
543                 return;
544             }
545             Frame frame = getFrame();
546
547             if (frame != null) {
548                 JRootPane rootPane = getRootPane();
549
550                 if (((state & Frame.MAXIMIZED_BOTH) != 0) &&
551                         (rootPane.getBorder() == null ||
552                         (rootPane.getBorder() instanceof UIResource)) &&
553                             frame.isShowing()) {
554                     rootPane.setBorder(null);
555                 }
556                 else if ((state & Frame.MAXIMIZED_BOTH) == 0) {
557                     // This is a croak, if state becomes bound, this can
558
// be nuked.
559
rootPaneUI.installBorder(rootPane);
560                 }
561                 if (frame.isResizable()) {
562                     if ((state & Frame.MAXIMIZED_BOTH) != 0) {
563                         updateToggleButton(restoreAction, minimizeIcon);
564                         maximizeAction.setEnabled(false);
565                         restoreAction.setEnabled(true);
566                     }
567                     else {
568                         updateToggleButton(maximizeAction, maximizeIcon);
569                         maximizeAction.setEnabled(true);
570                         restoreAction.setEnabled(false);
571                     }
572                     if (toggleButton.getParent() == null ||
573                         iconifyButton.getParent() == null) {
574                         add(toggleButton);
575                         add(iconifyButton);
576                         revalidate();
577                         repaint();
578                     }
579                     toggleButton.setText(null);
580                 }
581                 else {
582                     maximizeAction.setEnabled(false);
583                     restoreAction.setEnabled(false);
584                     if (toggleButton.getParent() != null) {
585                         remove(toggleButton);
586                         revalidate();
587                         repaint();
588                     }
589                 }
590             }
591             else {
592                 // Not contained in a Frame
593
maximizeAction.setEnabled(false);
594                 restoreAction.setEnabled(false);
595                 iconifyAction.setEnabled(false);
596                 remove(toggleButton);
597                 remove(iconifyButton);
598                 revalidate();
599                 repaint();
600             }
601             closeAction.setEnabled(true);
602             this.state = state;
603         }
604     }
605
606     /**
607      * Updates the toggle button to contain the Icon <code>icon</code>, and
608      * Action <code>action</code>.
609      */

610     private void updateToggleButton(Action action, Icon icon) {
611         toggleButton.setAction(action);
612         toggleButton.setIcon(icon);
613         toggleButton.setText(null);
614     }
615
616     /**
617      * Returns the Frame rendering in. This will return null if the
618      * <code>JRootPane</code> is not contained in a <code>Frame</code>.
619      */

620     private Frame getFrame() {
621         Window window = getWindow();
622
623         if (window instanceof Frame) {
624             return (Frame)window;
625         }
626         return null;
627     }
628
629     /**
630      * Returns the <code>Window</code> the <code>JRootPane</code> is
631      * contained in. This will return null if there is no parent ancestor
632      * of the <code>JRootPane</code>.
633      */

634     private Window getWindow() {
635         return window;
636     }
637
638     /**
639      * Returns the String to display as the title.
640      */

641     private String JavaDoc getTitle() {
642         Window w = getWindow();
643
644         if (w instanceof Frame) {
645             return ((Frame)w).getTitle();
646         }
647         else if (w instanceof Dialog) {
648             return ((Dialog)w).getTitle();
649         }
650         return null;
651     }
652
653     /**
654      * Renders the TitlePane.
655      */

656     public void paintComponent(Graphics g) {
657         // As state isn't bound, we need a convenience place to check
658
// if it has changed. Changing the state typically changes the
659
if (getFrame() != null) {
660             setState(getFrame().getExtendedState());
661         }
662         JRootPane rootPane = getRootPane();
663         Window window = getWindow();
664         boolean leftToRight = (window == null) ?
665                                rootPane.getComponentOrientation().isLeftToRight() :
666                                window.getComponentOrientation().isLeftToRight();
667         boolean isSelected = (window == null) ? true : window.isActive();
668         int width = getWidth();
669         int height = getHeight();
670
671         Color background;
672         Color foreground;
673         Color darkShadow;
674
675         MetalBumps JavaDoc bumps;
676
677         if (isSelected) {
678             background = activeBackground;
679             foreground = activeForeground;
680             darkShadow = activeShadow;
681             bumps = activeBumps;
682         } else {
683             background = inactiveBackground;
684             foreground = inactiveForeground;
685             darkShadow = inactiveShadow;
686             bumps = inactiveBumps;
687         }
688
689         g.setColor(background);
690         g.fillRect(0, 0, width, height);
691
692         g.setColor( darkShadow );
693         g.drawLine ( 0, height - 1, width, height -1);
694         g.drawLine ( 0, 0, 0 ,0);
695         g.drawLine ( width - 1, 0 , width -1, 0);
696
697         int xOffset = leftToRight ? 5 : width - 5;
698
699         if (getWindowDecorationStyle() == JRootPane.FRAME) {
700             xOffset += leftToRight ? IMAGE_WIDTH + 5 : - IMAGE_WIDTH - 5;
701         }
702         
703         String JavaDoc theTitle = getTitle();
704         if (theTitle != null) {
705             FontMetrics fm = SwingUtilities2.getFontMetrics(rootPane, g);
706
707             g.setColor(foreground);
708
709             int yOffset = ( (height - fm.getHeight() ) / 2 ) + fm.getAscent();
710
711             Rectangle rect = new Rectangle(0, 0, 0, 0);
712             if (iconifyButton != null && iconifyButton.getParent() != null) {
713                 rect = iconifyButton.getBounds();
714             }
715             int titleW;
716
717             if( leftToRight ) {
718                 if (rect.x == 0) {
719                     rect.x = window.getWidth() - window.getInsets().right-2;
720                 }
721                 titleW = rect.x - xOffset - 4;
722                 theTitle = SwingUtilities2.clipStringIfNecessary(
723                                 rootPane, fm, theTitle, titleW);
724             } else {
725                 titleW = xOffset - rect.x - rect.width - 4;
726                 theTitle = SwingUtilities2.clipStringIfNecessary(
727                                 rootPane, fm, theTitle, titleW);
728                 xOffset -= SwingUtilities2.stringWidth(rootPane, fm,
729                                                        theTitle);
730             }
731             int titleLength = SwingUtilities2.stringWidth(rootPane, fm,
732                                                           theTitle);
733             SwingUtilities2.drawString(rootPane, g, theTitle, xOffset,
734                                        yOffset );
735             xOffset += leftToRight ? titleLength + 5 : -5;
736         }
737   
738         int bumpXOffset;
739         int bumpLength;
740         if( leftToRight ) {
741             bumpLength = width - buttonsWidth - xOffset - 5;
742             bumpXOffset = xOffset;
743         } else {
744             bumpLength = xOffset - buttonsWidth - 5;
745             bumpXOffset = buttonsWidth + 5;
746         }
747         int bumpYOffset = 3;
748         int bumpHeight = getHeight() - (2 * bumpYOffset);
749         bumps.setBumpArea( bumpLength, bumpHeight );
750         bumps.paintIcon(this, g, bumpXOffset, bumpYOffset);
751     }
752
753     /**
754      * Actions used to <code>close</code> the <code>Window</code>.
755      */

756     private class CloseAction extends AbstractAction {
757         public CloseAction() {
758             super(UIManager.getString("MetalTitlePane.closeTitle",
759                                       getLocale()));
760         }
761
762         public void actionPerformed(ActionEvent e) {
763             close();
764         }
765     }
766
767
768     /**
769      * Actions used to <code>iconfiy</code> the <code>Frame</code>.
770      */

771     private class IconifyAction extends AbstractAction {
772         public IconifyAction() {
773             super(UIManager.getString("MetalTitlePane.iconifyTitle",
774                                       getLocale()));
775         }
776
777         public void actionPerformed(ActionEvent e) {
778             iconify();
779         }
780     }
781
782
783     /**
784      * Actions used to <code>restore</code> the <code>Frame</code>.
785      */

786     private class RestoreAction extends AbstractAction {
787         public RestoreAction() {
788             super(UIManager.getString
789                   ("MetalTitlePane.restoreTitle", getLocale()));
790         }
791
792         public void actionPerformed(ActionEvent e) {
793             restore();
794         }
795     }
796
797
798     /**
799      * Actions used to <code>restore</code> the <code>Frame</code>.
800      */

801     private class MaximizeAction extends AbstractAction {
802         public MaximizeAction() {
803             super(UIManager.getString("MetalTitlePane.maximizeTitle",
804                                       getLocale()));
805         }
806
807         public void actionPerformed(ActionEvent e) {
808             maximize();
809         }
810     }
811
812
813     /**
814      * Class responsible for drawing the system menu. Looks up the
815      * image to draw from the Frame associated with the
816      * <code>JRootPane</code>.
817      */

818     private class SystemMenuBar extends JMenuBar {
819         public void paint(Graphics g) {
820             Frame frame = getFrame();
821
822             if (isOpaque()) {
823                 g.setColor(getBackground());
824                 g.fillRect(0, 0, getWidth(), getHeight());
825             }
826             Image image = (frame != null) ? frame.getIconImage() : null;
827
828             if (image != null) {
829                 g.drawImage(image, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null);
830             } else {
831                 Icon icon = UIManager.getIcon("InternalFrame.icon");
832
833                 if (icon != null) {
834                     icon.paintIcon(this, g, 0, 0);
835                 }
836             }
837         }
838         public Dimension getMinimumSize() {
839             return getPreferredSize();
840         }
841         public Dimension getPreferredSize() {
842             Dimension size = super.getPreferredSize();
843
844             return new Dimension(Math.max(IMAGE_WIDTH, size.width),
845                                  Math.max(size.height, IMAGE_HEIGHT));
846         }
847     }
848
849     private class TitlePaneLayout implements LayoutManager {
850         public void addLayoutComponent(String JavaDoc name, Component c) {}
851         public void removeLayoutComponent(Component c) {}
852         public Dimension preferredLayoutSize(Container c) {
853             int height = computeHeight();
854             return new Dimension(height, height);
855         }
856         
857         public Dimension minimumLayoutSize(Container c) {
858             return preferredLayoutSize(c);
859         }
860     
861         private int computeHeight() {
862             FontMetrics fm = rootPane.getFontMetrics(getFont());
863             int fontHeight = fm.getHeight();
864             fontHeight += 7;
865             int iconHeight = 0;
866             if (getWindowDecorationStyle() == JRootPane.FRAME) {
867                 iconHeight = IMAGE_HEIGHT;
868             }
869
870             int finalHeight = Math.max( fontHeight, iconHeight );
871             return finalHeight;
872         }
873                     
874         public void layoutContainer(Container c) {
875             boolean leftToRight = (window == null) ?
876                 getRootPane().getComponentOrientation().isLeftToRight() :
877                 window.getComponentOrientation().isLeftToRight();
878
879             int w = getWidth();
880             int x;
881             int y = 3;
882             int spacing;
883             int buttonHeight;
884             int buttonWidth;
885             
886             if (closeButton != null && closeButton.getIcon() != null) {
887                 buttonHeight = closeButton.getIcon().getIconHeight();
888                 buttonWidth = closeButton.getIcon().getIconWidth();
889             }
890             else {
891                 buttonHeight = IMAGE_HEIGHT;
892                 buttonWidth = IMAGE_WIDTH;
893             }
894             
895             // assumes all buttons have the same dimensions
896
// these dimensions include the borders
897

898             x = leftToRight ? w : 0;
899
900             spacing = 5;
901             x = leftToRight ? spacing : w - buttonWidth - spacing;
902             if (menuBar != null) {
903                 menuBar.setBounds(x, y, buttonWidth, buttonHeight);
904             }
905
906             x = leftToRight ? w : 0;
907             spacing = 4;
908             x += leftToRight ? -spacing -buttonWidth : spacing;
909             if (closeButton != null) {
910                 closeButton.setBounds(x, y, buttonWidth, buttonHeight);
911             }
912
913             if( !leftToRight ) x += buttonWidth;
914
915             if (getWindowDecorationStyle() == JRootPane.FRAME) {
916                 if (Toolkit.getDefaultToolkit().isFrameStateSupported(
917                         Frame.MAXIMIZED_BOTH)) {
918                     if (toggleButton.getParent() != null) {
919                         spacing = 10;
920                         x += leftToRight ? -spacing -buttonWidth : spacing;
921                         toggleButton.setBounds(x, y, buttonWidth, buttonHeight);
922                         if (!leftToRight) {
923                             x += buttonWidth;
924                         }
925                     }
926                 }
927
928                 if (iconifyButton != null && iconifyButton.getParent() != null) {
929                     spacing = 2;
930                     x += leftToRight ? -spacing -buttonWidth : spacing;
931                     iconifyButton.setBounds(x, y, buttonWidth, buttonHeight);
932                     if (!leftToRight) {
933                         x += buttonWidth;
934                     }
935                 }
936             }
937             buttonsWidth = leftToRight ? w - x : x;
938         }
939     }
940
941
942
943     /**
944      * PropertyChangeListener installed on the Window. Updates the necessary
945      * state as the state of the Window changes.
946      */

947     private class PropertyChangeHandler implements PropertyChangeListener {
948         public void propertyChange(PropertyChangeEvent pce) {
949             String JavaDoc name = pce.getPropertyName();
950
951             // Frame.state isn't currently bound.
952
if ("resizable".equals(name) || "state".equals(name)) {
953                 Frame frame = getFrame();
954
955                 if (frame != null) {
956                     setState(frame.getExtendedState(), true);
957                 }
958                 if ("resizable".equals(name)) {
959                     getRootPane().repaint();
960                 }
961             }
962             else if ("title".equals(name)) {
963                 repaint();
964             }
965             else if ("componentOrientation".equals(name) ||
966                      "iconImage".equals(name)) {
967                 revalidate();
968                 repaint();
969             }
970         }
971     }
972
973
974     /**
975      * WindowListener installed on the Window, updates the state as necessary.
976      */

977     private class WindowHandler extends WindowAdapter {
978         public void windowActivated(WindowEvent ev) {
979             setActive(true);
980         }
981
982         public void windowDeactivated(WindowEvent ev) {
983             setActive(false);
984         }
985     }
986 }
987
Popular Tags