1 /* MetalRootPaneUI.java
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax
.swing
.plaf
.metal
;
41 import java
.awt
.Color
;
42 import java
.awt
.Component
;
43 import java
.awt
.Container
;
44 import java
.awt
.Dimension
;
45 import java
.awt
.Frame
;
46 import java
.awt
.Graphics
;
47 import java
.awt
.Insets
;
48 import java
.awt
.LayoutManager
;
49 import java
.awt
.LayoutManager2
;
50 import java
.awt
.Point
;
51 import java
.awt
.Rectangle
;
52 import java
.awt
.Window
;
53 import java
.awt
.event
.ActionEvent
;
54 import java
.awt
.event
.MouseEvent
;
55 import java
.beans
.PropertyChangeEvent
;
57 import javax
.swing
.AbstractAction
;
58 import javax
.swing
.Action
;
59 import javax
.swing
.Icon
;
60 import javax
.swing
.JButton
;
61 import javax
.swing
.JComponent
;
62 import javax
.swing
.JDialog
;
63 import javax
.swing
.JFrame
;
64 import javax
.swing
.JLabel
;
65 import javax
.swing
.JLayeredPane
;
66 import javax
.swing
.JMenu
;
67 import javax
.swing
.JMenuBar
;
68 import javax
.swing
.JRootPane
;
69 import javax
.swing
.SwingConstants
;
70 import javax
.swing
.SwingUtilities
;
71 import javax
.swing
.UIManager
;
72 import javax
.swing
.border
.AbstractBorder
;
73 import javax
.swing
.event
.MouseInputAdapter
;
74 import javax
.swing
.plaf
.ComponentUI
;
75 import javax
.swing
.plaf
.basic
.BasicRootPaneUI
;
78 * A UI delegate for the {@link JRootPane} component. This implementation
79 * supports the JRootPane <code>windowDecorationStyle</code> property.
81 * @author Roman Kennke (kennke@aicas.com)
85 public class MetalRootPaneUI
86 extends BasicRootPaneUI
90 * The border that is used on JRootPane when the windowDecorationStyle
91 * property of the JRootPane is set to a different value than NONE.
93 * @author Roman Kennke (kennke@aicas.com)
95 private static class MetalFrameBorder
96 extends AbstractBorder
99 * Returns the border insets.
101 * @param c the component
102 * @param newInsets the insets to be filled with the return value, may be
103 * <code>null</code> in which case a new object is created
105 * @return the border insets
107 public Insets
getBorderInsets(Component c
, Insets newInsets
)
109 if (newInsets
== null)
110 newInsets
= new Insets(5, 5, 5, 5);
115 newInsets
.bottom
= 5;
122 * Returns the border insets.
124 * @param c the component
126 * @return the border insets
128 public Insets
getBorderInsets(Component c
)
130 return getBorderInsets(c
, null);
134 * Paints the border for the specified component.
136 * @param c the component
137 * @param g the graphics device
138 * @param x the x-coordinate
139 * @param y the y-coordinate
141 * @param h the height
143 public void paintBorder(Component c
, Graphics g
, int x
, int y
, int w
,
146 JRootPane f
= (JRootPane
) c
;
147 Window frame
= SwingUtilities
.getWindowAncestor(f
);
148 if (frame
.isActive())
149 g
.setColor(MetalLookAndFeel
.getPrimaryControlDarkShadow());
151 g
.setColor(MetalLookAndFeel
.getControlDarkShadow());
153 // Fill the border background.
154 g
.fillRect(x
, y
, w
, 5);
155 g
.fillRect(x
, y
, 5, h
);
156 g
.fillRect(x
+ w
- 5, y
, 5, h
);
157 g
.fillRect(x
, y
+ h
- 5, w
, 5);
159 // Draw a dot in each corner.
160 g
.setColor(MetalLookAndFeel
.getControl());
161 g
.fillRect(x
, y
, 1, 1);
162 g
.fillRect(x
+ w
- 1, y
, 1, 1);
163 g
.fillRect(x
+ w
- 1, y
+ h
- 1, 1, 1);
164 g
.fillRect(x
, y
+ h
- 1, 1, 1);
167 g
.setColor(MetalLookAndFeel
.getBlack());
168 g
.drawLine(x
+ 14, y
+ 2, x
+ w
- 15, y
+ 2);
169 g
.drawLine(x
+ 14, y
+ h
- 3, x
+ w
- 15, y
+ h
- 3);
170 g
.drawLine(x
+ 2, y
+ 14, x
+ 2, y
+ h
- 15);
171 g
.drawLine(x
+ w
- 3, y
+ 14, x
+ w
- 3, y
+ h
- 15);
173 // Draw the line highlights.
174 if (frame
.isActive())
175 g
.setColor(MetalLookAndFeel
.getPrimaryControlShadow());
177 g
.setColor(MetalLookAndFeel
.getControlShadow());
178 g
.drawLine(x
+ 15, y
+ 3, x
+ w
- 14, y
+ 3);
179 g
.drawLine(x
+ 15, y
+ h
- 2, x
+ w
- 14, y
+ h
- 2);
180 g
.drawLine(x
+ 3, y
+ 15, x
+ 3, y
+ h
- 14);
181 g
.drawLine(x
+ w
- 2, y
+ 15, x
+ w
- 2, y
+ h
- 14);
186 * The component that renders the title bar for frames. This duplicates
187 * most of {@link MetalInternalFrameTitlePane}. It is not reasonably possible
188 * to reuse that class because that is bound to the JInternalFrame and we
189 * need to handle JFrames/JRootPanes here.
191 * @author Roman Kennke (kennke@aicas.com)
193 private static class MetalTitlePane
extends JComponent
197 * Handles dragging of the title pane and moves the window accordingly.
199 private class MouseHandler
200 extends MouseInputAdapter
203 * The point where the dragging started.
205 Point lastDragLocation
;
208 * Receives notification when the mouse gets pressed on the title pane.
209 * This updates the lastDragLocation.
211 * @param ev the mouse event
213 public void mousePressed(MouseEvent ev
)
215 lastDragLocation
= ev
.getPoint();
219 * Receives notification when the mouse is dragged on the title pane.
220 * This will move the nearest window accordingly.
222 * @param ev the mouse event
224 public void mouseDragged(MouseEvent ev
)
226 Point dragLocation
= ev
.getPoint();
227 int deltaX
= dragLocation
.x
- lastDragLocation
.x
;
228 int deltaY
= dragLocation
.y
- lastDragLocation
.y
;
229 Window window
= SwingUtilities
.getWindowAncestor(rootPane
);
230 Point loc
= window
.getLocation();
231 window
.setLocation(loc
.x
+ deltaX
, loc
.y
+ deltaY
);
232 // Note that we do not update the lastDragLocation. This is because
233 // we move the underlying window while dragging the component, which
234 // results in having the same lastDragLocation under the mouse while
240 * The Action responsible for closing the JInternalFrame.
242 private class CloseAction
extends AbstractAction
245 * Creates a new action.
253 * This method is called when something closes the frame.
255 * @param e the ActionEvent
257 public void actionPerformed(ActionEvent e
)
259 Window frame
= SwingUtilities
.getWindowAncestor(rootPane
);
260 if (frame
instanceof JFrame
)
262 JFrame jframe
= (JFrame
) frame
;
263 switch (jframe
.getDefaultCloseOperation())
265 case JFrame
.EXIT_ON_CLOSE
:
266 jframe
.setVisible(false);
270 case JFrame
.DISPOSE_ON_CLOSE
:
271 jframe
.setVisible(false);
274 case JFrame
.HIDE_ON_CLOSE
:
275 jframe
.setVisible(false);
277 case JFrame
.DO_NOTHING_ON_CLOSE
:
282 else if (frame
instanceof JDialog
)
284 JDialog jdialog
= (JDialog
) frame
;
285 switch (jdialog
.getDefaultCloseOperation())
287 case JFrame
.DISPOSE_ON_CLOSE
:
288 jdialog
.setVisible(false);
291 case JFrame
.HIDE_ON_CLOSE
:
292 jdialog
.setVisible(false);
294 case JFrame
.DO_NOTHING_ON_CLOSE
:
303 * This action is performed when the iconify button is pressed.
305 private class IconifyAction
306 extends AbstractAction
309 public void actionPerformed(ActionEvent event
)
311 Window w
= SwingUtilities
.getWindowAncestor(rootPane
);
312 if (w
instanceof Frame
)
315 int state
= f
.getExtendedState();
316 f
.setExtendedState(Frame
.ICONIFIED
);
323 * This action is performed when the maximize button is pressed.
325 private class MaximizeAction
326 extends AbstractAction
329 public void actionPerformed(ActionEvent event
)
331 Window w
= SwingUtilities
.getWindowAncestor(rootPane
);
332 if (w
instanceof Frame
)
335 int state
= f
.getExtendedState();
336 f
.setExtendedState(Frame
.MAXIMIZED_BOTH
);
342 * This helper class is used to create the minimize, maximize and close
343 * buttons in the top right corner of the Title Pane. These buttons are
344 * special since they cannot be given focus and have no border.
346 private class PaneButton
extends JButton
349 * Creates a new PaneButton object with the given Action.
351 * @param a The Action that the button uses.
353 public PaneButton(Action a
)
356 setMargin(new Insets(0, 0, 0, 0));
360 * This method returns true if the Component can be focused.
364 public boolean isFocusable()
366 // These buttons cannot be given focus.
373 * The layout for the JRootPane when the <code>windowDecorationStyle</code>
374 * property is set. In addition to the usual JRootPane.RootLayout behaviour
375 * this lays out the titlePane.
377 * @author Roman Kennke (kennke@aicas.com)
379 private class MetalTitlePaneLayout
implements LayoutManager
382 * Creates a new <code>TitlePaneLayout</code> object.
384 public MetalTitlePaneLayout()
390 * Adds a Component to the Container.
392 * @param name The name to reference the added Component by.
393 * @param c The Component to add.
395 public void addLayoutComponent(String name
, Component c
)
401 * This method is called to lay out the children of the Title Pane.
403 * @param c The Container to lay out.
405 public void layoutContainer(Container c
)
408 Dimension size
= c
.getSize();
409 Insets insets
= c
.getInsets();
410 int width
= size
.width
- insets
.left
- insets
.right
;
411 int height
= size
.height
- insets
.top
- insets
.bottom
;
413 int loc
= width
- insets
.right
- 1;
414 int top
= insets
.top
+ 2;
415 int buttonHeight
= height
- 4;
416 if (closeButton
.isVisible())
418 int buttonWidth
= closeIcon
.getIconWidth();
419 loc
-= buttonWidth
+ 2;
420 closeButton
.setBounds(loc
, top
, buttonWidth
, buttonHeight
);
424 if (maxButton
.isVisible())
426 int buttonWidth
= maxIcon
.getIconWidth();
427 loc
-= buttonWidth
+ 4;
428 maxButton
.setBounds(loc
, top
, buttonWidth
, buttonHeight
);
431 if (iconButton
.isVisible())
433 int buttonWidth
= minIcon
.getIconWidth();
434 loc
-= buttonWidth
+ 4;
435 iconButton
.setBounds(loc
, top
, buttonWidth
, buttonHeight
);
439 Dimension titlePreferredSize
= title
.getPreferredSize();
440 title
.setBounds(insets
.left
+ 5, insets
.top
,
441 Math
.min(titlePreferredSize
.width
, loc
- insets
.left
- 10),
447 * This method returns the minimum size of the given Container given the
448 * children that it has.
450 * @param c The Container to get a minimum size for.
452 * @return The minimum size of the Container.
454 public Dimension
minimumLayoutSize(Container c
)
456 return preferredLayoutSize(c
);
460 * Returns the preferred size of the given Container taking
461 * into account the children that it has.
463 * @param c The Container to lay out.
465 * @return The preferred size of the Container.
467 public Dimension
preferredLayoutSize(Container c
)
469 return new Dimension(22, 22);
473 * Removes a Component from the Container.
475 * @param c The Component to remove.
477 public void removeLayoutComponent(Component c
)
479 // Nothing to do here.
485 /** The button that closes the JInternalFrame. */
488 /** The button that iconifies the JInternalFrame. */
491 /** The button that maximizes the JInternalFrame. */
496 /** The icon displayed in the maximize button. */
499 /** The icon displayed in the iconify button. */
500 private Icon iconIcon
;
502 /** The icon displayed in the close button. */
506 * The background color of the TitlePane when the JInternalFrame is not
509 private Color notSelectedTitleColor
;
512 * The background color of the TitlePane when the JInternalFrame is
515 private Color selectedTitleColor
;
518 * The label used to display the title. This label is not added to the
523 /** The action associated with closing the JInternalFrame. */
524 private Action closeAction
;
526 /** The action associated with iconifying the JInternalFrame. */
527 private Action iconifyAction
;
529 /** The action associated with maximizing the JInternalFrame. */
530 private Action maximizeAction
;
532 /** The JMenuBar that is located at the top left of the Title Pane. */
533 private JMenuBar menuBar
;
535 /** The JMenu inside the menuBar. */
536 protected JMenu windowMenu
;
538 MetalTitlePane(JRootPane rp
)
541 setLayout(createLayout());
542 title
= new JLabel();
543 title
.setHorizontalAlignment(SwingConstants
.LEFT
);
544 title
.setHorizontalTextPosition(SwingConstants
.LEFT
);
545 title
.setOpaque(false);
549 protected LayoutManager
createLayout()
551 return new MetalTitlePaneLayout();
555 * This method installs the TitlePane onto the JInternalFrameTitlePane. It
556 * also creates any children components that need to be created and adds
557 * listeners to the appropriate components.
559 protected void installTitlePane()
564 assembleSystemMenu();
571 private void enableActions()
573 // TODO: Implement this.
576 private void addSubComponents()
584 private void installListeners()
586 MouseInputAdapter mouseHandler
= new MouseHandler();
587 addMouseListener(mouseHandler
);
588 addMouseMotionListener(mouseHandler
);
591 private void createActions()
593 closeAction
= new CloseAction();
594 iconifyAction
= new IconifyAction();
595 maximizeAction
= new MaximizeAction();
598 private void assembleSystemMenu()
600 menuBar
= createSystemMenuBar();
601 windowMenu
= createSystemMenu();
602 menuBar
.add(windowMenu
);
603 addSystemMenuItems(windowMenu
);
607 protected JMenuBar
createSystemMenuBar()
610 menuBar
= new JMenuBar();
615 protected JMenu
createSystemMenu()
617 if (windowMenu
== null)
618 windowMenu
= new JMenu();
619 windowMenu
.removeAll();
623 private void addSystemMenuItems(JMenu menu
)
625 // TODO: Implement this.
628 protected void createButtons()
630 closeButton
= new PaneButton(closeAction
);
631 closeButton
.setText(null);
632 iconButton
= new PaneButton(iconifyAction
);
633 iconButton
.setText(null);
634 maxButton
= new PaneButton(maximizeAction
);
635 maxButton
.setText(null);
636 closeButton
.setBorderPainted(false);
637 closeButton
.setContentAreaFilled(false);
638 iconButton
.setBorderPainted(false);
639 iconButton
.setContentAreaFilled(false);
640 maxButton
.setBorderPainted(false);
641 maxButton
.setContentAreaFilled(false);
644 protected void setButtonIcons()
646 if (closeIcon
!= null && closeButton
!= null)
647 closeButton
.setIcon(closeIcon
);
648 if (iconIcon
!= null && iconButton
!= null)
649 iconButton
.setIcon(iconIcon
);
650 if (maxIcon
!= null && maxButton
!= null)
651 maxButton
.setIcon(maxIcon
);
655 * Paints a representation of the current state of the internal frame.
657 * @param g the graphics device.
659 public void paintComponent(Graphics g
)
661 Window frame
= SwingUtilities
.getWindowAncestor(rootPane
);
662 Color savedColor
= g
.getColor();
663 paintTitleBackground(g
);
665 Dimension d
= getSize();
666 if (frame
.isActive())
667 g
.setColor(MetalLookAndFeel
.getPrimaryControlDarkShadow());
669 g
.setColor(MetalLookAndFeel
.getControlDarkShadow());
671 // put a dot in each of the top corners
672 g
.drawLine(0, 0, 0, 0);
673 g
.drawLine(d
.width
- 1, 0, d
.width
- 1, 0);
675 g
.drawLine(0, d
.height
- 1, d
.width
- 1, d
.height
- 1);
677 // draw the metal pattern
678 if (UIManager
.get("InternalFrame.activeTitleGradient") != null
681 MetalUtils
.paintGradient(g
, 0, 0, getWidth(), getHeight(),
682 SwingConstants
.VERTICAL
,
683 "InternalFrame.activeTitleGradient");
686 Rectangle b
= title
.getBounds();
687 int startX
= b
.x
+ b
.width
+ 5;
689 if (iconButton
.isVisible())
690 endX
= Math
.max(iconButton
.getX(), endX
);
691 else if (maxButton
.isVisible())
692 endX
= Math
.max(maxButton
.getX(), endX
);
693 else if (closeButton
.isVisible())
694 endX
= Math
.max(closeButton
.getX(), endX
);
697 MetalUtils
.fillMetalPattern(this, g
, startX
, 3, endX
- startX
, getHeight() - 6, Color
.white
, Color
.gray
);
698 g
.setColor(savedColor
);
702 * This method paints the TitlePane's background.
704 * @param g The Graphics object to paint with.
706 protected void paintTitleBackground(Graphics g
)
708 Window frame
= SwingUtilities
.getWindowAncestor(rootPane
);
713 Color saved
= g
.getColor();
714 Dimension dims
= getSize();
716 Color bg
= getBackground();
717 if (frame
.isActive())
718 bg
= selectedTitleColor
;
720 bg
= notSelectedTitleColor
;
722 g
.fillRect(0, 0, dims
.width
, dims
.height
);
727 * This method installs the defaults determined by the look and feel.
729 private void installDefaults()
731 title
.setFont(UIManager
.getFont("InternalFrame.titleFont"));
732 selectedTitleColor
= UIManager
.getColor("InternalFrame.activeTitleBackground");
733 notSelectedTitleColor
= UIManager
.getColor("InternalFrame.inactiveTitleBackground");
734 closeIcon
= UIManager
.getIcon("InternalFrame.closeIcon");
735 iconIcon
= UIManager
.getIcon("InternalFrame.iconifyIcon");
736 maxIcon
= UIManager
.getIcon("InternalFrame.maximizeIcon");
737 minIcon
= MetalIconFactory
.getInternalFrameAltMaximizeIcon(16);
738 Frame frame
= (Frame
) SwingUtilities
.getWindowAncestor(rootPane
);
739 title
= new JLabel(frame
.getTitle(),
740 MetalIconFactory
.getInternalFrameDefaultMenuIcon(),
741 SwingConstants
.LEFT
);
745 private static class MetalRootLayout
746 implements LayoutManager2
750 * The cached layout info for the glass pane.
752 private Rectangle glassPaneBounds
;
755 * The cached layout info for the layered pane.
757 private Rectangle layeredPaneBounds
;
760 * The cached layout info for the content pane.
762 private Rectangle contentPaneBounds
;
765 * The cached layout info for the menu bar.
767 private Rectangle menuBarBounds
;
770 * The cached layout info for the title pane.
772 private Rectangle titlePaneBounds
;
775 * The cached preferred size.
777 private Dimension prefSize
;
780 * The title pane for l&f decorated frames.
782 private MetalTitlePane titlePane
;
785 * Creates a new MetalRootLayout.
787 * @param tp the title pane
789 MetalRootLayout(MetalTitlePane tp
)
794 public void addLayoutComponent(Component component
, Object constraints
)
796 // Nothing to do here.
799 public Dimension
maximumLayoutSize(Container target
)
801 return preferredLayoutSize(target
);
804 public float getLayoutAlignmentX(Container target
)
809 public float getLayoutAlignmentY(Container target
)
814 public void invalidateLayout(Container target
)
818 glassPaneBounds
= null;
819 layeredPaneBounds
= null;
820 contentPaneBounds
= null;
821 menuBarBounds
= null;
822 titlePaneBounds
= null;
827 public void addLayoutComponent(String name
, Component component
)
829 // Nothing to do here.
832 public void removeLayoutComponent(Component component
)
834 // TODO Auto-generated method stub
838 public Dimension
preferredLayoutSize(Container parent
)
840 JRootPane rp
= (JRootPane
) parent
;
841 JLayeredPane layeredPane
= rp
.getLayeredPane();
842 Component contentPane
= rp
.getContentPane();
843 Component menuBar
= rp
.getJMenuBar();
845 // We must synchronize here, otherwise we cannot guarantee that the
846 // prefSize is still non-null when returning.
849 if (prefSize
== null)
851 Insets i
= parent
.getInsets();
852 prefSize
= new Dimension(i
.left
+ i
.right
, i
.top
+ i
.bottom
);
853 Dimension contentPrefSize
= contentPane
.getPreferredSize();
854 prefSize
.width
+= contentPrefSize
.width
;
855 prefSize
.height
+= contentPrefSize
.height
856 + titlePane
.getPreferredSize().height
;
859 Dimension menuBarSize
= menuBar
.getPreferredSize();
860 if (menuBarSize
.width
> contentPrefSize
.width
)
861 prefSize
.width
+= menuBarSize
.width
- contentPrefSize
.width
;
862 prefSize
.height
+= menuBarSize
.height
;
865 // Return a copy here so the cached value won't get trashed by some
867 return new Dimension(prefSize
);
871 public Dimension
minimumLayoutSize(Container parent
)
873 return preferredLayoutSize(parent
);
876 public void layoutContainer(Container parent
)
878 JRootPane rp
= (JRootPane
) parent
;
879 JLayeredPane layeredPane
= rp
.getLayeredPane();
880 Component contentPane
= rp
.getContentPane();
881 Component menuBar
= rp
.getJMenuBar();
882 Component glassPane
= rp
.getGlassPane();
884 if (glassPaneBounds
== null || layeredPaneBounds
== null
885 || contentPaneBounds
== null || menuBarBounds
== null)
887 Insets i
= rp
.getInsets();
888 int containerWidth
= parent
.getBounds().width
- i
.left
- i
.right
;
889 int containerHeight
= parent
.getBounds().height
- i
.top
- i
.bottom
;
891 // 1. The glassPane fills entire viewable region (bounds - insets).
892 // 2. The layeredPane filles entire viewable region.
893 // 3. The titlePane is placed at the upper edge of the layeredPane.
894 // 4. The menuBar is positioned at the upper edge of layeredPane.
895 // 5. The contentPane fills viewable region minus menuBar minus
896 // titlePane, if present.
898 // +-------------------------------+
900 // | +--------------------------+ |
902 // | +--------------------------+ |
903 // | +--------------------------+ |
905 // | +--------------------------+ |
906 // | +--------------------------+ |
907 // | |contentPane | |
911 // | +--------------------------+ |
912 // +-------------------------------+
914 // Setup titlePaneBounds.
915 if (titlePaneBounds
== null)
916 titlePaneBounds
= new Rectangle();
917 titlePaneBounds
.width
= containerWidth
;
918 titlePaneBounds
.height
= titlePane
.getPreferredSize().height
;
920 // Setup menuBarBounds.
921 if (menuBarBounds
== null)
922 menuBarBounds
= new Rectangle();
923 menuBarBounds
.setBounds(0,
924 titlePaneBounds
.y
+ titlePaneBounds
.height
,
928 Dimension menuBarSize
= menuBar
.getPreferredSize();
929 if (menuBarSize
.height
> containerHeight
)
930 menuBarBounds
.height
= containerHeight
;
932 menuBarBounds
.height
= menuBarSize
.height
;
935 // Setup contentPaneBounds.
936 if (contentPaneBounds
== null)
937 contentPaneBounds
= new Rectangle();
938 contentPaneBounds
.setBounds(0,
939 menuBarBounds
.y
+ menuBarBounds
.height
,
941 containerHeight
- menuBarBounds
.y
942 - menuBarBounds
.height
);
943 glassPaneBounds
= new Rectangle(i
.left
, i
.top
, containerWidth
, containerHeight
);
944 layeredPaneBounds
= new Rectangle(i
.left
, i
.top
, containerWidth
, containerHeight
);
947 // Layout components.
948 glassPane
.setBounds(glassPaneBounds
);
949 layeredPane
.setBounds(layeredPaneBounds
);
951 menuBar
.setBounds(menuBarBounds
);
952 contentPane
.setBounds(contentPaneBounds
);
953 titlePane
.setBounds(titlePaneBounds
);
959 * The shared UI instance for MetalRootPaneUIs.
961 private static MetalRootPaneUI instance
= null;
964 * Constructs a shared instance of <code>MetalRootPaneUI</code>.
966 public MetalRootPaneUI()
972 * Returns a shared instance of <code>MetalRootPaneUI</code>.
974 * @param component the component for which we return an UI instance
976 * @return A shared instance of <code>MetalRootPaneUI</code>.
978 public static ComponentUI
createUI(JComponent component
)
980 if (instance
== null)
981 instance
= new MetalRootPaneUI();
986 * Installs this UI to the root pane. If the
987 * <code>windowDecorationsStyle</code> property is set on the root pane,
988 * the Metal window decorations are installed on the root pane.
992 public void installUI(JComponent c
)
995 JRootPane rp
= (JRootPane
) c
;
996 if (rp
.getWindowDecorationStyle() != JRootPane
.NONE
)
997 installWindowDecorations(rp
);
1001 * Uninstalls the UI from the root pane. This performs the superclass
1002 * behaviour and uninstalls the window decorations that have possibly been
1003 * installed by {@link #installUI}.
1005 * @param c the root pane
1007 public void uninstallUI(JComponent c
)
1009 JRootPane rp
= (JRootPane
) c
;
1010 if (rp
.getWindowDecorationStyle() != JRootPane
.NONE
)
1011 uninstallWindowDecorations(rp
);
1012 super.uninstallUI(c
);
1016 * Receives notification if any of the JRootPane's property changes. In
1017 * particular this catches changes to the <code>windowDecorationStyle</code>
1018 * property and installs the window decorations accordingly.
1020 * @param ev the property change event
1022 public void propertyChange(PropertyChangeEvent ev
)
1024 super.propertyChange(ev
);
1025 String propertyName
= ev
.getPropertyName();
1026 if (propertyName
.equals("windowDecorationStyle"))
1028 JRootPane rp
= (JRootPane
) ev
.getSource();
1029 if (rp
.getWindowDecorationStyle() != JRootPane
.NONE
)
1030 installWindowDecorations(rp
);
1032 uninstallWindowDecorations(rp
);
1037 * Installs the window decorations to the root pane. This sets up a border,
1038 * a title pane and a layout manager that can layout the root pane with that
1041 * @param rp the root pane.
1043 private void installWindowDecorations(JRootPane rp
)
1045 rp
.setBorder(new MetalFrameBorder());
1046 MetalTitlePane titlePane
= new MetalTitlePane(rp
);
1047 rp
.setLayout(new MetalRootLayout(titlePane
));
1048 // We should have a contentPane already.
1049 assert rp
.getLayeredPane().getComponentCount() > 0
1050 : "We should have a contentPane already";
1052 rp
.getLayeredPane().add(titlePane
,
1053 JLayeredPane
.FRAME_CONTENT_LAYER
, 1);
1057 * Uninstalls the window decorations from the root pane. This should rarely
1058 * be necessary, but we do it anyway.
1060 * @param rp the root pane
1062 private void uninstallWindowDecorations(JRootPane rp
)
1065 JLayeredPane lp
= rp
.getLayeredPane();
1066 for (int i
= lp
.getComponentCount() - 1; i
>= 0; --i
)
1068 if (lp
.getComponent(i
) instanceof MetalTitlePane
)