/* MetalRootPaneUI.java
   Copyright (C) 2005, 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.plaf.metal;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JRootPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.event.MouseInputAdapter;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicRootPaneUI;

/**
 * A UI delegate for the {@link JRootPane} component. This implementation
 * supports the JRootPane <code>windowDecorationStyle</code> property.  
 * 
 * @author Roman Kennke (kennke@aicas.com)
 *
 * @since 1.4
 */
public class MetalRootPaneUI
  extends BasicRootPaneUI
{

  /**
   * The border that is used on JRootPane when the windowDecorationStyle
   * property of the JRootPane is set to a different value than NONE.
   *
   * @author Roman Kennke (kennke@aicas.com)
   */
  private static class MetalFrameBorder
    extends AbstractBorder
  {
    /**
     * Returns the border insets.
     *
     * @param c the component
     * @param newInsets the insets to be filled with the return value, may be
     *        <code>null</code> in which case a new object is created
     *
     * @return the border insets
     */
    public Insets getBorderInsets(Component c, Insets newInsets)
    {
      if (newInsets == null)
        newInsets = new Insets(5, 5, 5, 5);
      else
        {
          newInsets.top = 5;
          newInsets.left = 5;
          newInsets.bottom = 5;
          newInsets.right = 5;
        }
      return newInsets;  
    }

    /**
     * Returns the border insets.
     *
     * @param c the component
     *
     * @return the border insets
     */
    public Insets getBorderInsets(Component c)
    {
      return getBorderInsets(c, null);
    }

    /**
     * Paints the border for the specified component.
     * 
     * @param c  the component
     * @param g  the graphics device
     * @param x  the x-coordinate
     * @param y  the y-coordinate
     * @param w  the width
     * @param h  the height
     */
    public void paintBorder(Component c, Graphics g, int x, int y, int w, 
                            int h)
    {
      JRootPane f = (JRootPane) c;
      Window frame = SwingUtilities.getWindowAncestor(f);
      if (frame.isActive())
        g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
      else
        g.setColor(MetalLookAndFeel.getControlDarkShadow());
      
      // Fill the border background.
      g.fillRect(x, y, w, 5);
      g.fillRect(x, y, 5, h);
      g.fillRect(x + w - 5, y, 5, h);
      g.fillRect(x, y + h - 5, w, 5);
      
      // Draw a dot in each corner.
      g.setColor(MetalLookAndFeel.getControl());
      g.fillRect(x, y, 1, 1);
      g.fillRect(x + w - 1, y, 1, 1);
      g.fillRect(x + w - 1, y + h - 1, 1, 1);
      g.fillRect(x, y + h - 1, 1, 1);
      
      // Draw the lines.
      g.setColor(MetalLookAndFeel.getBlack());
      g.drawLine(x + 14, y + 2, x + w - 15, y + 2);
      g.drawLine(x + 14, y + h - 3, x + w - 15, y + h - 3);
      g.drawLine(x + 2, y + 14, x + 2, y + h - 15);
      g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15);
      
      // Draw the line highlights.
      if (frame.isActive())
        g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
      else 
        g.setColor(MetalLookAndFeel.getControlShadow());
      g.drawLine(x + 15, y + 3, x + w - 14, y + 3);
      g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2);
      g.drawLine(x + 3, y + 15, x + 3, y + h - 14);
      g.drawLine(x + w - 2, y + 15, x + w - 2, y + h - 14);
    }
  }

  /**
   * The component that renders the title bar for frames. This duplicates
   * most of {@link MetalInternalFrameTitlePane}. It is not reasonably possible
   * to reuse that class because that is bound to the JInternalFrame and we
   * need to handle JFrames/JRootPanes here.
   *
   * @author Roman Kennke (kennke@aicas.com)
   */
  private static class MetalTitlePane extends JComponent
  {

    /**
     * Handles dragging of the title pane and moves the window accordingly.
     */
    private class MouseHandler
      extends MouseInputAdapter
    {
      /**
       * The point where the dragging started.
       */
      Point lastDragLocation;

      /**
       * Receives notification when the mouse gets pressed on the title pane.
       * This updates the lastDragLocation.
       *
       * @param ev the mouse event
       */
      public void mousePressed(MouseEvent ev)
      {
        lastDragLocation = ev.getPoint();
      }

      /**
       * Receives notification when the mouse is dragged on the title pane.
       * This will move the nearest window accordingly.
       *
       * @param ev the mouse event
       */
      public void mouseDragged(MouseEvent ev)
      {
        Point dragLocation = ev.getPoint();
        int deltaX = dragLocation.x - lastDragLocation.x;
        int deltaY = dragLocation.y - lastDragLocation.y;
        Window window = SwingUtilities.getWindowAncestor(rootPane);
        Point loc = window.getLocation();
        window.setLocation(loc.x + deltaX, loc.y + deltaY);
        // Note that we do not update the lastDragLocation. This is because
        // we move the underlying window while dragging the component, which
        // results in having the same lastDragLocation under the mouse while
        // dragging.
      }
    }

    /**
     * The Action responsible for closing the JInternalFrame.
     */
    private class CloseAction extends AbstractAction
    {
      /**
       * Creates a new action.
       */
      public CloseAction()
      {
        super("Close");
      }
      
      /**
       * This method is called when something closes the frame.
       *
       * @param e the ActionEvent
       */
      public void actionPerformed(ActionEvent e)
      {
        Window frame = SwingUtilities.getWindowAncestor(rootPane);
        if (frame instanceof JFrame)
          {
            JFrame jframe = (JFrame) frame;
            switch (jframe.getDefaultCloseOperation())
            {
              case JFrame.EXIT_ON_CLOSE:
                jframe.setVisible(false);
                jframe.dispose();
                System.exit(0);
                break;
              case JFrame.DISPOSE_ON_CLOSE:
                jframe.setVisible(false);
                jframe.dispose();
                break;
              case JFrame.HIDE_ON_CLOSE:
                jframe.setVisible(false);
                break;
              case JFrame.DO_NOTHING_ON_CLOSE:
              default:
                  break;
            }
          }
        else if (frame instanceof JDialog)
          {
            JDialog jdialog = (JDialog) frame;
            switch (jdialog.getDefaultCloseOperation())
            {
              case JFrame.DISPOSE_ON_CLOSE:
                jdialog.setVisible(false);
                jdialog.dispose();
                break;
              case JFrame.HIDE_ON_CLOSE:
                jdialog.setVisible(false);
                break;
              case JFrame.DO_NOTHING_ON_CLOSE:
              default:
                  break;
            }
          }
      }
    }

    /**
     * This action is performed when the iconify button is pressed.
     */
    private class IconifyAction
      extends AbstractAction
    {

      public void actionPerformed(ActionEvent event)
      {
        Window w = SwingUtilities.getWindowAncestor(rootPane);
        if (w instanceof Frame)
          {
            Frame f = (Frame) w;
            int state = f.getExtendedState();
            f.setExtendedState(Frame.ICONIFIED);
          }
      }
        
    }

    /**
     * This action is performed when the maximize button is pressed.
     */
    private class MaximizeAction
      extends AbstractAction
    {

      public void actionPerformed(ActionEvent event)
      {
        Window w = SwingUtilities.getWindowAncestor(rootPane);
        if (w instanceof Frame)
          {
            Frame f = (Frame) w;
            int state = f.getExtendedState();
            f.setExtendedState(Frame.MAXIMIZED_BOTH);
          }
      }
    }

    /**
     * This helper class is used to create the minimize, maximize and close
     * buttons in the top right corner of the Title Pane. These buttons are
     * special since they cannot be given focus and have no border.
     */
    private class PaneButton extends JButton
    {
      /**
       * Creates a new PaneButton object with the given Action.
       *
       * @param a The Action that the button uses.
       */
      public PaneButton(Action a)
      {
        super(a);
        setMargin(new Insets(0, 0, 0, 0));
      }

      /**
       * This method returns true if the Component can be focused.
       *
       * @return false.
       */
      public boolean isFocusable()
      {
        // These buttons cannot be given focus.
        return false;
      }

    }

    /**
     * The layout for the JRootPane when the <code>windowDecorationStyle</code>
     * property is set. In addition to the usual JRootPane.RootLayout behaviour
     * this lays out the titlePane.
     *
     * @author Roman Kennke (kennke@aicas.com)
     */
    private class MetalTitlePaneLayout implements LayoutManager
    {
      /**
       * Creates a new <code>TitlePaneLayout</code> object.
       */
      public MetalTitlePaneLayout()
      {
        // Do nothing.
      }

      /**
       * Adds a Component to the Container.
       *
       * @param name The name to reference the added Component by.
       * @param c The Component to add.
       */
      public void addLayoutComponent(String name, Component c)
      {
        // Do nothing.
      }

      /**
       * This method is called to lay out the children of the Title Pane.
       *
       * @param c The Container to lay out.
       */
      public void layoutContainer(Container c)
      {

        Dimension size = c.getSize();
        Insets insets = c.getInsets();
        int width = size.width - insets.left - insets.right;
        int height = size.height - insets.top - insets.bottom;

        int loc = width - insets.right - 1;
        int top = insets.top + 2;
        int buttonHeight = height - 4;
        if (closeButton.isVisible())
          {
            int buttonWidth = closeIcon.getIconWidth();
            loc -= buttonWidth + 2;
            closeButton.setBounds(loc, top, buttonWidth, buttonHeight);
            loc -= 6;
          }

        if (maxButton.isVisible())
          {
            int buttonWidth = maxIcon.getIconWidth();
            loc -= buttonWidth + 4;
            maxButton.setBounds(loc, top, buttonWidth, buttonHeight);
          }

        if (iconButton.isVisible())
          {
            int buttonWidth = minIcon.getIconWidth();
            loc -= buttonWidth + 4;
            iconButton.setBounds(loc, top, buttonWidth, buttonHeight);
            loc -= 2;
          }

        Dimension titlePreferredSize = title.getPreferredSize();
        title.setBounds(insets.left + 5, insets.top, 
                Math.min(titlePreferredSize.width, loc - insets.left - 10), 
                height);

      }

      /**
       * This method returns the minimum size of the given Container given the
       * children that it has.
       *
       * @param c The Container to get a minimum size for.
       *
       * @return The minimum size of the Container.
       */
      public Dimension minimumLayoutSize(Container c)
      {
        return preferredLayoutSize(c);
      }

      /**
       * Returns the preferred size of the given Container taking
       * into account the children that it has.
       *
       * @param c The Container to lay out.
       *
       * @return The preferred size of the Container.
       */
      public Dimension preferredLayoutSize(Container c)
      {
        return new Dimension(22, 22);
      }

      /**
       * Removes a Component from the Container.
       *
       * @param c The Component to remove.
       */
      public void removeLayoutComponent(Component c)
      {
        // Nothing to do here.
      }
    }

    JRootPane rootPane;

    /** The button that closes the JInternalFrame. */
    JButton closeButton;

    /** The button that iconifies the JInternalFrame. */
    JButton iconButton;

    /** The button that maximizes the JInternalFrame. */
    JButton maxButton;

    Icon minIcon;

    /** The icon displayed in the maximize button. */
    Icon maxIcon;

    /** The icon displayed in the iconify button. */
    private Icon iconIcon;

    /** The icon displayed in the close button. */
    Icon closeIcon;
    
    /**
     * The background color of the TitlePane when the JInternalFrame is not
     * selected.
     */
    private Color notSelectedTitleColor;

    /**
     * The background color of the TitlePane when the JInternalFrame is
     * selected.
     */
    private Color selectedTitleColor;

    /**
     * The label used to display the title. This label is not added to the
     * TitlePane.
     */
    JLabel title;

    /** The action associated with closing the JInternalFrame. */
    private Action closeAction;

    /** The action associated with iconifying the JInternalFrame. */
    private Action iconifyAction;

    /** The action associated with maximizing the JInternalFrame. */
    private Action maximizeAction;

    /** The JMenuBar that is located at the top left of the Title Pane. */
    private JMenuBar menuBar;

    /** The JMenu inside the menuBar. */
    protected JMenu windowMenu;

    MetalTitlePane(JRootPane rp)
    {
      rootPane = rp;
      setLayout(createLayout());
      title = new JLabel();
      title.setHorizontalAlignment(SwingConstants.LEFT);
      title.setHorizontalTextPosition(SwingConstants.LEFT);
      title.setOpaque(false);
      installTitlePane();
    }

    protected LayoutManager createLayout()
    {
      return new MetalTitlePaneLayout();
    }

    /**
     * This method installs the TitlePane onto the JInternalFrameTitlePane. It
     * also creates any children components that need to be created and adds
     * listeners to the appropriate components.
     */
    protected void installTitlePane()
    {
      installDefaults();
      installListeners();
      createActions();
      assembleSystemMenu();
      createButtons();
      setButtonIcons();
      addSubComponents();
      enableActions();
    }

    private void enableActions()
    {
      // TODO: Implement this.
    }

    private void addSubComponents()
    {
      add(menuBar);
      add(closeButton);
      add(iconButton);
      add(maxButton);
    }

    private void installListeners()
    {
      MouseInputAdapter mouseHandler = new MouseHandler();
      addMouseListener(mouseHandler);
      addMouseMotionListener(mouseHandler);
    }

    private void createActions()
    {
      closeAction = new CloseAction();
      iconifyAction = new IconifyAction();
      maximizeAction = new MaximizeAction();
    }

    private void assembleSystemMenu()
    {
      menuBar = createSystemMenuBar();
      windowMenu = createSystemMenu();
      menuBar.add(windowMenu);
      addSystemMenuItems(windowMenu);
      enableActions();
    }

    protected JMenuBar createSystemMenuBar()
    {
      if (menuBar == null)
        menuBar = new JMenuBar();
      menuBar.removeAll();
      return menuBar;
    }

    protected JMenu createSystemMenu()
    {
      if (windowMenu == null)
        windowMenu = new JMenu();
      windowMenu.removeAll();
      return windowMenu;
    }

    private void addSystemMenuItems(JMenu menu)
    {
      // TODO: Implement this.
    }

    protected void createButtons()
    {
      closeButton = new PaneButton(closeAction);
      closeButton.setText(null);
      iconButton = new PaneButton(iconifyAction);
      iconButton.setText(null);
      maxButton = new PaneButton(maximizeAction);
      maxButton.setText(null);
      closeButton.setBorderPainted(false);
      closeButton.setContentAreaFilled(false);
      iconButton.setBorderPainted(false);
      iconButton.setContentAreaFilled(false);
      maxButton.setBorderPainted(false);
      maxButton.setContentAreaFilled(false);
    }

    protected void setButtonIcons()
    {
      if (closeIcon != null && closeButton != null)
        closeButton.setIcon(closeIcon);
      if (iconIcon != null && iconButton != null)
        iconButton.setIcon(iconIcon);
      if (maxIcon != null && maxButton != null)
        maxButton.setIcon(maxIcon);
    }

    /**
     * Paints a representation of the current state of the internal frame.
     * 
     * @param g  the graphics device.
     */
    public void paintComponent(Graphics g)
    {
      Window frame = SwingUtilities.getWindowAncestor(rootPane);
      Color savedColor = g.getColor();
      paintTitleBackground(g);
      paintChildren(g);
      Dimension d = getSize();
      if (frame.isActive())
        g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
      else
        g.setColor(MetalLookAndFeel.getControlDarkShadow());
          
      // put a dot in each of the top corners
      g.drawLine(0, 0, 0, 0);
      g.drawLine(d.width - 1, 0, d.width - 1, 0);
          
      g.drawLine(0, d.height - 1, d.width - 1, d.height - 1);
          
      // draw the metal pattern
      if (UIManager.get("InternalFrame.activeTitleGradient") != null
          && frame.isActive())
        {
          MetalUtils.paintGradient(g, 0, 0, getWidth(), getHeight(),
                                   SwingConstants.VERTICAL,
          "InternalFrame.activeTitleGradient");
        }

      Rectangle b = title.getBounds();
      int startX = b.x + b.width + 5;
      int endX = startX;
      if (iconButton.isVisible())
        endX = Math.max(iconButton.getX(), endX);
      else if (maxButton.isVisible()) 
        endX = Math.max(maxButton.getX(), endX);
      else if (closeButton.isVisible())
        endX = Math.max(closeButton.getX(), endX);
      endX -= 7;
      if (endX > startX)
        MetalUtils.fillMetalPattern(this, g, startX, 3, endX - startX, getHeight() - 6, Color.white, Color.gray);
      g.setColor(savedColor);
    }

    /**
     * This method paints the TitlePane's background.
     *
     * @param g The Graphics object to paint with.
     */
    protected void paintTitleBackground(Graphics g)
    {
      Window frame = SwingUtilities.getWindowAncestor(rootPane);

      if (!isOpaque())
        return;
      
      Color saved = g.getColor();
      Dimension dims = getSize();
      
      Color bg = getBackground();
      if (frame.isActive())
        bg = selectedTitleColor;
      else
        bg = notSelectedTitleColor;
      g.setColor(bg);
      g.fillRect(0, 0, dims.width, dims.height);
      g.setColor(saved);
    }

    /**
     * This method installs the defaults determined by the look and feel.
     */
    private void installDefaults()
    {
      title.setFont(UIManager.getFont("InternalFrame.titleFont"));
      selectedTitleColor = UIManager.getColor("InternalFrame.activeTitleBackground");
      notSelectedTitleColor = UIManager.getColor("InternalFrame.inactiveTitleBackground");
      closeIcon = UIManager.getIcon("InternalFrame.closeIcon");
      iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon");
      maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
      minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16);
      Frame frame = (Frame) SwingUtilities.getWindowAncestor(rootPane);
      title = new JLabel(frame.getTitle(), 
              MetalIconFactory.getInternalFrameDefaultMenuIcon(), 
              SwingConstants.LEFT);
    }
  }

  private static class MetalRootLayout
    implements LayoutManager2
  {

    /**
     * The cached layout info for the glass pane.
     */
    private Rectangle glassPaneBounds;

    /**
     * The cached layout info for the layered pane.
     */
    private Rectangle layeredPaneBounds;

    /**
     * The cached layout info for the content pane.
     */
    private Rectangle contentPaneBounds;

    /**
     * The cached layout info for the menu bar.
     */
    private Rectangle menuBarBounds;

    /**
     * The cached layout info for the title pane.
     */
    private Rectangle titlePaneBounds;
    
    /**
     * The cached preferred size.
     */
    private Dimension prefSize;

    /**
     * The title pane for l&f decorated frames.
     */
    private MetalTitlePane titlePane;

    /**
     * Creates a new MetalRootLayout.
     *
     * @param tp the title pane
     */
    MetalRootLayout(MetalTitlePane tp)
    {
      titlePane = tp;
    }

    public void addLayoutComponent(Component component, Object constraints)
    {
      // Nothing to do here.
    }

    public Dimension maximumLayoutSize(Container target)
    {
      return preferredLayoutSize(target);
    }

    public float getLayoutAlignmentX(Container target)
    {
      return 0.0F;
    }

    public float getLayoutAlignmentY(Container target)
    {
      return 0.0F;
    }

    public void invalidateLayout(Container target)
    {
      synchronized (this)
      {
        glassPaneBounds = null;
        layeredPaneBounds = null;
        contentPaneBounds = null;
        menuBarBounds = null;
        titlePaneBounds = null;
        prefSize = null;
      }
    }

    public void addLayoutComponent(String name, Component component)
    {
      // Nothing to do here.
    }

    public void removeLayoutComponent(Component component)
    {
      // TODO Auto-generated method stub
      
    }

    public Dimension preferredLayoutSize(Container parent)
    {
      JRootPane rp = (JRootPane) parent;
      JLayeredPane layeredPane = rp.getLayeredPane();
      Component contentPane = rp.getContentPane();
      Component menuBar = rp.getJMenuBar();

      // We must synchronize here, otherwise we cannot guarantee that the
      // prefSize is still non-null when returning.
      synchronized (this)
        {
          if (prefSize == null)
            {
              Insets i = parent.getInsets();
              prefSize = new Dimension(i.left + i.right, i.top + i.bottom);
              Dimension contentPrefSize = contentPane.getPreferredSize();
              prefSize.width += contentPrefSize.width;
              prefSize.height += contentPrefSize.height
                                 + titlePane.getPreferredSize().height;
              if (menuBar != null)
                {
                  Dimension menuBarSize = menuBar.getPreferredSize();
                  if (menuBarSize.width > contentPrefSize.width)
                    prefSize.width += menuBarSize.width - contentPrefSize.width;
                  prefSize.height += menuBarSize.height;
                }
            }
          // Return a copy here so the cached value won't get trashed by some
          // other component.
          return new Dimension(prefSize);
      }
    }

    public Dimension minimumLayoutSize(Container parent)
    {
      return preferredLayoutSize(parent);
    }

    public void layoutContainer(Container parent)
    {
      JRootPane rp = (JRootPane) parent;
      JLayeredPane layeredPane = rp.getLayeredPane();
      Component contentPane = rp.getContentPane();
      Component menuBar = rp.getJMenuBar();
      Component glassPane = rp.getGlassPane();

      if (glassPaneBounds == null || layeredPaneBounds == null
          || contentPaneBounds == null || menuBarBounds == null)
        {
          Insets i = rp.getInsets();
          int containerWidth = parent.getBounds().width - i.left - i.right;
          int containerHeight = parent.getBounds().height - i.top - i.bottom;

          // 1. The glassPane fills entire viewable region (bounds - insets).
          // 2. The layeredPane filles entire viewable region.
          // 3. The titlePane is placed at the upper edge of the layeredPane.
          // 4. The menuBar is positioned at the upper edge of layeredPane.
          // 5. The contentPane fills viewable region minus menuBar minus
          //    titlePane, if present.
      
          // +-------------------------------+
          // |  JLayeredPane                 |
          // |  +--------------------------+ |
          // |  | titlePane                + |
          // |  +--------------------------+ |
          // |  +--------------------------+ |
          // |  | menuBar                  | |
          // |  +--------------------------+ |
          // |  +--------------------------+ |
          // |  |contentPane               | |
          // |  |                          | |
          // |  |                          | |
          // |  |                          | |
          // |  +--------------------------+ |
          // +-------------------------------+

          // Setup titlePaneBounds.
          if (titlePaneBounds == null)
            titlePaneBounds = new Rectangle();
          titlePaneBounds.width = containerWidth;
          titlePaneBounds.height = titlePane.getPreferredSize().height;

          // Setup menuBarBounds.
          if (menuBarBounds == null)
            menuBarBounds = new Rectangle();
          menuBarBounds.setBounds(0,
                                  titlePaneBounds.y + titlePaneBounds.height,
                                  containerWidth, 0);
          if (menuBar != null)
            {
              Dimension menuBarSize = menuBar.getPreferredSize();
              if (menuBarSize.height > containerHeight)
                menuBarBounds.height = containerHeight;
              else
                menuBarBounds.height = menuBarSize.height;
            }

          // Setup contentPaneBounds.
          if (contentPaneBounds == null)
            contentPaneBounds = new Rectangle();
          contentPaneBounds.setBounds(0,
                                      menuBarBounds.y + menuBarBounds.height,
                                      containerWidth,
                                      containerHeight - menuBarBounds.y
                                      - menuBarBounds.height);
          glassPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight);
          layeredPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight);
        }

      // Layout components.
      glassPane.setBounds(glassPaneBounds);
      layeredPane.setBounds(layeredPaneBounds);
      if (menuBar != null)
        menuBar.setBounds(menuBarBounds);
      contentPane.setBounds(contentPaneBounds);
      titlePane.setBounds(titlePaneBounds);
    }
      
  }

  /**
   * The shared UI instance for MetalRootPaneUIs.
   */
  private static MetalRootPaneUI instance;

  /**
   * Constructs a shared instance of <code>MetalRootPaneUI</code>.
   */
  public MetalRootPaneUI()
  {
    super();
  }

  /**
   * Returns a shared instance of <code>MetalRootPaneUI</code>.
   *
   * @param component the component for which we return an UI instance
   *
   * @return A shared instance of <code>MetalRootPaneUI</code>.
   */
  public static ComponentUI createUI(JComponent component)
  {
    if (instance == null)
      instance = new MetalRootPaneUI();
    return instance;
  }

  /**
   * Installs this UI to the root pane. If the
   * <code>windowDecorationsStyle</code> property is set on the root pane,
   * the Metal window decorations are installed on the root pane.
   *
   * @param c
   */
  public void installUI(JComponent c)
  {
    super.installUI(c);
    JRootPane rp = (JRootPane) c;
    if (rp.getWindowDecorationStyle() != JRootPane.NONE)
      installWindowDecorations(rp);
  }

  /**
   * Uninstalls the UI from the root pane. This performs the superclass
   * behaviour and uninstalls the window decorations that have possibly been
   * installed by {@link #installUI}.
   *
   * @param c the root pane
   */
  public void uninstallUI(JComponent c)
  {
    JRootPane rp = (JRootPane) c;
    if (rp.getWindowDecorationStyle() != JRootPane.NONE)
      uninstallWindowDecorations(rp);
    super.uninstallUI(c);
  }

  /**
   * Receives notification if any of the JRootPane's property changes. In
   * particular this catches changes to the <code>windowDecorationStyle</code>
   * property and installs the window decorations accordingly.
   *
   * @param ev the property change event
   */
  public void propertyChange(PropertyChangeEvent ev)
  {
    super.propertyChange(ev);
    String propertyName = ev.getPropertyName();
    if (propertyName.equals("windowDecorationStyle"))
      {
        JRootPane rp = (JRootPane) ev.getSource();
        if (rp.getWindowDecorationStyle() != JRootPane.NONE)
          installWindowDecorations(rp);
        else
          uninstallWindowDecorations(rp);
      }
  }

  /**
   * Installs the window decorations to the root pane. This sets up a border,
   * a title pane and a layout manager that can layout the root pane with that
   * title pane.
   *
   * @param rp the root pane.
   */
  private void installWindowDecorations(JRootPane rp)
  {
    rp.setBorder(new MetalFrameBorder());
    MetalTitlePane titlePane = new MetalTitlePane(rp);
    rp.setLayout(new MetalRootLayout(titlePane));
    // We should have a contentPane already.
    assert rp.getLayeredPane().getComponentCount() > 0
           : "We should have a contentPane already";

    rp.getLayeredPane().add(titlePane,
                            JLayeredPane.FRAME_CONTENT_LAYER, 1);
  }

  /**
   * Uninstalls the window decorations from the root pane. This should rarely
   * be necessary, but we do it anyway.
   *
   * @param rp the root pane
   */
  private void uninstallWindowDecorations(JRootPane rp)
  {
    rp.setBorder(null);
    JLayeredPane lp = rp.getLayeredPane();
    for (int i = lp.getComponentCount() - 1; i >= 0; --i)
      {
        if (lp.getComponent(i) instanceof MetalTitlePane)
          {
            lp.remove(i);
            break;
          }
      }
  }
}
