summaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/plaf/metal
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/metal')
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java305
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalBorders.java1626
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java298
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java142
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java88
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java294
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java190
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java102
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java372
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java72
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java2120
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java2626
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java457
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java183
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java108
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java1372
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalMenuBarUI.java94
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java77
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java147
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java183
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java1075
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java584
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java483
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java159
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java131
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java475
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java264
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java89
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java1269
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java82
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTheme.java576
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java230
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java298
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java276
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java317
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalUtils.java597
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/OceanTheme.java318
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/package.html55
39 files changed, 18208 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java b/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java
new file mode 100644
index 000000000..27c569f03
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java
@@ -0,0 +1,305 @@
+/* DefaultMetalTheme.java --
+ Copyright (C) 2004, 2005 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 gnu.classpath.SystemProperties;
+
+import java.awt.Font;
+
+import javax.swing.UIManager;
+import javax.swing.plaf.ColorUIResource;
+import javax.swing.plaf.FontUIResource;
+
+/**
+ * The default theme for the {@link MetalLookAndFeel}.
+ *
+ * @see MetalLookAndFeel#setCurrentTheme(MetalTheme)
+ */
+public class DefaultMetalTheme extends MetalTheme
+{
+ private static final ColorUIResource PRIMARY1 =
+ new ColorUIResource(102, 102, 153);
+ private static final ColorUIResource PRIMARY2 =
+ new ColorUIResource(153, 153, 204);
+ private static final ColorUIResource PRIMARY3 =
+ new ColorUIResource(204, 204, 255);
+ private static final ColorUIResource SECONDARY1 =
+ new ColorUIResource(102, 102, 102);
+ private static final ColorUIResource SECONDARY2 =
+ new ColorUIResource(153, 153, 153);
+ private static final ColorUIResource SECONDARY3 =
+ new ColorUIResource(204, 204, 204);
+
+ private static final FontUIResource SUB_TEXT_FONT =
+ new FontUIResource("Dialog", Font.PLAIN, 10);
+ private static final FontUIResource SYSTEM_TEXT_FONT =
+ new FontUIResource("Dialog", Font.PLAIN, 12);
+ private static final FontUIResource USER_TEXT_FONT =
+ new FontUIResource("Dialog", Font.PLAIN, 12);
+ private static final FontUIResource WINDOW_TITLE_FONT =
+ new FontUIResource("Dialog", Font.BOLD, 12);
+
+ /**
+ * The control text font for swing.boldMetal=false.
+ */
+ private static final FontUIResource PLAIN_CONTROL_TEXT_FONT =
+ new FontUIResource("Dialog", Font.PLAIN, 12);
+
+ /**
+ * The standard control text font.
+ */
+ private static final FontUIResource BOLD_CONTROL_TEXT_FONT =
+ new FontUIResource("Dialog", Font.BOLD, 12);
+
+ /**
+ * The menu text font for swing.boldMetal=false.
+ */
+ private static final FontUIResource PLAIN_MENU_TEXT_FONT =
+ new FontUIResource("Dialog", Font.PLAIN, 12);
+
+ /**
+ * The menu control text font.
+ */
+ private static final FontUIResource BOLD_MENU_TEXT_FONT =
+ new FontUIResource("Dialog", Font.BOLD, 12);
+
+ /**
+ * Indicates the control text font.
+ */
+ static final int CONTROL_TEXT_FONT = 1;
+
+ /**
+ * Indicates the menu text font.
+ */
+ static final int MENU_TEXT_FONT = 2;
+
+ /**
+ * Creates a new instance of this theme.
+ */
+ public DefaultMetalTheme()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Returns the name of the theme.
+ *
+ * @return <code>"Steel"</code>.
+ */
+ public String getName()
+ {
+ return "Steel";
+ }
+
+ /**
+ * Returns the first primary color for this theme.
+ *
+ * @return The first primary color.
+ */
+ protected ColorUIResource getPrimary1()
+ {
+ return PRIMARY1;
+ }
+
+ /**
+ * Returns the second primary color for this theme.
+ *
+ * @return The second primary color.
+ */
+ protected ColorUIResource getPrimary2()
+ {
+ return PRIMARY2;
+ }
+
+ /**
+ * Returns the third primary color for this theme.
+ *
+ * @return The third primary color.
+ */
+ protected ColorUIResource getPrimary3()
+ {
+ return PRIMARY3;
+ }
+
+ /**
+ * Returns the first secondary color for this theme.
+ *
+ * @return The first secondary color.
+ */
+ protected ColorUIResource getSecondary1()
+ {
+ return SECONDARY1;
+ }
+
+ /**
+ * Returns the second secondary color for this theme.
+ *
+ * @return The second secondary color.
+ */
+ protected ColorUIResource getSecondary2()
+ {
+ return SECONDARY2;
+ }
+
+ /**
+ * Returns the third secondary color for this theme.
+ *
+ * @return The third secondary color.
+ */
+ protected ColorUIResource getSecondary3()
+ {
+ return SECONDARY3;
+ }
+
+ /**
+ * Returns the font used for text on controls. In this case, the font is
+ * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>, unless the
+ * <code>swing.boldMetal</code> UI default is set to {@link Boolean#FALSE}
+ * in which case it is <code>FontUIResource("Dialog", Font.PLAIN, 12)</code>.
+ *
+ * @return The font.
+ */
+ public FontUIResource getControlTextFont()
+ {
+ return getFont(CONTROL_TEXT_FONT);
+ }
+
+ /**
+ * Returns the font used for text in menus. In this case, the font is
+ * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>, unless the
+ * <code>swing.boldMetal</code> UI default is set to {@link Boolean#FALSE}
+ * in which case it is <code>FontUIResource("Dialog", Font.PLAIN, 12)</code>.
+ *
+ * @return The font used for text in menus.
+ */
+ public FontUIResource getMenuTextFont()
+ {
+ return getFont(MENU_TEXT_FONT);
+ }
+
+ /**
+ * Returns the font used for sub text. In this case, the font is
+ * <code>FontUIResource("Dialog", Font.PLAIN, 10)</code>.
+ *
+ * @return The font used for sub text.
+ */
+ public FontUIResource getSubTextFont()
+ {
+ return SUB_TEXT_FONT;
+ }
+
+ /**
+ * Returns the font used for system text. In this case, the font is
+ * <code>FontUIResource("Dialog", Font.PLAIN, 12)</code>.
+ *
+ * @return The font used for system text.
+ */
+ public FontUIResource getSystemTextFont()
+ {
+ return SYSTEM_TEXT_FONT;
+ }
+
+ /**
+ * Returns the font used for user text. In this case, the font is
+ * <code>FontUIResource("Dialog", Font.PLAIN, 12)</code>.
+ *
+ * @return The font used for user text.
+ */
+ public FontUIResource getUserTextFont()
+ {
+ return USER_TEXT_FONT;
+ }
+
+ /**
+ * Returns the font used for window titles. In this case, the font is
+ * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>.
+ *
+ * @return The font used for window titles.
+ */
+ public FontUIResource getWindowTitleFont()
+ {
+ return WINDOW_TITLE_FONT;
+ }
+
+ /**
+ * Returns the appropriate font. The font type to return is identified
+ * by the specified id.
+ *
+ * @param id the font type to return
+ *
+ * @return the correct font
+ */
+ private FontUIResource getFont(int id)
+ {
+ FontUIResource font = null;
+ switch (id)
+ {
+ case CONTROL_TEXT_FONT:
+ if (isBoldMetal())
+ font = BOLD_CONTROL_TEXT_FONT;
+ else
+ font = PLAIN_CONTROL_TEXT_FONT;
+ break;
+ case MENU_TEXT_FONT:
+ if (isBoldMetal())
+ font = BOLD_MENU_TEXT_FONT;
+ else
+ font = PLAIN_MENU_TEXT_FONT;
+ break;
+ // TODO: Add other font types and their mapping here.
+ }
+ return font;
+ }
+
+ /**
+ * Determines if the theme should be bold or not. The theme is bold by
+ * default, this can be turned off by setting the system property
+ * swing.boldMetal to true, or by putting the property with the same name
+ * into the current UIManager's defaults.
+ *
+ * @return <code>true</code>, when the theme is bold, <code>false</code>
+ * otherwise
+ */
+ private boolean isBoldMetal()
+ {
+ Object boldMetal = UIManager.get("swing.boldMetal");
+ return (boldMetal == null || ! Boolean.FALSE.equals(boldMetal))
+ && ! ("false".equals(SystemProperties.getProperty("swing.boldMetal")));
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java
new file mode 100644
index 000000000..253629998
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java
@@ -0,0 +1,1626 @@
+/* MetalBorders.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.Graphics;
+import java.awt.Insets;
+
+import javax.swing.AbstractButton;
+import javax.swing.ButtonModel;
+import javax.swing.JButton;
+import javax.swing.JInternalFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+import javax.swing.border.AbstractBorder;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.plaf.BorderUIResource;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.basic.BasicBorders;
+import javax.swing.text.JTextComponent;
+
+
+/**
+ * A factory class that creates borders for the different Swing components.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+public class MetalBorders
+{
+
+ /** The shared instance for getButtonBorder(). */
+ private static Border buttonBorder;
+
+ /** The shared instance for getToggleButtonBorder(). */
+ private static Border toggleButtonBorder;
+
+ /** The shared instance for getDesktopIconBorder(). */
+ private static Border desktopIconBorder;
+
+ /** The shared instance for getRolloverButtonBorder(). */
+ private static Border toolbarButtonBorder;
+
+ /** The shared instance for getTextFieldBorder(). */
+ private static Border textFieldBorder;
+
+ /** The shared instance for getTextBorder(). */
+ private static Border textBorder;
+
+ /** The shared instance for getRolloverBorder(). */
+ private static Border rolloverBorder;
+
+ /**
+ * A MarginBorder that gets shared by multiple components.
+ * Created on demand by the private helper function {@link
+ * #getMarginBorder()}.
+ */
+ private static BasicBorders.MarginBorder marginBorder;
+
+ /**
+ * <p>A border used for {@link JButton} components.</p>
+ *
+ * <p>This {@link Border} implementation can handle only instances of
+ * {@link AbstractButton} and their subclasses.</p>
+ *
+ * <p>If the Metal Look and Feel's current theme is 'Ocean' the border
+ * will be painted with a special highlight when the mouse cursor if
+ * over the button (ie. the property <code>rollover</code> of the
+ * button's model is <code>true</code>) and is not a <b>direct</b>
+ * child of a {@link JToolBar}.</p>
+ */
+ public static class ButtonBorder extends AbstractBorder implements UIResource
+ {
+ /** The borders insets. */
+ protected static Insets borderInsets = new Insets(3, 3, 3, 3);
+
+ /**
+ * Creates a new instance of <code>ButtonBorder</code>.
+ */
+ public ButtonBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the button border.
+ *
+ * @param c the component for which we paint the border
+ * @param g the Graphics context to use
+ * @param x the X coordinate of the upper left corner of c
+ * @param y the Y coordinate of the upper left corner of c
+ * @param w the width of c
+ * @param h the height of c
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ // With the OceanTheme the button border is painted entirely different.
+ // However, I couldn't figure out how this is determined besides checking
+ // for instanceof OceanTheme. The button painting is definitely not
+ // influenced by a UI default property and it is definitely performed
+ // by the same Border class.
+ if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
+ paintOceanButtonBorder(c, g, x, y, w, h);
+ else
+ paintDefaultButtonBorder(c, g, x, y, w, h);
+ }
+
+ /**
+ * Paints the button border for the DefaultMetalTheme.
+ *
+ * @param c the component (button)
+ * @param g the graphics object to use
+ * @param x the upper left corner of the component, X coordinate
+ * @param y the upper left corner of the component, Y coordinate
+ * @param w the width of the component
+ * @param h the height of the component
+ */
+ private void paintDefaultButtonBorder(Component c, Graphics g, int x,
+ int y, int w, int h)
+ {
+ ButtonModel bmodel = null;
+
+ // The RI will fail with a ClassCastException in such a situation.
+ // This code tries to be more helpful.
+ if (c instanceof AbstractButton)
+ bmodel = ((AbstractButton) c).getModel();
+ else
+ throw new IllegalStateException("A ButtonBorder is supposed to work "
+ + "only with AbstractButton and"
+ + "subclasses.");
+
+ Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ Color light = MetalLookAndFeel.getControlHighlight();
+ Color middle = MetalLookAndFeel.getControl();
+
+ if (c.isEnabled())
+ {
+ // draw dark border
+ g.setColor(darkShadow);
+ g.drawRect(x, y, w - 2, h - 2);
+
+ // If the button is the default button, we paint a special border,
+ // regardless of the pressed state.
+ if (c instanceof JButton && ((JButton) c).isDefaultButton())
+ {
+ g.drawRect(x + 1, y + 1, w - 4, h - 4);
+ // Draw white highlight.
+ g.setColor(light);
+ g.drawLine(x + 2, y + 2, x + w - 4, y + 2);
+ g.drawLine(x + 2, y + 2, x + 2, y + h - 4);
+ g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
+ g.drawLine(x + w - 1, y + 2, x + w - 1, y + h - 1);
+ // Draw crossing pixels.
+ g.setColor(middle);
+ g.fillRect(x + w - 2, y + 2, 1, 1);
+ g.fillRect(x + 2, y + h - 2, 1, 1);
+ }
+ else
+ {
+ // The normal border. This is used when the button is not
+ // pressed or the button is not armed.
+ if (! (bmodel.isPressed() && bmodel.isArmed()))
+ {
+ // draw light border
+ g.setColor(light);
+ g.drawRect(x + 1, y + 1, w - 2, h - 2);
+
+ // draw crossing pixels of both borders
+ g.setColor(middle);
+ g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
+ }
+ // The pressed border. This border is painted only when
+ // the button is both pressed and armed.
+ else
+ {
+ // draw light border
+ g.setColor(light);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+
+ // draw shadow border
+ g.setColor(middle);
+ g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
+
+ // draw crossing pixels of both borders
+ g.setColor(shadow);
+ g.drawRect(x + 1, y + h - 2, 0, 0);
+ g.drawRect(x + w - 2, y + 1, 0, 0);
+ }
+ }
+ }
+ else
+ {
+ // draw disabled border
+ g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
+ g.drawRect(x, y, w - 2, h - 2);
+ }
+ }
+
+ /**
+ * Paints the button border for the OceanTheme.
+ *
+ * @param c the button
+ * @param g the graphics context
+ * @param x the X coordinate of the upper left corner of the painting rect
+ * @param y the Y coordinate of the upper left corner of the painting rect
+ * @param w the width of the painting rect
+ * @param h the height of the painting rect
+ */
+ private void paintOceanButtonBorder(Component c, Graphics g, int x,
+ int y, int w, int h)
+ {
+ ButtonModel bmodel = null;
+
+ // The RI will fail with a ClassCastException in such a situation.
+ // This code tries to be more helpful.
+ if (c instanceof AbstractButton)
+ bmodel = ((AbstractButton) c).getModel();
+ else
+ throw new IllegalStateException("A ButtonBorder is supposed to work "
+ + "only with AbstractButton and"
+ + "subclasses.");
+
+ Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ Color light = MetalLookAndFeel.getControlHighlight();
+ Color middle = MetalLookAndFeel.getControl();
+
+ if (c.isEnabled())
+ {
+ // Paint the pressed border if the button is pressed, or if
+ // the button is the default button. In the OceanTheme, the default
+ // button has the same border as a pressed button.
+ if (bmodel.isPressed() || ((c instanceof JButton)
+ && ((JButton) c).isDefaultButton()))
+ {
+ // Draw fat border.
+ g.setColor(darkShadow);
+ g.drawRect(x, y, w - 1, h - 1);
+ g.drawRect(x + 1, y + 1, w - 3, h - 3);
+ }
+ else if (bmodel.isRollover() && !(c.getParent() instanceof JToolBar))
+ {
+ // Paint a bigger border when the mouse is over the button but
+ // only if it is *not* part of a JToolBar.
+ g.setColor(shadow);
+ g.drawRect(x, y, w - 1, h - 1);
+ g.drawRect(x + 2, y + 2, w - 5, h - 5);
+ g.setColor(darkShadow);
+ g.drawRect(x + 1, y + 1, w - 3, h - 3);
+ }
+ else
+ {
+ g.setColor(darkShadow);
+ g.drawRect(x, y, w - 1, h - 1);
+ }
+ }
+ else
+ {
+ // draw disabled border
+ g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
+ g.drawRect(x, y, w - 2, h - 2);
+ }
+ }
+
+ /**
+ * Returns the insets of the <code>ButtonBorder</code>.
+ *
+ * @param c the component for which the border is used (ignored).
+ *
+ * @return The insets of the <code>ButtonBorder</code>.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return borderInsets;
+ }
+
+ /**
+ * Returns the insets of the <code>ButtonBorder</code> in the specified
+ * <code>newInsets</code> object.
+ *
+ * @param c the component for which the border is used (ignored).
+ * @param newInsets the insets object where to put the values (
+ * <code>null</code> not permitted).
+ *
+ * @return The <code>newInsets</code> reference.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ newInsets.bottom = borderInsets.bottom;
+ newInsets.left = borderInsets.left;
+ newInsets.right = borderInsets.right;
+ newInsets.top = borderInsets.top;
+ return newInsets;
+ }
+ }
+
+ /**
+ * A border used when painting {@link JInternalFrame} instances.
+ */
+ static class DesktopIconBorder extends AbstractBorder
+ implements UIResource
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public DesktopIconBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ if (newInsets == null)
+ newInsets = new Insets(3, 3, 2, 3);
+ else
+ {
+ newInsets.top = 3;
+ newInsets.left = 3;
+ newInsets.bottom = 2;
+ newInsets.right = 3;
+ }
+ return newInsets;
+ }
+
+ /**
+ * 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)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawRect(x, y, w - 1, h - 1);
+ }
+
+ }
+
+ /**
+ * A simple 3D border.
+ */
+ public static class Flush3DBorder extends AbstractBorder
+ implements UIResource
+ {
+ private static final Insets borderInsets = new Insets(2, 2, 2, 2);
+
+ /**
+ * Creates a new border instance.
+ */
+ public Flush3DBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return borderInsets;
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @param newInsets an existing insets instance, that will be populated
+ * with the border insets and returned as the result
+ * (<code>null</code> not permitted).
+ *
+ * @return The <code>newInsets</code> reference.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ newInsets.top = borderInsets.top;
+ newInsets.left = borderInsets.left;
+ newInsets.bottom = borderInsets.bottom;
+ newInsets.right = borderInsets.right;
+ return newInsets;
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component (ignored).
+ * @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)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawRect(x, y, w - 2, h - 2);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawRect(x + 1, y + 1, w - 2, h - 2);
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
+ g.setColor(savedColor);
+ }
+
+ }
+
+ /**
+ * A border used for a {@link JInternalFrame} when it is being used as a
+ * palette.
+ *
+ * @since 1.3
+ */
+ public static class PaletteBorder extends AbstractBorder
+ implements UIResource
+ {
+ private static final Insets borderInsets = new Insets(1, 1, 1, 1);
+
+ /**
+ * Creates a new <code>PaletteBorder</code>.
+ */
+ public PaletteBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return borderInsets;
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @param newInsets an existing insets instance, that will be populated
+ * with the border insets and returned as the result
+ * (<code>null</code> not permitted).
+ *
+ * @return The <code>newInsets</code> reference.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ newInsets.top = borderInsets.top;
+ newInsets.left = borderInsets.left;
+ newInsets.bottom = borderInsets.bottom;
+ newInsets.right = borderInsets.right;
+ return newInsets;
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component (ignored).
+ * @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)
+ {
+ Color savedColor = g.getColor();
+
+ // draw the outline
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.drawRect(x, y, w - 1, h - 1);
+
+ // put 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);
+ g.setColor(savedColor);
+ }
+
+ }
+
+ /**
+ * A border used for the {@link JTextField} component.
+ */
+ public static class TextFieldBorder extends Flush3DBorder
+ implements UIResource
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public TextFieldBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component (ignored).
+ * @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)
+ {
+ boolean enabledTextBorder;
+ if (c instanceof JTextComponent)
+ {
+ JTextComponent tc = (JTextComponent) c;
+ enabledTextBorder = tc.isEnabled() && tc.isEditable();
+ }
+ else
+ enabledTextBorder = false;
+
+ if (enabledTextBorder)
+ super.paintBorder(c, g, x, y, w, h);
+ else
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawRect(x, y, w - 1, h - 1);
+ g.setColor(savedColor);
+ }
+ }
+
+ }
+
+ /**
+ * A border used for the {@link JInternalFrame} component.
+ */
+ public static class InternalFrameBorder extends AbstractBorder
+ implements UIResource
+ {
+ private static final Insets borderInsets = new Insets(5, 5, 5, 5);
+
+ /**
+ * Creates a new border instance.
+ */
+ public InternalFrameBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return borderInsets;
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @param newInsets an existing insets instance, that will be populated
+ * with the border insets and returned as the result
+ * (<code>null</code> not permitted).
+ *
+ * @return The <code>newInsets</code> reference.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ newInsets.top = borderInsets.top;
+ newInsets.left = borderInsets.left;
+ newInsets.bottom = borderInsets.bottom;
+ newInsets.right = borderInsets.right;
+ return newInsets;
+ }
+
+ /**
+ * 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)
+ {
+
+ JInternalFrame f = (JInternalFrame) c;
+ if (f.isSelected())
+ 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 (f.isSelected())
+ 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);
+ }
+
+ }
+
+ /**
+ * A border used for {@link JInternalFrame} components that are
+ * presented as dialogs (by the {@link JOptionPane} class).
+ */
+ public static class OptionDialogBorder extends AbstractBorder
+ implements UIResource
+ {
+
+ /**
+ * Creates a new border instance.
+ */
+ public OptionDialogBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ if (newInsets == null)
+ newInsets = new Insets(3, 3, 3, 3);
+ else
+ {
+ newInsets.top = 3;
+ newInsets.left = 3;
+ newInsets.bottom = 3;
+ newInsets.right = 3;
+ }
+ return newInsets;
+ }
+
+ /**
+ * 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)
+ {
+
+ JInternalFrame f = (JInternalFrame) c;
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ if (f.getContentPane() instanceof JOptionPane)
+ {
+ JOptionPane pane = (JOptionPane) f.getContentPane();
+ int type = pane.getMessageType();
+ if (type == JOptionPane.QUESTION_MESSAGE)
+ {
+ Color bc = UIManager.getColor(
+ "OptionPane.questionDialog.border.background");
+ if (bc != null)
+ g.setColor(bc);
+ }
+ if (type == JOptionPane.WARNING_MESSAGE)
+ {
+ Color bc = UIManager.getColor(
+ "OptionPane.warningDialog.border.background");
+ if (bc != null)
+ g.setColor(bc);
+ }
+ else if (type == JOptionPane.ERROR_MESSAGE)
+ {
+ Color bc = UIManager.getColor(
+ "OptionPane.errorDialog.border.background");
+ if (bc != null)
+ g.setColor(bc);
+ }
+ }
+
+ // fill the border background
+ g.fillRect(x, y, w, 3);
+ g.fillRect(x, y, 3, h);
+ g.fillRect(x + w - 3, y, 3, h);
+ g.fillRect(x, y + h - 3, w, 3);
+
+ // 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);
+
+ }
+
+ }
+
+ /**
+ * A border used for {@link JMenu} and {@link JMenuItem} components.
+ */
+ public static class MenuItemBorder extends AbstractBorder
+ implements UIResource
+ {
+ /** The border insets. */
+ protected static Insets borderInsets = new Insets(2, 2, 2, 2);
+
+ /**
+ * Creates a new border instance.
+ */
+ public MenuItemBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the border for the component. A border is painted only if the
+ * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate of the border area.
+ * @param y the y-coordinate of the border area.
+ * @param w the width of the border area.
+ * @param h the height of the border area.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ Color dark = MetalLookAndFeel.getPrimaryControlDarkShadow();
+ Color light = MetalLookAndFeel.getPrimaryControlHighlight();
+ if (c instanceof JMenu)
+ {
+ JMenu menu = (JMenu) c;
+ if (menu.isSelected())
+ {
+ g.setColor(dark);
+ g.drawLine(x, y, x, y + h);
+ g.drawLine(x, y, x + w, y);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + h);
+ g.setColor(light);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h);
+ }
+ }
+ else if (c instanceof JMenuItem)
+ {
+ JMenuItem item = (JMenuItem) c;
+ if (item.isArmed())
+ {
+ g.setColor(dark);
+ g.drawLine(x, y, x + w, y);
+ g.setColor(light);
+ g.drawLine(x, y + h - 1, x + w, y + h - 1);
+ }
+ else
+ {
+ // Normally we draw a light line on the left.
+ g.setColor(light);
+ g.drawLine(x, y, x, y + h);
+ }
+ }
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return borderInsets;
+ }
+
+ /**
+ * Populates <code>insets</code> with the border insets, then returns it.
+ *
+ * @param c the component (ignored).
+ * @param insets the object to populate with the border insets.
+ *
+ * @return The border insets.
+ *
+ * @throws NullPointerException if <code>insets</code> is <code>null</code>.
+ */
+ public Insets getBorderInsets(Component c, Insets insets)
+ {
+ insets.left = borderInsets.left;
+ insets.top = borderInsets.top;
+ insets.bottom = borderInsets.bottom;
+ insets.right = borderInsets.right;
+ return insets;
+ }
+ }
+
+ /**
+ * A border used for {@link JMenuBar} components.
+ */
+ public static class MenuBarBorder
+ extends AbstractBorder
+ implements UIResource
+ {
+ /** The border insets. */
+ protected static Insets borderInsets = new Insets(1, 0, 1, 0);
+
+ /**
+ * Creates a new border instance.
+ */
+ public MenuBarBorder()
+ {
+ }
+
+ /**
+ * Paints the border for the component. A border is painted only if the
+ * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate of the border area.
+ * @param y the y-coordinate of the border area.
+ * @param w the width of the border area.
+ * @param h the height of the border area.
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ // Although it is not correct to decide on the static property
+ // currentTheme which color to use the RI does it like that.
+ // The trouble is that by simply changing the current theme to
+ // e.g. DefaultMetalLookAndFeel this method will use another color
+ // although a change in painting behavior should be expected only
+ // after setting a new look and feel and updating all components.
+ if(MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
+ g.setColor(UIManager.getColor("MenuBar.borderColor"));
+ else
+ g.setColor(MetalLookAndFeel.getControlShadow());
+
+ g.drawLine(x, y + h - 1, x + w, y + h - 1);
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return borderInsets;
+ }
+
+ /**
+ * Populates <code>insets</code> with the border insets, then returns it.
+ *
+ * @param c the component (ignored).
+ * @param insets the object to populate with the border insets.
+ *
+ * @return The border insets.
+ *
+ * @throws NullPointerException if <code>insets</code> is <code>null</code>.
+ */
+ public Insets getBorderInsets(Component c, Insets insets)
+ {
+ insets.left = borderInsets.left;
+ insets.top = borderInsets.top;
+ insets.bottom = borderInsets.bottom;
+ insets.right = borderInsets.right;
+ return insets;
+ }
+ }
+
+ /**
+ * A border for {@link JScrollPane} components.
+ */
+ public static class ScrollPaneBorder
+ extends AbstractBorder
+ implements UIResource
+ {
+ /** The border insets. */
+ private static Insets insets = new Insets(1, 1, 2, 2);
+
+ /**
+ * Constructs a new ScrollPaneBorder.
+ */
+ public ScrollPaneBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the insets of the border for the Component <code>c</code>.
+ *
+ * @param c the Component for which we return the border insets
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return insets;
+ }
+
+ /**
+ * Paints the border.
+ *
+ * @param c the Component for which the border is painted
+ * @param g the Graphics context
+ * @param x the X coordinate of the upper left corner of the border
+ * @param y the Y coordinate of the upper left corner of the border
+ * @param w the width of the border
+ * @param h the height of the border
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y,
+ int w, int h)
+ {
+ Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ Color light = MetalLookAndFeel.getWhite();
+ Color middle = MetalLookAndFeel.getControl();
+
+ // paint top border line
+ g.setColor(darkShadow);
+ g.drawLine(x, y, x + w - 2, y);
+
+ // paint left border line
+ g.drawLine(x, y, x, y + h - 2);
+
+ // paint right inner border line
+ g.drawLine(x + w - 2, y, x + w - 2, y + h + 1);
+
+ // paint bottom inner border line
+ g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2);
+
+ // draw right outer border line
+ g.setColor(light);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+
+ // draw bottom outer border line
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+
+ // paint the lighter points
+ g.setColor(middle);
+ g.drawLine(x + w - 1, y, x + w - 1, y);
+ g.drawLine(x + w - 2, y + 2, x + w - 2, y + 2);
+ g.drawLine(x, y + h - 1, x, y + h - 1);
+ g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
+
+ }
+
+ }
+
+ /**
+ * A button border that is only visible when the mouse pointer is within
+ * the button's bounds.
+ */
+ public static class RolloverButtonBorder
+ extends MetalBorders.ButtonBorder
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public RolloverButtonBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the border.
+ *
+ * @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)
+ {
+ // TODO: What should be done here? Obviously the ButtonBorder already
+ // handles the rollover state in Sun's impl. Maybe this is only there
+ // for backwards compatibility.
+ super.paintBorder(c, g, x, y, w, h);
+ }
+ }
+
+ /**
+ * This border is used in Toolbar buttons as inner border.
+ */
+ static class RolloverMarginBorder extends AbstractBorder
+ {
+ /** The borders insets. */
+ protected static Insets borderInsets = new Insets(3, 3, 3, 3);
+
+ /**
+ * Creates a new instance of RolloverBorder.
+ */
+ public RolloverMarginBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the insets of the RolloverBorder.
+ *
+ * @param c the component for which the border is used
+ *
+ * @return the insets of the RolloverBorder
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the insets of the RolloverMarginBorder in the specified
+ * Insets object.
+ *
+ * @param c the component for which the border is used
+ * @param newInsets the insets object where to put the values
+ *
+ * @return the insets of the RolloverMarginBorder
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ if (newInsets == null)
+ newInsets = new Insets(0, 0, 0, 0);
+
+ AbstractButton b = (AbstractButton) c;
+ Insets margin = b.getMargin();
+ newInsets.bottom = borderInsets.bottom;
+ newInsets.left = borderInsets.left;
+ newInsets.right = borderInsets.right;
+ newInsets.top = borderInsets.top;
+ return newInsets;
+ }
+ }
+
+ /**
+ * A border implementation for popup menus.
+ */
+ public static class PopupMenuBorder
+ extends AbstractBorder
+ implements UIResource
+ {
+
+ /** The border's insets. */
+ protected static Insets borderInsets = new Insets(3, 1, 2, 1);
+
+ /**
+ * Constructs a new PopupMenuBorder.
+ */
+ public PopupMenuBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the insets of the border, creating a new Insets instance
+ * with each call.
+ *
+ * @param c the component for which we return the border insets
+ * (not used here)
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the insets of the border, using the supplied Insets instance.
+ *
+ * @param c the component for which we return the border insets
+ * (not used here)
+ * @param i the Insets instance to fill with the Insets values
+ */
+ public Insets getBorderInsets(Component c, Insets i)
+ {
+ Insets insets;
+ if (i == null)
+ insets = new Insets(borderInsets.top, borderInsets.left,
+ borderInsets.bottom, borderInsets.right);
+ else
+ {
+ insets = i;
+ insets.top = borderInsets.top;
+ insets.left = borderInsets.left;
+ insets.bottom = borderInsets.bottom;
+ insets.right = borderInsets.right;
+ }
+
+ return insets;
+ }
+
+ /**
+ * Paints the border for component <code>c</code> using the
+ * Graphics context <code>g</code> with the dimension
+ * <code>x, y, w, h</code>.
+ *
+ * @param c the component for which we paint the border
+ * @param g the Graphics context to use
+ * @param x the X coordinate of the upper left corner of c
+ * @param y the Y coordinate of the upper left corner of c
+ * @param w the width of c
+ * @param h the height of c
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
+ Color light = MetalLookAndFeel.getPrimaryControlHighlight();
+
+ // draw dark outer border
+ g.setColor(darkShadow);
+ g.drawRect(x, y, w - 1, h - 1);
+
+ // draw highlighted inner border (only top and left)
+ g.setColor(light);
+ g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
+ }
+
+ }
+
+ /**
+ * A border used for the {@link JToggleButton} component.
+ *
+ * @since 1.3
+ */
+ public static class ToggleButtonBorder
+ extends ButtonBorder
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public ToggleButtonBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the toggle button border.
+ *
+ * @param c the component for which we paint the border
+ * @param g the Graphics context to use
+ * @param x the X coordinate of the upper left corner of c
+ * @param y the Y coordinate of the upper left corner of c
+ * @param w the width of c
+ * @param h the height of c
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
+ int h)
+ {
+ ButtonModel bmodel = null;
+
+ if (c instanceof AbstractButton)
+ bmodel = ((AbstractButton) c).getModel();
+
+ Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ Color light = MetalLookAndFeel.getWhite();
+ Color middle = MetalLookAndFeel.getControl();
+
+ if (c.isEnabled())
+ {
+ // draw dark border
+ g.setColor(darkShadow);
+ g.drawRect(x, y, w - 2, h - 2);
+
+ if (!bmodel.isArmed())
+ {
+ // draw light border
+ g.setColor(light);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ if (bmodel.isSelected())
+ g.setColor(middle);
+ g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+
+ // draw crossing pixels of both borders
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
+ }
+ else
+ {
+ // draw light border
+ g.setColor(light);
+ g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+
+ // draw shadow border
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
+
+ // draw crossing pixels of both borders
+ g.setColor(shadow);
+ g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
+
+ }
+ // draw corners
+ g.setColor(middle);
+ g.drawLine(x, y + h - 1, x, y + h - 1);
+ g.drawLine(x + w - 1, y, x + w - 1, y);
+ }
+ else
+ {
+ // draw disabled border
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawRect(x, y, w - 2, h - 2);
+ }
+ }
+ }
+
+ /**
+ * A border used for the {@link JToolBar} component.
+ */
+ public static class ToolBarBorder extends AbstractBorder
+ implements UIResource, SwingConstants
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public ToolBarBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ *
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, null);
+ }
+
+ /**
+ * Returns the border insets.
+ *
+ * @param c the component (ignored).
+ * @return The border insets.
+ */
+ public Insets getBorderInsets(Component c, Insets newInsets)
+ {
+ JToolBar tb = (JToolBar) c;
+ if (tb.getOrientation() == JToolBar.HORIZONTAL)
+ {
+ if (newInsets == null)
+ newInsets = new Insets(2, 16, 2, 2);
+ else
+ {
+ newInsets.top = 2;
+ newInsets.left = 16;
+ newInsets.bottom = 2;
+ newInsets.right = 2;
+ }
+ return newInsets;
+ }
+ else // assume JToolBar.VERTICAL
+ {
+ if (newInsets == null)
+ newInsets = new Insets(16, 2, 2, 2);
+ else
+ {
+ newInsets.top = 16;
+ newInsets.left = 2;
+ newInsets.bottom = 2;
+ newInsets.right = 2;
+ }
+ return newInsets;
+ }
+
+ }
+
+ /**
+ * 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)
+ {
+
+ JToolBar tb = (JToolBar) c;
+ if (tb.getOrientation() == JToolBar.HORIZONTAL)
+ {
+ MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + 11, y + h - 5,
+ MetalLookAndFeel.getControlHighlight(),
+ MetalLookAndFeel.getControlDarkShadow());
+ }
+ else
+ {
+ MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + w - 5, y + 11,
+ MetalLookAndFeel.getControlHighlight(),
+ MetalLookAndFeel.getControlDarkShadow());
+ }
+ }
+
+ }
+
+ /**
+ * A border for table header cells.
+ *
+ * @since 1.3
+ */
+ public static class TableHeaderBorder extends AbstractBorder
+ {
+ /**
+ * The insets of this border.
+ */
+ // TODO: According to tests that I have done, this is really the border
+ // that should be returned by getBorderInsets(). However, the name
+ // is very distracting. Is there any deeper meaning in it?
+ protected Insets editorBorderInsets;
+
+ /**
+ * Creates a new instance of <code>TableHeaderBorder</code>.
+ */
+ public TableHeaderBorder()
+ {
+ editorBorderInsets = new Insets(1, 1, 1, 1);
+ }
+
+ /**
+ * Return the insets of this border.
+ *
+ * @return the insets of this border
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return editorBorderInsets;
+ }
+
+ /**
+ * Paints the border.
+ *
+ * @param c the component for which to paint the border
+ * @param g the graphics context to use
+ * @param x the x cooridinate of the border rectangle
+ * @param y the y cooridinate of the border rectangle
+ * @param w the width of the border rectangle
+ * @param h the height of the border rectangle
+ */
+ public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
+ {
+ Color dark = MetalLookAndFeel.getControlDarkShadow();
+ Color light = MetalLookAndFeel.getWhite();
+ Color old = g.getColor();
+ g.setColor(light);
+ g.drawLine(x, y, x + w - 2, y);
+ g.drawLine(x, y, x, y + h - 2);
+ g.setColor(dark);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+ g.setColor(old);
+ }
+ }
+
+ /**
+ * Returns a border for Swing buttons in the Metal Look &amp; Feel.
+ *
+ * @return a border for Swing buttons in the Metal Look &amp; Feel
+ */
+ public static Border getButtonBorder()
+ {
+ if (buttonBorder == null)
+ {
+ Border outer = new ButtonBorder();
+ Border inner = getMarginBorder();
+ buttonBorder = new BorderUIResource.CompoundBorderUIResource(outer,
+ inner);
+ }
+ return buttonBorder;
+ }
+
+ /**
+ * Returns a border for use with {@link JToggleButton} components.
+ *
+ * @return A border.
+ *
+ * @since 1.3
+ */
+ public static Border getToggleButtonBorder()
+ {
+ if (toggleButtonBorder == null)
+ {
+ Border outer = new ToggleButtonBorder();
+ Border inner = getMarginBorder();
+ toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
+ outer, inner);
+ }
+ return toggleButtonBorder;
+ }
+
+ /**
+ * Returns a border instance that is used with a {@link JInternalFrame} when
+ * it is in the iconified state.
+ *
+ * @return A border.
+ *
+ * @since 1.3
+ */
+ public static Border getDesktopIconBorder()
+ {
+ if (desktopIconBorder == null)
+ desktopIconBorder = new DesktopIconBorder();
+ return desktopIconBorder;
+ }
+
+ /**
+ * Returns a border for use by the {@link JTextField} component.
+ *
+ * @return A border.
+ *
+ * @since 1.3
+ */
+ public static Border getTextFieldBorder()
+ {
+ if (textFieldBorder == null)
+ {
+ Border inner = getMarginBorder();
+ Border outer = new TextFieldBorder();
+ textFieldBorder =
+ new BorderUIResource.CompoundBorderUIResource(outer, inner);
+ }
+ return textFieldBorder;
+ }
+
+ /**
+ * Returns the border that is used for text components (except text fields,
+ * which use {@link #getTextFieldBorder}.
+ *
+ * @return the border that is used for text components
+ *
+ * @since 1.3
+ */
+ public static Border getTextBorder()
+ {
+ if (textBorder == null)
+ {
+ Border inner = getMarginBorder();
+ Border outer = new Flush3DBorder();
+ textBorder =
+ new BorderUIResource.CompoundBorderUIResource(outer, inner);
+ }
+ return textBorder;
+ }
+
+ /**
+ * Returns a border for Toolbar buttons in the Metal Look &amp; Feel.
+ *
+ * @return a border for Toolbar buttons in the Metal Look &amp; Feel
+ */
+ static Border getToolbarButtonBorder()
+ {
+ if (toolbarButtonBorder == null)
+ {
+ Border outer = new ButtonBorder();
+ Border inner = new RolloverMarginBorder();
+ toolbarButtonBorder = new CompoundBorder(outer, inner);
+ }
+ return toolbarButtonBorder;
+ }
+
+ /**
+ * Returns a shared instance of {@link BasicBorders.MarginBorder}.
+ *
+ * @return a shared instance of {@link BasicBorders.MarginBorder}
+ */
+ static Border getMarginBorder()
+ {
+ if (marginBorder == null)
+ marginBorder = new BasicBorders.MarginBorder();
+ return marginBorder;
+ }
+
+ /**
+ * Returns a shared instance of a compound border for rollover buttons.
+ *
+ * @return A shared border instance.
+ */
+ static Border getRolloverBorder()
+ {
+ if (rolloverBorder == null)
+ {
+ Border outer = new MetalBorders.RolloverButtonBorder();
+ Border inner = MetalBorders.getMarginBorder();
+ rolloverBorder = new BorderUIResource.CompoundBorderUIResource(outer,
+ inner);
+ }
+ return rolloverBorder;
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java
new file mode 100644
index 000000000..7cf84e5f6
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java
@@ -0,0 +1,74 @@
+/* MetalButtonListener.java
+ Copyright (C) 2005 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.beans.PropertyChangeEvent;
+
+import javax.swing.AbstractButton;
+import javax.swing.plaf.basic.BasicButtonListener;
+
+/**
+ * A listener for buttons under the {@link MetalLookAndFeel}.
+ *
+ * @see MetalButtonUI#createButtonListener
+ */
+class MetalButtonListener extends BasicButtonListener
+{
+
+ /**
+ * Creates a new instance.
+ *
+ * @param button the button.
+ */
+ public MetalButtonListener(AbstractButton button)
+ {
+ super(button);
+ }
+
+ /**
+ * Handles property change events.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ super.propertyChange(e);
+ // TODO: What should be done here?
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java
new file mode 100644
index 000000000..974f0a85a
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java
@@ -0,0 +1,298 @@
+/* MetalButtonUI.java
+ Copyright (C) 2005 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.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.AbstractButton;
+import javax.swing.ButtonModel;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JToolBar;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.basic.BasicButtonUI;
+
+/**
+ * A UI delegate for the {@link JButton} component.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+public class MetalButtonUI
+ extends BasicButtonUI
+{
+
+ /**
+ * The shared button UI.
+ */
+ private static MetalButtonUI sharedUI;
+
+ /**
+ * The color used to draw the focus rectangle around the text and/or icon.
+ */
+ protected Color focusColor;
+
+ /**
+ * The background color for the button when it is pressed.
+ */
+ protected Color selectColor;
+
+ /**
+ * The color for disabled button labels.
+ */
+ protected Color disabledTextColor;
+
+ /**
+ * Returns a UI delegate for the specified component.
+ *
+ * @param c the component (should be a subclass of {@link AbstractButton}).
+ *
+ * @return A new instance of <code>MetalButtonUI</code>.
+ */
+ public static ComponentUI createUI(JComponent c)
+ {
+ if (sharedUI == null)
+ sharedUI = new MetalButtonUI();
+ return sharedUI;
+ }
+
+ /**
+ * Creates a new instance.
+ */
+ public MetalButtonUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns the color for the focus border.
+ *
+ * @return the color for the focus border
+ */
+ protected Color getFocusColor()
+ {
+ focusColor = UIManager.getColor(getPropertyPrefix() + "focus");
+ return focusColor;
+ }
+
+ /**
+ * Returns the color that indicates a selected button.
+ *
+ * @return the color that indicates a selected button
+ */
+ protected Color getSelectColor()
+ {
+ selectColor = UIManager.getColor(getPropertyPrefix() + "select");
+ return selectColor;
+ }
+
+ /**
+ * Returns the color for the text label of disabled buttons.
+ *
+ * @return the color for the text label of disabled buttons
+ */
+ protected Color getDisabledTextColor()
+ {
+ disabledTextColor = UIManager.getColor(getPropertyPrefix()
+ + "disabledText");
+ return disabledTextColor;
+ }
+
+ /**
+ * Installs the default settings for the specified button.
+ *
+ * @param button the button.
+ *
+ * @see #uninstallDefaults(AbstractButton)
+ */
+ public void installDefaults(AbstractButton button)
+ {
+ // This is overridden to be public, for whatever reason.
+ super.installDefaults(button);
+ }
+
+ /**
+ * Removes the defaults added by {@link #installDefaults(AbstractButton)}.
+ */
+ public void uninstallDefaults(AbstractButton button)
+ {
+ // This is overridden to be public, for whatever reason.
+ super.uninstallDefaults(button);
+ }
+
+ /**
+ * Paints the background of the button to indicate that it is in the
+ * "pressed" state.
+ *
+ * @param g the graphics context.
+ * @param b the button.
+ */
+ protected void paintButtonPressed(Graphics g, AbstractButton b)
+ {
+ if (b.isContentAreaFilled())
+ {
+ g.setColor(getSelectColor());
+ g.fillRect(0, 0, b.getWidth(), b.getHeight());
+ }
+ }
+
+ /**
+ * Paints the focus rectangle around the button text and/or icon.
+ *
+ * @param g the graphics context.
+ * @param b the button.
+ * @param viewRect the button bounds.
+ * @param textRect the text bounds.
+ * @param iconRect the icon bounds.
+ */
+ protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect,
+ Rectangle textRect, Rectangle iconRect)
+ {
+ if (b.isEnabled() && b.hasFocus() && b.isFocusPainted())
+ {
+ Color savedColor = g.getColor();
+ g.setColor(getFocusColor());
+ Rectangle focusRect = iconRect.union(textRect);
+ g.drawRect(focusRect.x - 1, focusRect.y,
+ focusRect.width + 1, focusRect.height);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * Paints the button text.
+ *
+ * @param g the graphics context.
+ * @param c the button.
+ * @param textRect the text bounds.
+ * @param text the text to display.
+ */
+ protected void paintText(Graphics g, JComponent c, Rectangle textRect,
+ String text)
+ {
+ AbstractButton b = (AbstractButton) c;
+ Font f = b.getFont();
+ g.setFont(f);
+ FontMetrics fm = g.getFontMetrics(f);
+
+ if (b.isEnabled())
+ {
+ g.setColor(b.getForeground());
+ g.drawString(text, textRect.x, textRect.y + fm.getAscent());
+ }
+ else
+ {
+ g.setColor(getDisabledTextColor());
+ g.drawString(text, textRect.x, textRect.y + fm.getAscent());
+ }
+ }
+
+ /**
+ * If the property <code>Button.gradient</code> is set, then a gradient is
+ * painted as background, otherwise the normal superclass behaviour is
+ * called.
+ */
+ public void update(Graphics g, JComponent c)
+ {
+ AbstractButton b = (AbstractButton) c;
+ if ((b.getBackground() instanceof UIResource)
+ && b.isContentAreaFilled() && b.isEnabled())
+ {
+ ButtonModel m = b.getModel();
+ String uiKey = "Button.gradient";
+ if (! isToolbarButton(b))
+ {
+ if (! m.isArmed() && ! m.isPressed() && isDrawingGradient(uiKey))
+ {
+ MetalUtils.paintGradient(g, 0, 0, b.getWidth(), b.getHeight(),
+ SwingConstants.VERTICAL,
+ uiKey);
+ paint(g, c);
+ return;
+ }
+ }
+ else if (m.isRollover() && isDrawingGradient(uiKey))
+ {
+ MetalUtils.paintGradient(g, 0, 0, b.getWidth(), b.getHeight(),
+ SwingConstants.VERTICAL,
+ uiKey);
+ paint(g, c);
+ return;
+ }
+ }
+ // Fallback if we didn't have any of the two above cases.
+ super.update(g, c);
+ }
+
+ /**
+ * Returns <code>true</code> when the button is a toolbar button,
+ * <code>false</code> otherwise.
+ *
+ * @param b the button component to test
+ *
+ * @return <code>true</code> when the button is a toolbar button,
+ * <code>false</code> otherwise
+ */
+ private boolean isToolbarButton(Component b)
+ {
+ Component parent = b.getParent();
+ return parent instanceof JToolBar;
+ }
+
+ /**
+ * Returns <code>true</code> if we should draw the button gradient,
+ * <code>false</code> otherwise.
+ *
+ * @param uiKey the UIManager key for the gradient
+ *
+ * @return <code>true</code> if we should draw the button gradient,
+ * <code>false</code> otherwise
+ */
+ private boolean isDrawingGradient(String uiKey)
+ {
+ return (UIManager.get(uiKey) != null);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java
new file mode 100644
index 000000000..5e0ac066c
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java
@@ -0,0 +1,142 @@
+/* MetalCheckBoxIcon.java -- An icon for JCheckBoxes in the Metal L&F
+ 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.Component;
+import java.awt.Graphics;
+import java.io.Serializable;
+
+import javax.swing.AbstractButton;
+import javax.swing.Icon;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+import javax.swing.plaf.UIResource;
+
+/**
+ * An {@link Icon} used by the {@link MetalCheckBoxUI} class.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+public class MetalCheckBoxIcon
+ implements Icon, UIResource, Serializable
+{
+
+ /** Used to paint the border of the icon. */
+ MetalBorders.ButtonBorder border;
+
+ /**
+ * Creates a new MetalCheckBoxIcon instance.
+ */
+ public MetalCheckBoxIcon()
+ {
+ border = new MetalBorders.ButtonBorder();
+ }
+
+ /**
+ * Draws the check in the CheckBox.
+ *
+ * @param c the component to draw on
+ * @param g the Graphics context to draw with
+ * @param x the X position
+ * @param y the Y position
+ */
+ protected void drawCheck(Component c, Graphics g, int x, int y)
+ {
+ if (c.isEnabled())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(3 + x, 5 + y, 3 + x, 9 + y);
+ g.drawLine(4 + x, 5 + y, 4 + x, 9 + y);
+ g.drawLine(5 + x, 7 + y, 9 + x, 3 + y);
+ g.drawLine(5 + x, 8 + y, 9 + x, 4 + y);
+ }
+
+ /**
+ * Returns the size (both X and Y) of the checkbox icon.
+ *
+ * @return the size of the checkbox icon
+ */
+ protected int getControlSize()
+ {
+ return 13;
+ }
+
+ /**
+ * Returns the width of the icon in pixels.
+ *
+ * @return the width of the icon in pixels
+ */
+ public int getIconWidth()
+ {
+ return getControlSize();
+ }
+
+ /**
+ * Returns the height of the icon in pixels.
+ *
+ * @return the height of the icon in pixels
+ */
+ public int getIconHeight()
+ {
+ return getControlSize();
+ }
+
+ /**
+ * Paints the icon. This first paints the border of the CheckBox and
+ * if the CheckBox is selected it calls {@link #drawCheck} to draw
+ * the check.
+ *
+ * @param c the Component to draw on (gets casted to JCheckBox)
+ * @param g the Graphics context to draw with
+ * @param x the X position
+ * @param y the Y position
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ if (UIManager.get("CheckBox.gradient") != null)
+ MetalUtils.paintGradient(g, x, y, getIconWidth(), getIconHeight(),
+ SwingConstants.VERTICAL, "CheckBox.gradient");
+ border.paintBorder(c, g, x, y, getIconWidth(), getIconHeight());
+
+ AbstractButton b = (AbstractButton) c;
+ if (b.isSelected())
+ drawCheck(b, g, x, y);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java
new file mode 100644
index 000000000..11979e170
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java
@@ -0,0 +1,88 @@
+/* MetalCheckBoxUI.java
+ Copyright (C) 2005 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 javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.UIDefaults;
+import javax.swing.plaf.ComponentUI;
+
+/**
+ * A UI delegate for the {@link JCheckBox} component.
+ */
+public class MetalCheckBoxUI
+ extends MetalRadioButtonUI
+{
+
+ // FIXME: maybe replace by a Map of instances when this becomes stateful
+ /** The shared UI instance for JCheckBoxes. */
+ private static MetalCheckBoxUI instance;
+
+ /**
+ * Constructs a new instance of MetalCheckBoxUI.
+ */
+ public MetalCheckBoxUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a shared instance of <code>MetalCheckBoxUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A shared instance of <code>MetalCheckBoxUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ if (instance == null)
+ instance = new MetalCheckBoxUI();
+ return instance;
+ }
+
+ /**
+ * Returns the prefix for properties defined in the {@link UIDefaults} table.
+ *
+ * @return The property prefix (<code>"CheckBox."</code>).
+ */
+ public String getPropertyPrefix()
+ {
+ return "CheckBox.";
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java
new file mode 100644
index 000000000..8ec8bad72
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java
@@ -0,0 +1,294 @@
+/* MetalComboBoxButton.java
+ Copyright (C) 2005 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.Graphics;
+import java.awt.Insets;
+
+import javax.swing.CellRendererPane;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+import javax.swing.UIManager;
+
+/**
+ * A button used by the {@link MetalComboBoxUI} class.
+ */
+public class MetalComboBoxButton
+ extends JButton
+{
+
+ /** A reference to the JComboBox that the button belongs to. */
+ protected JComboBox comboBox;
+
+ /** A reference to the JList. */
+ protected JList listBox;
+
+ /**
+ * Used for rendering the selected item.
+ */
+ protected CellRendererPane rendererPane;
+
+ /** The button icon. */
+ protected Icon comboIcon;
+
+ /** Display just the icon, or the icon plus the label. */
+ protected boolean iconOnly;
+
+ /**
+ * Creates a new button.
+ *
+ * @param cb the combo that the button is used for (<code>null</code> not
+ * permitted).
+ * @param i the icon displayed on the button.
+ * @param pane the rendering pane.
+ * @param list the list.
+ */
+ public MetalComboBoxButton(JComboBox cb, Icon i, CellRendererPane pane,
+ JList list)
+ {
+ this(cb, i, cb.isEditable(), pane, list);
+ }
+
+ /**
+ * Creates a new button.
+ *
+ * @param cb the combo that the button is used for (<code>null</code> not
+ * permitted).
+ * @param i the icon displayed on the button.
+ * @param onlyIcon a flag that specifies whether the button displays only an
+ * icon, or text as well.
+ * @param pane the rendering pane.
+ * @param list the list.
+ */
+ public MetalComboBoxButton(JComboBox cb, Icon i, boolean onlyIcon,
+ CellRendererPane pane, JList list)
+ {
+ super();
+ if (cb == null)
+ throw new NullPointerException("Null 'cb' argument");
+ comboBox = cb;
+ comboIcon = i;
+ iconOnly = onlyIcon;
+ listBox = list;
+ rendererPane = pane;
+ setRolloverEnabled(false);
+ setEnabled(comboBox.isEnabled());
+ setFocusable(comboBox.isEnabled());
+ }
+
+ /**
+ * Returns the combo box that the button is used with.
+ *
+ * @return The combo box.
+ */
+ public final JComboBox getComboBox()
+ {
+ return comboBox;
+ }
+
+ /**
+ * Sets the combo box that the button is used with.
+ *
+ * @param cb the combo box.
+ */
+ public final void setComboBox(JComboBox cb)
+ {
+ comboBox = cb;
+ }
+
+ /**
+ * Returns the icon displayed by the button. By default, this will be an
+ * instance of {@link MetalComboBoxIcon}.
+ *
+ * @return The icon displayed by the button.
+ */
+ public final Icon getComboIcon()
+ {
+ return comboIcon;
+ }
+
+ /**
+ * Sets the icon displayed by the button.
+ *
+ * @param i the icon.
+ */
+ public final void setComboIcon(Icon i)
+ {
+ comboIcon = i;
+ }
+
+ /**
+ * Returns a flag that controls whether the button displays an icon only,
+ * or text as well.
+ *
+ * @return A boolean.
+ */
+ public final boolean isIconOnly()
+ {
+ return iconOnly;
+ }
+
+ /**
+ * Sets the flag that controls whether the button displays an icon only,
+ * or text as well.
+ *
+ * @param isIconOnly the flag.
+ */
+ public final void setIconOnly(boolean isIconOnly)
+ {
+ iconOnly = isIconOnly;
+ }
+
+ /**
+ * Returns <code>false</code>, to indicate that this component is not part
+ * of the focus traversal group.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isFocusTraversable()
+ {
+ return false;
+ }
+
+ /**
+ * Enables or disables the button.
+ *
+ * @param enabled the new status.
+ */
+ public void setEnabled(boolean enabled)
+ {
+ super.setEnabled(enabled);
+ if (enabled)
+ {
+ setBackground(comboBox.getBackground());
+ setForeground(comboBox.getForeground());
+ }
+ else
+ {
+ setBackground(UIManager.getColor("ComboBox.disabledBackground"));
+ setForeground(UIManager.getColor("ComboBox.disabledForeground"));
+ }
+ }
+
+ /**
+ * Paints the component.
+ *
+ * @param g the graphics device.
+ */
+ public void paintComponent(Graphics g)
+ {
+ super.paintComponent(g);
+ Insets insets = this.getInsets();
+ int w = getWidth() - (insets.left + insets.right);
+ int h = getHeight() - (insets.top + insets.bottom);
+ if (h > 0 && w > 0)
+ {
+ int x1 = insets.left;
+ int y1 = insets.top;
+ int x2 = x1 + (w - 1);
+ int y2 = y1 + (h - 1);
+ int iconWidth = 0;
+ int iconX = x2;
+ if (comboIcon != null)
+ {
+ iconWidth = comboIcon.getIconWidth();
+ int iconHeight = comboIcon.getIconHeight();
+ int iconY;
+ if (iconOnly)
+ {
+ iconX = getWidth() / 2 - iconWidth / 2;
+ iconY = getHeight() / 2 - iconHeight / 2;
+ }
+ else
+ {
+ iconX = x1 + (w - 1) - iconWidth;
+ iconY = y1 + (y2 - y1) / 2 - iconHeight / 2;
+ }
+ comboIcon.paintIcon(this, g, iconX, iconY);
+ if (this.hasFocus())
+ {
+ g.setColor(MetalLookAndFeel.getFocusColor());
+ g.drawRect(x1 - 1, y1 - 1, w + 3, h + 1);
+ }
+ }
+ if (! iconOnly && comboBox != null)
+ {
+ ListCellRenderer renderer = comboBox.getRenderer();
+ boolean pressed = this.getModel().isPressed();
+ Component comp = renderer.getListCellRendererComponent(listBox,
+ comboBox.getSelectedItem(), -1, false, false);
+ comp.setFont(rendererPane.getFont());
+
+ if ((model.isArmed() && model.isPressed())
+ || (comboBox.isFocusOwner() && !comboBox.isPopupVisible()))
+ {
+ if (isOpaque())
+ {
+ comp.setBackground(UIManager.getColor("Button.select"));
+ comp.setForeground(comboBox.getForeground());
+ }
+ }
+ else if (! comboBox.isEnabled())
+ {
+ if (this.isOpaque())
+ {
+ Color dbg =
+ UIManager.getColor("ComboBox.disabledBackground");
+ comp.setBackground(dbg);
+ Color dfg =
+ UIManager.getColor("ComboBox.disabledForeground");
+ comp.setForeground(dfg);
+ }
+ }
+ else
+ {
+ comp.setForeground(comboBox.getForeground());
+ comp.setBackground(comboBox.getBackground());
+ }
+ int wr = w - (insets.right + iconWidth);
+ rendererPane.paintComponent(g, comp, this, x1, y1, wr, h);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java
new file mode 100644
index 000000000..8872d74e2
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java
@@ -0,0 +1,190 @@
+/* MetalComboBoxEditor.java
+ Copyright (C) 2005 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.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+
+import javax.swing.JTextField;
+import javax.swing.border.AbstractBorder;
+import javax.swing.plaf.basic.BasicComboBoxEditor;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+
+/**
+ * An editor used by the {@link MetalComboBoxUI} class.
+ */
+public class MetalComboBoxEditor extends BasicComboBoxEditor
+{
+ /**
+ * A border used for the {@link JTextField} component.
+ */
+ static class MetalComboBoxEditorBorder extends AbstractBorder
+ {
+ /**
+ * Creates a new border instance.
+ */
+ public MetalComboBoxEditorBorder()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the border for the specified component.
+ *
+ * @param c the component (ignored).
+ * @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)
+ {
+ g.translate(x, y);
+ if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(1, 1, w - 2, 1);
+ g.drawLine(1, 1, 1, h - 2);
+ g.drawLine(1, h - 2, w - 1, h - 2);
+ g.drawLine(w - 1, 1, w - 1, h - 2);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(0, 0, 0, h - 2);
+ g.drawLine(0, h - 2, w - 1, h - 2);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 1, w - 1, 1);
+ g.drawLine(1, 1, 1, h - 1);
+ g.drawLine(1, h - 1, w - 1, h - 1);
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 2, 1, h - 2);
+ }
+ g.translate(-x, -y);
+ }
+
+ /**
+ * Measures the width of this border.
+ *
+ * @param c the component whose border is to be measured.
+ *
+ * @return an Insets object whose <code>left</code>, <code>right</code>,
+ * <code>top</code> and <code>bottom</code> fields indicate the
+ * width of the border at the respective edge, which is zero
+ * for the default implementation provided by AbstractButton.
+ *
+ * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return editorBorderInsets;
+ }
+ }
+
+ /**
+ * A subclass of {@link MetalComboBoxEditor} that implements the
+ * {@link javax.swing.plaf.UIResource} interface.
+ */
+ public static class UIResource extends MetalComboBoxEditor
+ implements javax.swing.plaf.UIResource
+ {
+ /**
+ * Creates a new instance.
+ */
+ public UIResource()
+ {
+ // Nothing to do here.
+ }
+ }
+
+ /**
+ * A special textfield implementation for the MetalComboBoxEditor.
+ */
+ private class EditorTextField extends JTextField
+ {
+ EditorTextField(String s, int columns)
+ {
+ super(s, columns);
+ }
+
+ /**
+ * Tests seem to show that the textfield in MetalComboBoxEditors have
+ * a height + 4.
+ */
+ public Dimension getPreferredSize()
+ {
+ Dimension size = super.getPreferredSize();
+ size.height += 4;
+ return size;
+ }
+
+ /**
+ * Tests seem to show that the textfield in MetalComboBoxEditors have
+ * a height + 4.
+ */
+ public Dimension getMinimumSize()
+ {
+ Dimension size = super.getMinimumSize();
+ size.height += 4;
+ return size;
+ }
+ }
+
+ /** The editor's border insets. */
+ protected static Insets editorBorderInsets = new Insets(2, 2, 2, 0);
+
+ /**
+ * Creates a new editor.
+ */
+ public MetalComboBoxEditor()
+ {
+ editor = new EditorTextField("", 9);
+ editor.setBorder(new MetalComboBoxEditorBorder());
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java
new file mode 100644
index 000000000..45c8eadc5
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java
@@ -0,0 +1,102 @@
+/* MetalComboBoxIcon.java
+ Copyright (C) 2005 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.Graphics;
+import java.io.Serializable;
+
+import javax.swing.Icon;
+
+/**
+ * An icon used by the {@link MetalComboBoxUI} class.
+ */
+public class MetalComboBoxIcon implements Icon, Serializable
+{
+
+ /**
+ * Creates a new icon.
+ */
+ public MetalComboBoxIcon()
+ {
+ // nothing required.
+ }
+
+ /**
+ * Returns the icon width, which for this icon is 10 pixels.
+ *
+ * @return <code>10</code>.
+ */
+ public int getIconWidth()
+ {
+ return 10;
+ }
+
+ /**
+ * Returns the icon height, which for this icon is 5 pixels.
+ *
+ * @return <code>5</code>.
+ */
+ public int getIconHeight()
+ {
+ return 5;
+ }
+
+ /**
+ * Paints the icon at the location (x, y).
+ *
+ * @param c the combo box (ignored here).
+ * @param g the graphics device.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ if (c.isEnabled())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ for (int i = 0; i < 5; i++)
+ g.drawLine(x + i, y + i, x + 9 - i, y + i);
+ g.setColor(savedColor);
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java
new file mode 100644
index 000000000..b9019b70d
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java
@@ -0,0 +1,372 @@
+/* MetalComboBoxUI.java
+ Copyright (C) 2005 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.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.ComboBoxEditor;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicComboBoxUI;
+import javax.swing.plaf.basic.BasicComboPopup;
+import javax.swing.plaf.basic.ComboPopup;
+
+
+/**
+ * A UI delegate for the {@link JComboBox} component.
+ */
+public class MetalComboBoxUI extends BasicComboBoxUI
+{
+ /**
+ * A layout manager that arranges the editor component (if active) and the
+ * button that make up the combo box.
+ */
+ public class MetalComboBoxLayoutManager
+ extends BasicComboBoxUI.ComboBoxLayoutManager
+ {
+ /**
+ * Creates a new instance of the layout manager.
+ */
+ public MetalComboBoxLayoutManager()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Arranges the editor (if visible) and button that comprise the combo
+ * box.
+ *
+ * @param parent the parent.
+ */
+ public void layoutContainer(Container parent)
+ {
+ layoutComboBox(parent, this);
+ }
+
+ /**
+ * Calls the <code>layoutContainer(Container)</code> method in the super
+ * class.
+ *
+ * @param parent the container.
+ */
+ public void superLayout(Container parent)
+ {
+ super.layoutContainer(parent);
+ }
+ }
+
+ /**
+ * A listener used to handle property changes in the {@link JComboBox}
+ * component, to ensure that the UI delegate accurately reflects the current
+ * state in the rendering onscreen.
+ */
+ public class MetalPropertyChangeListener
+ extends BasicComboBoxUI.PropertyChangeHandler
+ {
+ /**
+ * Creates a new listener.
+ */
+ public MetalPropertyChangeListener()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles a property change event, updating the UI components as
+ * appropriate.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ super.propertyChange(e);
+ String name = e.getPropertyName();
+ if (name.equals("editable"))
+ editablePropertyChanged(e);
+ else if (name.equals("enabled"))
+ {
+ if (arrowButton instanceof MetalComboBoxButton)
+ {
+ arrowButton.setFocusable(!comboBox.isEditable()
+ && comboBox.isEnabled());
+ comboBox.repaint();
+ }
+ }
+ else if (name.equals("background"))
+ {
+ Color c = (Color) e.getNewValue();
+ arrowButton.setBackground(c);
+ listBox.setBackground(c);
+ }
+ else if (name.equals("foreground"))
+ {
+ Color c = (Color) e.getNewValue();
+ arrowButton.setForeground(c);
+ listBox.setForeground(c);
+ }
+ }
+ }
+
+ /**
+ * A popup menu for the combo-box.
+ *
+ * @see #createPopup()
+ *
+ * @deprecated 1.4
+ */
+ public class MetalComboPopup extends BasicComboPopup
+ {
+ /**
+ * Creates a new popup.
+ *
+ * @param cBox the combo box.
+ */
+ public MetalComboPopup(JComboBox cBox)
+ {
+ super(cBox);
+ }
+
+ public void delegateFocus(MouseEvent e)
+ {
+ super.delegateFocus(e);
+ }
+ }
+
+ /**
+ * Constructs a new instance of MetalComboBoxUI.
+ */
+ public MetalComboBoxUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns an instance of MetalComboBoxUI.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return an instance of MetalComboBoxUI
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalComboBoxUI();
+ }
+
+ /**
+ * Creates an editor for the combo box.
+ *
+ * @return An editor.
+ */
+ protected ComboBoxEditor createEditor()
+ {
+ return new MetalComboBoxEditor.UIResource();
+ }
+
+ /**
+ * Creates a popup for the combo box.
+ *
+ * @return A popup.
+ */
+ protected ComboPopup createPopup()
+ {
+ return super.createPopup();
+ }
+
+ /**
+ * Creates a new button for use in rendering the JComboBox.
+ *
+ * @return A button.
+ */
+ protected JButton createArrowButton()
+ {
+ JButton button = new MetalComboBoxButton(comboBox, new MetalComboBoxIcon(),
+ currentValuePane, listBox);
+ button.setMargin(new Insets(0, 1, 1, 3));
+ return button;
+ }
+
+ /**
+ * Creates a new property change listener.
+ *
+ * @return A new property change listener.
+ */
+ public PropertyChangeListener createPropertyChangeListener()
+ {
+ return new MetalPropertyChangeListener();
+ }
+
+ public void paint(Graphics g, JComponent c)
+ {
+ // do nothing, the button and text field are painted elsewhere
+ }
+
+ /**
+ * Updates the button and text field to reflect a change in the 'editable'
+ * property.
+ *
+ * @param e the event.
+ *
+ * @deprecated 1.4
+ */
+ protected void editablePropertyChanged(PropertyChangeEvent e)
+ {
+ if (arrowButton instanceof MetalComboBoxButton)
+ {
+ MetalComboBoxButton b = (MetalComboBoxButton) arrowButton;
+ b.setIconOnly(comboBox.isEditable());
+ b.setFocusable(!comboBox.isEditable() && comboBox.isEnabled());
+ comboBox.repaint();
+ }
+ }
+
+ /**
+ * Creates a new layout manager for the UI delegate.
+ *
+ * @return A new layout manager.
+ */
+ protected LayoutManager createLayoutManager()
+ {
+ return new MetalComboBoxLayoutManager();
+ }
+
+ /**
+ * Not used in Classpath.
+ *
+ * @deprecated 1.4
+ */
+ protected void removeListeners()
+ {
+ // no longer used in JDK 1.4
+ }
+
+ /**
+ * Returns the minimum size for the combo.
+ *
+ * @param c the component
+ *
+ * @return The minimum size for the combo box.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ if (!isMinimumSizeDirty)
+ return new Dimension(cachedMinimumSize);
+
+ Dimension d;
+ if (!comboBox.isEditable() && arrowButton != null
+ && arrowButton instanceof MetalComboBoxButton)
+ {
+ MetalComboBoxButton b = (MetalComboBoxButton) arrowButton;
+ d = getDisplaySize();
+ Insets arrowInsets = b.getInsets();
+ Insets comboInsets = comboBox.getInsets();
+ Icon icon = b.getComboIcon();
+ d.width += comboInsets.left + comboInsets.right;
+ d.width += arrowInsets.left + arrowInsets.right;
+ d.width += arrowInsets.right + icon.getIconWidth();
+ d.height += comboInsets.top + comboInsets.bottom;
+ d.height += arrowInsets.top + arrowInsets.bottom;
+ }
+ else if (comboBox.isEditable() && arrowButton != null && editor != null)
+ {
+ d = super.getMinimumSize(c);
+ Insets arrowMargin = arrowButton.getMargin();
+ d.height += arrowMargin.top + arrowMargin.bottom;
+ d.width += arrowMargin.left + arrowMargin.right;
+ }
+ else
+ {
+ d = super.getMinimumSize(c);
+ }
+ cachedMinimumSize.setSize(d.width, d.height);
+ isMinimumSizeDirty = false;
+ return new Dimension(cachedMinimumSize);
+ }
+
+ /**
+ * Configures the editor for this combo box.
+ */
+ public void configureEditor()
+ {
+ super.configureEditor();
+ if (popupKeyListener != null)
+ editor.removeKeyListener(popupKeyListener);
+ if (focusListener != null)
+ editor.addFocusListener(focusListener);
+ }
+
+ /**
+ * Unconfigures the editor for this combo box.
+ */
+ public void unconfigureEditor()
+ {
+ super.unconfigureEditor();
+ if (focusListener != null)
+ editor.removeFocusListener(focusListener);
+ }
+
+ /**
+ * Lays out the ComboBox
+ */
+ public void layoutComboBox(Container parent,
+ MetalComboBoxUI.MetalComboBoxLayoutManager manager)
+ {
+ if (comboBox.isEditable())
+ manager.superLayout(parent);
+ else if (arrowButton != null)
+ {
+ Insets comboInsets = comboBox.getInsets();
+ int width = comboBox.getWidth();
+ int height = comboBox.getHeight();
+ arrowButton.setBounds(comboInsets.left, comboInsets.top,
+ width - (comboInsets.left + comboInsets.right),
+ height - (comboInsets.top + comboInsets.bottom));
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java
new file mode 100644
index 000000000..0c1163a8e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java
@@ -0,0 +1,72 @@
+/* MetalDesktopIconUI.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 javax.swing.JComponent;
+import javax.swing.JInternalFrame;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicDesktopIconUI;
+
+/**
+ * A UI delegate for the {@link JInternalFrame.JDesktopIcon} component.
+ */
+public class MetalDesktopIconUI
+ extends BasicDesktopIconUI
+{
+
+ /**
+ * Constructs a new instance of <code>MetalDesktopIconUI</code>.
+ */
+ public MetalDesktopIconUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new <code>MetalDesktopIconUI</code> instance.
+ *
+ * @param component the component (ignored).
+ *
+ * @return A new <code>MetalDesktopIconUI</code> instance.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalDesktopIconUI();
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java
new file mode 100644
index 000000000..df49edf61
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java
@@ -0,0 +1,2120 @@
+/* MetalFileChooserUI.java --
+ Copyright (C) 2005 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.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.Rectangle;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Date;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.AbstractListModel;
+import javax.swing.ActionMap;
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import javax.swing.ListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.filechooser.FileFilter;
+import javax.swing.filechooser.FileSystemView;
+import javax.swing.filechooser.FileView;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicFileChooserUI;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.DefaultTableModel;
+
+
+/**
+ * A UI delegate for the {@link JFileChooser} component. This class is only
+ * partially implemented and is not usable yet.
+ */
+public class MetalFileChooserUI
+ extends BasicFileChooserUI
+{
+
+ /**
+ * A renderer for the files and directories in the file chooser table.
+ */
+ class TableFileRenderer
+ extends DefaultTableCellRenderer
+ {
+
+ /**
+ * Creates a new renderer.
+ */
+ public TableFileRenderer()
+ {
+ super();
+ }
+
+ /**
+ * Returns a component that can render the specified value.
+ *
+ * @param table the table
+ * @param value the string value of the cell
+ * @param isSelected is the item selected?
+ * @param hasFocus does the item have the focus?
+ * @param row the row
+ * @param column the column
+ *
+ * @return The renderer.
+ */
+ public Component getTableCellRendererComponent(JTable table, Object value,
+ boolean isSelected, boolean hasFocus, int row, int column)
+ {
+ if (column == 0)
+ {
+ FileView v = getFileView(getFileChooser());
+ ListModel lm = fileList.getModel();
+ if (row < lm.getSize())
+ setIcon(v.getIcon((File) lm.getElementAt(row)));
+ }
+ else
+ setIcon(null);
+
+ setText(value.toString());
+ setOpaque(true);
+ setEnabled(table.isEnabled());
+ setFont(fileList.getFont());
+
+ if (startEditing && column == 0 || !isSelected)
+ {
+ setBackground(table.getBackground());
+ setForeground(table.getForeground());
+ }
+ else
+ {
+ setBackground(table.getSelectionBackground());
+ setForeground(table.getSelectionForeground());
+ }
+
+ if (hasFocus)
+ setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
+ else
+ setBorder(noFocusBorder);
+
+ return this;
+ }
+ }
+
+ /**
+ * ActionListener for the list view.
+ */
+ class ListViewActionListener implements ActionListener
+ {
+
+ /**
+ * This method is invoked when an action occurs.
+ *
+ * @param e -
+ * the <code>ActionEvent</code> that occurred
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ if (!listView)
+ {
+ int[] index = fileTable.getSelectedRows();
+ listView = true;
+ JFileChooser fc = getFileChooser();
+ fc.remove(fileTablePanel);
+ createList(fc);
+
+ fileList.getSelectionModel().clearSelection();
+ if (index.length > 0)
+ for (int i = 0; i < index.length; i++)
+ fileList.getSelectionModel().addSelectionInterval(index[i], index[i]);
+
+ fc.add(fileListPanel, BorderLayout.CENTER);
+ fc.revalidate();
+ fc.repaint();
+ }
+ }
+ }
+
+ /**
+ * ActionListener for the details view.
+ */
+ class DetailViewActionListener implements ActionListener
+ {
+
+ /**
+ * This method is invoked when an action occurs.
+ *
+ * @param e -
+ * the <code>ActionEvent</code> that occurred
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ if (listView)
+ {
+ int[] index = fileList.getSelectedIndices();
+ JFileChooser fc = getFileChooser();
+ listView = false;
+ fc.remove(fileListPanel);
+
+ if (fileTable == null)
+ createDetailsView(fc);
+ else
+ updateTable();
+
+ fileTable.getSelectionModel().clearSelection();
+ if (index.length > 0)
+ {
+ for (int i = 0; i < index.length; i++)
+ fileTable.getSelectionModel().addSelectionInterval(index[i], index[i]);
+ }
+
+ fc.add(fileTablePanel, BorderLayout.CENTER);
+ fc.revalidate();
+ fc.repaint();
+ }
+ }
+ }
+
+ /**
+ * A property change listener.
+ */
+ class MetalFileChooserPropertyChangeListener
+ implements PropertyChangeListener
+ {
+ /**
+ * Default constructor.
+ */
+ public MetalFileChooserPropertyChangeListener()
+ {
+ }
+
+ /**
+ * Handles a property change event.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ JFileChooser filechooser = getFileChooser();
+
+ String n = e.getPropertyName();
+ if (n.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY))
+ {
+ int mode = -1;
+ if (filechooser.isMultiSelectionEnabled())
+ mode = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION;
+ else
+ mode = ListSelectionModel.SINGLE_SELECTION;
+
+ if (listView)
+ fileList.setSelectionMode(mode);
+ else
+ fileTable.setSelectionMode(mode);
+ }
+ else if (n.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY))
+ {
+ File file = filechooser.getSelectedFile();
+
+ if (file != null
+ && filechooser.getDialogType() == JFileChooser.SAVE_DIALOG)
+ {
+ if (file.isDirectory() && filechooser.isTraversable(file))
+ {
+ directoryLabel = look;
+ dirLabel.setText(directoryLabel);
+ filechooser.setApproveButtonText(openButtonText);
+ filechooser.setApproveButtonToolTipText(openButtonToolTipText);
+ }
+ else if (file.isFile())
+ {
+ directoryLabel = save;
+ dirLabel.setText(directoryLabel);
+ filechooser.setApproveButtonText(saveButtonText);
+ filechooser.setApproveButtonToolTipText(saveButtonToolTipText);
+ }
+ }
+
+ if (file == null)
+ setFileName(null);
+ else if (file.isFile() || filechooser.getFileSelectionMode()
+ != JFileChooser.FILES_ONLY)
+ setFileName(file.getName());
+ int index = -1;
+ index = getModel().indexOf(file);
+ if (index >= 0)
+ {
+ if (listView)
+ {
+ fileList.setSelectedIndex(index);
+ fileList.ensureIndexIsVisible(index);
+ fileList.revalidate();
+ fileList.repaint();
+ }
+ else
+ {
+ fileTable.getSelectionModel().addSelectionInterval(index, index);
+ fileTable.scrollRectToVisible(fileTable.getCellRect(index, 0, true));
+ fileTable.revalidate();
+ fileTable.repaint();
+ }
+ }
+ }
+
+ else if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY))
+ {
+ if (listView)
+ {
+ fileList.clearSelection();
+ fileList.revalidate();
+ fileList.repaint();
+ }
+ else
+ {
+ fileTable.clearSelection();
+ fileTable.revalidate();
+ fileTable.repaint();
+ }
+
+ setDirectorySelected(false);
+ File currentDirectory = filechooser.getCurrentDirectory();
+ setDirectory(currentDirectory);
+ boolean hasParent = currentDirectory.getParentFile() != null;
+ getChangeToParentDirectoryAction().setEnabled(hasParent);
+ }
+
+ else if (n.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY))
+ {
+ filterModel.propertyChange(e);
+ }
+ else if (n.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
+ {
+ filterModel.propertyChange(e);
+ }
+ else if (n.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)
+ || n.equals(JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY))
+ {
+ Window owner = SwingUtilities.windowForComponent(filechooser);
+ if (owner instanceof JDialog)
+ ((JDialog) owner).setTitle(getDialogTitle(filechooser));
+ approveButton.setText(getApproveButtonText(filechooser));
+ approveButton.setToolTipText(
+ getApproveButtonToolTipText(filechooser));
+ approveButton.setMnemonic(getApproveButtonMnemonic(filechooser));
+ }
+
+ else if (n.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY))
+ approveButton.setText(getApproveButtonText(filechooser));
+
+ else if (n.equals(
+ JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY))
+ approveButton.setToolTipText(getApproveButtonToolTipText(filechooser));
+
+ else if (n.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY))
+ approveButton.setMnemonic(getApproveButtonMnemonic(filechooser));
+
+ else if (n.equals(
+ JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY))
+ {
+ if (filechooser.getControlButtonsAreShown())
+ {
+ topPanel.add(controls, BorderLayout.EAST);
+ }
+ else
+ topPanel.remove(controls);
+ topPanel.revalidate();
+ topPanel.repaint();
+ topPanel.doLayout();
+ }
+
+ else if (n.equals(
+ JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY))
+ {
+ if (filechooser.isAcceptAllFileFilterUsed())
+ filechooser.addChoosableFileFilter(
+ getAcceptAllFileFilter(filechooser));
+ else
+ filechooser.removeChoosableFileFilter(
+ getAcceptAllFileFilter(filechooser));
+ }
+
+ else if (n.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY))
+ {
+ JComponent old = (JComponent) e.getOldValue();
+ if (old != null)
+ getAccessoryPanel().remove(old);
+ JComponent newval = (JComponent) e.getNewValue();
+ if (newval != null)
+ getAccessoryPanel().add(newval);
+ }
+
+ if (n.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
+ || n.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)
+ || n.equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY))
+ {
+ // Remove editing component
+ if (fileTable != null)
+ fileTable.removeAll();
+ if (fileList != null)
+ fileList.removeAll();
+ startEditing = false;
+
+ // Set text on button back to original.
+ if (filechooser.getDialogType() == JFileChooser.SAVE_DIALOG)
+ {
+ directoryLabel = save;
+ dirLabel.setText(directoryLabel);
+ filechooser.setApproveButtonText(saveButtonText);
+ filechooser.setApproveButtonToolTipText(saveButtonToolTipText);
+ }
+
+ rescanCurrentDirectory(filechooser);
+ }
+
+ filechooser.revalidate();
+ filechooser.repaint();
+ }
+ }
+
+ /**
+ * A combo box model containing the selected directory and all its parent
+ * directories.
+ */
+ protected class DirectoryComboBoxModel
+ extends AbstractListModel
+ implements ComboBoxModel
+ {
+ /** Storage for the items in the model. */
+ private List items;
+
+ /** The index of the selected item. */
+ private int selectedIndex;
+
+ /**
+ * Creates a new model.
+ */
+ public DirectoryComboBoxModel()
+ {
+ items = new java.util.ArrayList();
+ selectedIndex = -1;
+ }
+
+ /**
+ * Returns the number of items in the model.
+ *
+ * @return The number of items in the model.
+ */
+ public int getSize()
+ {
+ return items.size();
+ }
+
+ /**
+ * Returns the item at the specified index.
+ *
+ * @param index the item index.
+ *
+ * @return The item.
+ */
+ public Object getElementAt(int index)
+ {
+ return items.get(index);
+ }
+
+ /**
+ * Returns the depth of the item at the given <code>index</code>.
+ *
+ * @param index the item index.
+ *
+ * @return The depth.
+ */
+ public int getDepth(int index)
+ {
+ return Math.max(index, 0);
+ }
+
+ /**
+ * Returns the selected item, or <code>null</code> if no item is selected.
+ *
+ * @return The selected item, or <code>null</code>.
+ */
+ public Object getSelectedItem()
+ {
+ if (selectedIndex >= 0)
+ return items.get(selectedIndex);
+ else
+ return null;
+ }
+
+ /**
+ * Sets the selected item. This clears all the directories from the
+ * existing list, and repopulates it with the new selected directory
+ * and all its parent directories.
+ *
+ * @param selectedDirectory the selected directory.
+ */
+ public void setSelectedItem(Object selectedDirectory)
+ {
+ items.clear();
+ FileSystemView fsv = getFileChooser().getFileSystemView();
+ File parent = (File) selectedDirectory;
+ while (parent != null)
+ {
+ items.add(0, parent);
+ parent = fsv.getParentDirectory(parent);
+ }
+ selectedIndex = items.indexOf(selectedDirectory);
+ fireContentsChanged(this, 0, items.size() - 1);
+ }
+
+ }
+
+ /**
+ * Handles changes to the selection in the directory combo box.
+ */
+ protected class DirectoryComboBoxAction
+ extends AbstractAction
+ {
+ /**
+ * Creates a new action.
+ */
+ protected DirectoryComboBoxAction()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles the action event.
+ *
+ * @param e the event.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ JFileChooser fc = getFileChooser();
+ fc.setCurrentDirectory((File) directoryModel.getSelectedItem());
+ }
+ }
+
+ /**
+ * A renderer for the items in the directory combo box.
+ */
+ class DirectoryComboBoxRenderer
+ extends DefaultListCellRenderer
+ {
+ /**
+ * This is the icon that is displayed in the combobox. This wraps
+ * the standard icon and adds indendation.
+ */
+ private IndentIcon indentIcon;
+
+ /**
+ * Creates a new renderer.
+ */
+ public DirectoryComboBoxRenderer(JFileChooser fc)
+ {
+ indentIcon = new IndentIcon();
+ }
+
+ /**
+ * Returns a component that can be used to paint the given value within
+ * the list.
+ *
+ * @param list the list.
+ * @param value the value (a {@link File}).
+ * @param index the item index.
+ * @param isSelected is the item selected?
+ * @param cellHasFocus does the list cell have focus?
+ *
+ * @return The list cell renderer.
+ */
+ public Component getListCellRendererComponent(JList list, Object value,
+ int index,
+ boolean isSelected,
+ boolean cellHasFocus)
+ {
+ super.getListCellRendererComponent(list, value, index, isSelected,
+ cellHasFocus);
+ File file = (File) value;
+ setText(getFileChooser().getName(file));
+
+ // Install indented icon.
+ Icon icon = getFileChooser().getIcon(file);
+ indentIcon.setIcon(icon);
+ int depth = directoryModel.getDepth(index);
+ indentIcon.setDepth(depth);
+ setIcon(indentIcon);
+
+ return this;
+ }
+ }
+
+ /**
+ * An icon that wraps another icon and adds indentation.
+ */
+ class IndentIcon
+ implements Icon
+ {
+
+ /**
+ * The indentation level.
+ */
+ private static final int INDENT = 10;
+
+ /**
+ * The wrapped icon.
+ */
+ private Icon icon;
+
+ /**
+ * The current depth.
+ */
+ private int depth;
+
+ /**
+ * Sets the icon to be wrapped.
+ *
+ * @param i the icon
+ */
+ void setIcon(Icon i)
+ {
+ icon = i;
+ }
+
+ /**
+ * Sets the indentation depth.
+ *
+ * @param d the depth to set
+ */
+ void setDepth(int d)
+ {
+ depth = d;
+ }
+
+ public int getIconHeight()
+ {
+ return icon.getIconHeight();
+ }
+
+ public int getIconWidth()
+ {
+ return icon.getIconWidth() + depth * INDENT;
+ }
+
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ icon.paintIcon(c, g, x + depth * INDENT, y);
+ }
+
+ }
+
+ /**
+ * A renderer for the files and directories in the file chooser.
+ */
+ protected class FileRenderer
+ extends DefaultListCellRenderer
+ {
+
+ /**
+ * Creates a new renderer.
+ */
+ protected FileRenderer()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns a component that can render the specified value.
+ *
+ * @param list the list.
+ * @param value the value (a {@link File}).
+ * @param index the index.
+ * @param isSelected is the item selected?
+ * @param cellHasFocus does the item have the focus?
+ *
+ * @return The renderer.
+ */
+ public Component getListCellRendererComponent(JList list, Object value,
+ int index, boolean isSelected, boolean cellHasFocus)
+ {
+ FileView v = getFileView(getFileChooser());
+ File f = (File) value;
+ if (f != null)
+ {
+ setText(v.getName(f));
+ setIcon(v.getIcon(f));
+ }
+ else
+ {
+ setText("");
+ setIcon(null);
+ }
+ setOpaque(true);
+ if (isSelected)
+ {
+ setBackground(list.getSelectionBackground());
+ setForeground(list.getSelectionForeground());
+ }
+ else
+ {
+ setBackground(list.getBackground());
+ setForeground(list.getForeground());
+ }
+
+ setEnabled(list.isEnabled());
+ setFont(list.getFont());
+
+ if (cellHasFocus)
+ setBorder(UIManager.getBorder("List.focusCellHighlightBorder"));
+ else
+ setBorder(noFocusBorder);
+ return this;
+ }
+ }
+
+ /**
+ * A combo box model for the file selection filters.
+ */
+ protected class FilterComboBoxModel
+ extends AbstractListModel
+ implements ComboBoxModel, PropertyChangeListener
+ {
+
+ /** Storage for the filters in the model. */
+ protected FileFilter[] filters;
+
+ /** The index of the selected file filter. */
+ private Object selected;
+
+ /**
+ * Creates a new model.
+ */
+ protected FilterComboBoxModel()
+ {
+ filters = new FileFilter[1];
+ filters[0] = getAcceptAllFileFilter(getFileChooser());
+ selected = filters[0];
+ }
+
+ /**
+ * Handles property changes.
+ *
+ * @param e the property change event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY))
+ {
+ JFileChooser fc = getFileChooser();
+ FileFilter[] choosableFilters = fc.getChoosableFileFilters();
+ filters = choosableFilters;
+ fireContentsChanged(this, 0, filters.length);
+ selected = e.getNewValue();
+ fireContentsChanged(this, -1, -1);
+ }
+ else if (e.getPropertyName().equals(
+ JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY))
+ {
+ // repopulate list
+ JFileChooser fc = getFileChooser();
+ FileFilter[] choosableFilters = fc.getChoosableFileFilters();
+ filters = choosableFilters;
+ fireContentsChanged(this, 0, filters.length);
+ }
+ }
+
+ /**
+ * Sets the selected filter.
+ *
+ * @param filter the filter (<code>null</code> ignored).
+ */
+ public void setSelectedItem(Object filter)
+ {
+ if (filter != null)
+ {
+ selected = filter;
+ fireContentsChanged(this, -1, -1);
+ }
+ }
+
+ /**
+ * Returns the selected file filter.
+ *
+ * @return The selected file filter.
+ */
+ public Object getSelectedItem()
+ {
+ return selected;
+ }
+
+ /**
+ * Returns the number of items in the model.
+ *
+ * @return The number of items in the model.
+ */
+ public int getSize()
+ {
+ return filters.length;
+ }
+
+ /**
+ * Returns the item at the specified index.
+ *
+ * @param index the item index.
+ *
+ * @return The item at the specified index.
+ */
+ public Object getElementAt(int index)
+ {
+ return filters[index];
+ }
+
+ }
+
+ /**
+ * A renderer for the items in the file filter combo box.
+ */
+ public class FilterComboBoxRenderer
+ extends DefaultListCellRenderer
+ {
+ /**
+ * Creates a new renderer.
+ */
+ public FilterComboBoxRenderer()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns a component that can be used to paint the given value within
+ * the list.
+ *
+ * @param list the list.
+ * @param value the value (a {@link FileFilter}).
+ * @param index the item index.
+ * @param isSelected is the item selected?
+ * @param cellHasFocus does the list cell have focus?
+ *
+ * @return This component as the renderer.
+ */
+ public Component getListCellRendererComponent(JList list, Object value,
+ int index, boolean isSelected, boolean cellHasFocus)
+ {
+ super.getListCellRendererComponent(list, value, index, isSelected,
+ cellHasFocus);
+ FileFilter filter = (FileFilter) value;
+ setText(filter.getDescription());
+ return this;
+ }
+ }
+
+ /**
+ * A listener for selection events in the file list.
+ *
+ * @see #createListSelectionListener(JFileChooser)
+ */
+ class MetalFileChooserSelectionListener
+ implements ListSelectionListener
+ {
+ /**
+ * Creates a new <code>SelectionListener</code> object.
+ */
+ protected MetalFileChooserSelectionListener()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Makes changes to different properties when
+ * a value has changed in the filechooser's selection.
+ *
+ * @param e - the list selection event that occured.
+ */
+ public void valueChanged(ListSelectionEvent e)
+ {
+ File f = (File) fileList.getSelectedValue();
+ if (f == null)
+ return;
+ JFileChooser filechooser = getFileChooser();
+ if (! filechooser.isTraversable(f))
+ filechooser.setSelectedFile(f);
+ else
+ filechooser.setSelectedFile(null);
+ }
+ }
+
+ /**
+ * A mouse listener for the {@link JFileChooser}.
+ * This listener is used for editing filenames.
+ */
+ protected class SingleClickListener
+ extends MouseAdapter
+ {
+
+ /** Stores instance of the list */
+ JList list;
+
+ /**
+ * Stores the current file that is being edited.
+ * It is null if nothing is currently being edited.
+ */
+ File editFile;
+
+ /** The current file chooser. */
+ JFileChooser fc;
+
+ /** The last file selected. */
+ Object lastSelected;
+
+ /** The textfield used for editing. */
+ JTextField editField;
+
+ /**
+ * Creates a new listener.
+ *
+ * @param list the directory/file list.
+ */
+ public SingleClickListener(JList list)
+ {
+ this.list = list;
+ editFile = null;
+ fc = getFileChooser();
+ lastSelected = null;
+ startEditing = false;
+ }
+
+ /**
+ * Receives notification of a mouse click event.
+ *
+ * @param e the event.
+ */
+ public void mouseClicked(MouseEvent e)
+ {
+ if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1)
+ {
+ int index = list.locationToIndex(e.getPoint());
+ File[] sf = fc.getSelectedFiles();
+ if ((!fc.isMultiSelectionEnabled() || (sf != null && sf.length <= 1))
+ && index >= 0 && !startEditing && list.isSelectedIndex(index))
+ {
+ Object tmp = list.getModel().getElementAt(index);
+ if (lastSelected != null && lastSelected.equals(tmp))
+ editFile(index);
+ lastSelected = tmp;
+ }
+ else
+ completeEditing();
+ }
+ else
+ completeEditing();
+ }
+
+ /**
+ * Sets up the text editor for the current file.
+ *
+ * @param index -
+ * the current index of the item in the list to be edited.
+ */
+ void editFile(int index)
+ {
+ Rectangle bounds = list.getCellBounds(index, index);
+ list.scrollRectToVisible(bounds);
+ editFile = (File) list.getModel().getElementAt(index);
+ if (editFile.canWrite())
+ {
+ startEditing = true;
+ editField = new JTextField(editFile.getName());
+ editField.addActionListener(new EditingActionListener());
+
+ Icon icon = getFileView(fc).getIcon(editFile);
+ if (icon != null)
+ {
+ int padding = icon.getIconWidth() + 4;
+ bounds.x += padding;
+ bounds.width -= padding;
+ }
+ editField.setBounds(bounds);
+
+ list.add(editField);
+
+ editField.requestFocus();
+ editField.selectAll();
+ }
+ else
+ completeEditing();
+ list.repaint();
+ }
+
+ /**
+ * Completes the editing.
+ */
+ void completeEditing()
+ {
+ if (editField != null && editFile != null)
+ {
+ String text = editField.getText();
+ if (text != null && text != "" && !text.equals(fc.getName(editFile)))
+ {
+ File f = fc.getFileSystemView().
+ createFileObject(fc.getCurrentDirectory(), text);
+ if ( editFile.renameTo(f) )
+ rescanCurrentDirectory(fc);
+ }
+ list.remove(editField);
+ }
+ startEditing = false;
+ editFile = null;
+ lastSelected = null;
+ editField = null;
+ list.repaint();
+ }
+
+ /**
+ * ActionListener for the editing text field.
+ */
+ class EditingActionListener implements ActionListener
+ {
+
+ /**
+ * This method is invoked when an action occurs.
+ *
+ * @param e -
+ * the <code>ActionEvent</code> that occurred
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ if (editField != null)
+ completeEditing();
+ }
+ }
+ }
+
+ /**
+ * A mouse listener for the {@link JFileChooser}.
+ * This listener is used for the table
+ */
+ private class TableClickListener extends MouseAdapter
+ {
+
+ /** Stores instance of the table */
+ JTable table;
+
+ /** Stores instance of the file chooser */
+ JFileChooser fc;
+
+ /** The last selected file. */
+ Object lastSelected;
+
+ /**
+ * Stores the current file that is being edited.
+ * It is null if nothing is currently being edited.
+ */
+ File editFile;
+
+ /** The textfield used for editing. */
+ JTextField editField;
+
+ /**
+ * Creates a new listener.
+ *
+ * @param table the directory/file table
+ * @param fc the JFileChooser
+ */
+ public TableClickListener(JTable table, JFileChooser fc)
+ {
+ this.table = table;
+ this.fc = fc;
+ lastSelected = fileList.getSelectedValue();
+ setDirectorySelected(false);
+ startEditing = false;
+ editFile = null;
+ editField = null;
+ }
+
+ /**
+ * Receives notification of a mouse click event.
+ *
+ * @param e the event.
+ */
+ public void mouseClicked(MouseEvent e)
+ {
+ int row = table.getSelectedRow();
+ Object selVal = fileList.getModel().getElementAt(row);
+ if (selVal == null)
+ return;
+ FileSystemView fsv = fc.getFileSystemView();
+ if (e.getClickCount() == 1 &&
+ selVal.equals(lastSelected) &&
+ e.getButton() == MouseEvent.BUTTON1)
+ {
+ File[] sf = fc.getSelectedFiles();
+ if ((!fc.isMultiSelectionEnabled() || (sf != null && sf.length <= 1))
+ && !startEditing)
+ {
+ editFile = (File) selVal;
+ editFile(row);
+ }
+ }
+ else if (e.getClickCount() >= 2 &&
+ selVal.equals(lastSelected))
+ {
+ if (startEditing)
+ completeEditing();
+ File f = fsv.createFileObject(lastSelected.toString());
+ if (fc.isTraversable(f))
+ {
+ fc.setCurrentDirectory(f);
+ fc.rescanCurrentDirectory();
+ }
+ else
+ {
+ fc.setSelectedFile(f);
+ fc.approveSelection();
+ closeDialog();
+ }
+ }
+ else
+ {
+ if (startEditing)
+ completeEditing();
+ String path = selVal.toString();
+ File f = fsv.createFileObject(path);
+ fc.setSelectedFile(f);
+ if (fc.isTraversable(f))
+ {
+ setDirectorySelected(true);
+ setDirectory(f);
+ }
+ else
+ {
+ setDirectorySelected(false);
+ setDirectory(null);
+ }
+ lastSelected = selVal;
+ if (f.isFile())
+ setFileName(path.substring(path.lastIndexOf("/") + 1));
+ else if (fc.getFileSelectionMode() != JFileChooser.FILES_ONLY)
+ setFileName(path);
+ }
+ fileTable.repaint();
+ }
+
+ /**
+ * Sets up the text editor for the current file.
+ *
+ * @param row -
+ * the current row of the item in the list to be edited.
+ */
+ void editFile(int row)
+ {
+ Rectangle bounds = table.getCellRect(row, 0, true);
+ table.scrollRectToVisible(bounds);
+ if (editFile.canWrite())
+ {
+ startEditing = true;
+ editField = new JTextField(editFile.getName());
+ editField.addActionListener(new EditingActionListener());
+
+ // Need to adjust y pos
+ bounds.y = row * table.getRowHeight();
+ editField.setBounds(bounds);
+
+ table.add(editField);
+
+ editField.requestFocus();
+ editField.selectAll();
+ }
+ else
+ completeEditing();
+ table.repaint();
+ }
+
+ /**
+ * Completes the editing.
+ */
+ void completeEditing()
+ {
+ if (editField != null && editFile != null)
+ {
+ String text = editField.getText();
+ if (text != null && text != "" && !text.equals(fc.getName(editFile)))
+ if (editFile.renameTo(fc.getFileSystemView().createFileObject(
+ fc.getCurrentDirectory(), text)))
+ rescanCurrentDirectory(fc);
+ table.remove(editField);
+ }
+ startEditing = false;
+ editFile = null;
+ editField = null;
+ table.repaint();
+ }
+
+ /**
+ * ActionListener for the editing text field.
+ */
+ class EditingActionListener implements ActionListener
+ {
+
+ /**
+ * This method is invoked when an action occurs.
+ *
+ * @param e -
+ * the <code>ActionEvent</code> that occurred
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ if (editField != null)
+ completeEditing();
+ }
+ }
+
+ /**
+ * Closes the dialog.
+ */
+ public void closeDialog()
+ {
+ Window owner = SwingUtilities.windowForComponent(fc);
+ if (owner instanceof JDialog)
+ ((JDialog) owner).dispose();
+ }
+ }
+
+ /** The text for a label describing the directory combo box. */
+ private String directoryLabel;
+
+ private JComboBox directoryComboBox;
+
+ /** The model for the directory combo box. */
+ DirectoryComboBoxModel directoryModel;
+
+ /** The text for a label describing the file text field. */
+ private String fileLabel;
+
+ /** The file name text field. */
+ private JTextField fileTextField;
+
+ /** The text for a label describing the filter combo box. */
+ private String filterLabel;
+
+ /**
+ * The top panel (contains the directory combo box and the control buttons).
+ */
+ private JPanel topPanel;
+
+ /** A panel containing the control buttons ('up', 'home' etc.). */
+ private JPanel controls;
+
+ /**
+ * The panel that contains the filename field and the filter combobox.
+ */
+ private JPanel bottomPanel;
+
+ /**
+ * The panel that contains the 'Open' (or 'Save') and 'Cancel' buttons.
+ */
+ private JPanel buttonPanel;
+
+ private JButton approveButton;
+
+ /** The file list. */
+ JList fileList;
+
+ /** The file table. */
+ JTable fileTable;
+
+ /** The panel containing the file list. */
+ JPanel fileListPanel;
+
+ /** The panel containing the file table. */
+ JPanel fileTablePanel;
+
+ /** The filter combo box model. */
+ private FilterComboBoxModel filterModel;
+
+ /** The action map. */
+ private ActionMap actionMap;
+
+ /** True if currently in list view. */
+ boolean listView;
+
+ /** True if we can or have started editing a cell. */
+ boolean startEditing;
+
+ /** The scrollpane used for the table and list. */
+ JScrollPane scrollPane;
+
+ /** The text for the label when saving. */
+ String save;
+
+ /** The text for the label when opening a directory. */
+ String look;
+
+ /** The label for the file combo box. */
+ JLabel dirLabel;
+
+ /** Listeners. */
+ ListSelectionListener listSelList;
+ MouseListener doubleClickList;
+ SingleClickListener singleClickList;
+ TableClickListener tableClickList;
+
+ /**
+ * A factory method that returns a UI delegate for the specified
+ * component.
+ *
+ * @param c the component (which should be a {@link JFileChooser}).
+ */
+ public static ComponentUI createUI(JComponent c)
+ {
+ JFileChooser chooser = (JFileChooser) c;
+ return new MetalFileChooserUI(chooser);
+ }
+
+ /**
+ * Creates a new instance of this UI delegate.
+ *
+ * @param filechooser the file chooser component.
+ */
+ public MetalFileChooserUI(JFileChooser filechooser)
+ {
+ super(filechooser);
+ bottomPanel = new JPanel(new GridLayout(3, 2));
+ buttonPanel = new JPanel();
+ }
+
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ actionMap = createActionMap();
+ }
+
+ public void uninstallUI(JComponent c)
+ {
+ super.uninstallUI(c);
+ actionMap = null;
+ }
+
+ /**
+ * Installs the sub-components of the file chooser.
+ *
+ * @param fc the file chooser component.
+ */
+ public void installComponents(JFileChooser fc)
+ {
+ fc.setLayout(new BorderLayout());
+ topPanel = new JPanel(new BorderLayout());
+ dirLabel = new JLabel(directoryLabel);
+ topPanel.add(dirLabel, BorderLayout.WEST);
+ this.controls = new JPanel();
+ addControlButtons();
+
+ JPanel dirPanel = new JPanel(new VerticalMidLayout());
+ directoryModel = createDirectoryComboBoxModel(fc);
+ directoryComboBox = new JComboBox(directoryModel);
+ directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
+ dirPanel.add(directoryComboBox);
+ topPanel.add(dirPanel);
+ topPanel.add(controls, BorderLayout.EAST);
+ topPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 8));
+ fc.add(topPanel, BorderLayout.NORTH);
+
+ JPanel list = createList(fc);
+ list.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
+ fc.add(list, BorderLayout.CENTER);
+
+ JPanel bottomPanel = getBottomPanel();
+ filterModel = createFilterComboBoxModel();
+ JComboBox fileFilterCombo = new JComboBox(filterModel);
+ fileFilterCombo.setRenderer(createFilterComboBoxRenderer());
+
+ fileTextField = new JTextField();
+ JPanel fileNamePanel = new JPanel(new VerticalMidLayout());
+ fileNamePanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 5));
+ fileNamePanel.add(fileTextField);
+ JPanel row1 = new JPanel(new BorderLayout());
+ row1.add(new JLabel(this.fileLabel), BorderLayout.WEST);
+ row1.add(fileNamePanel);
+ bottomPanel.add(row1);
+
+ JPanel row2 = new JPanel(new BorderLayout());
+ row2.add(new JLabel(this.filterLabel), BorderLayout.WEST);
+ row2.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
+ row2.add(fileFilterCombo);
+ bottomPanel.add(row2);
+ JPanel buttonPanel = new JPanel(new ButtonLayout());
+
+ approveButton = new JButton(getApproveSelectionAction());
+ approveButton.setText(getApproveButtonText(fc));
+ approveButton.setToolTipText(getApproveButtonToolTipText(fc));
+ approveButton.setMnemonic(getApproveButtonMnemonic(fc));
+ buttonPanel.add(approveButton);
+ buttonPanel.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
+
+ JButton cancelButton = new JButton(getCancelSelectionAction());
+ cancelButton.setText(cancelButtonText);
+ cancelButton.setToolTipText(cancelButtonToolTipText);
+ cancelButton.setMnemonic(cancelButtonMnemonic);
+ buttonPanel.add(cancelButton);
+ bottomPanel.add(buttonPanel, BorderLayout.SOUTH);
+ bottomPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 8, 8));
+ fc.add(bottomPanel, BorderLayout.SOUTH);
+
+ fc.add(getAccessoryPanel(), BorderLayout.EAST);
+ }
+
+ /**
+ * Uninstalls the components added by
+ * {@link #installComponents(JFileChooser)}.
+ *
+ * @param fc the file chooser.
+ */
+ public void uninstallComponents(JFileChooser fc)
+ {
+ fc.remove(bottomPanel);
+ bottomPanel = null;
+ fc.remove(fileListPanel);
+ fc.remove(fileTablePanel);
+ fileTablePanel = null;
+ fileListPanel = null;
+ fc.remove(topPanel);
+ topPanel = null;
+
+ directoryModel = null;
+ fileTextField = null;
+ directoryComboBox = null;
+ }
+
+ /**
+ * Returns the panel that contains the 'Open' (or 'Save') and 'Cancel'
+ * buttons.
+ *
+ * @return The panel.
+ */
+ protected JPanel getButtonPanel()
+ {
+ return buttonPanel;
+ }
+
+ /**
+ * Creates and returns a new panel that will be used for the controls at
+ * the bottom of the file chooser.
+ *
+ * @return A new panel.
+ */
+ protected JPanel getBottomPanel()
+ {
+ if (bottomPanel == null)
+ bottomPanel = new JPanel(new GridLayout(3, 2));
+ return bottomPanel;
+ }
+
+ /**
+ * Fetches localised strings for use by the labels and buttons on the
+ * file chooser.
+ *
+ * @param fc the file chooser.
+ */
+ protected void installStrings(JFileChooser fc)
+ {
+ super.installStrings(fc);
+ look = "Look In: ";
+ save = "Save In: ";
+ if (fc.getDialogType() == JFileChooser.SAVE_DIALOG)
+ directoryLabel = save;
+ else
+ directoryLabel = look;
+
+ fileLabel = "File Name: ";
+ filterLabel = "Files of Type: ";
+
+ this.cancelButtonMnemonic = 0;
+ this.cancelButtonText = "Cancel";
+ this.cancelButtonToolTipText = "Abort file chooser dialog";
+
+ this.directoryOpenButtonMnemonic = 0;
+ this.directoryOpenButtonText = "Open";
+ this.directoryOpenButtonToolTipText = "Open selected directory";
+
+ this.helpButtonMnemonic = 0;
+ this.helpButtonText = "Help";
+ this.helpButtonToolTipText = "Filechooser help";
+
+ this.openButtonMnemonic = 0;
+ this.openButtonText = "Open";
+ this.openButtonToolTipText = "Open selected file";
+
+ this.saveButtonMnemonic = 0;
+ this.saveButtonText = "Save";
+ this.saveButtonToolTipText = "Save selected file";
+
+ this.updateButtonMnemonic = 0;
+ this.updateButtonText = "Update";
+ this.updateButtonToolTipText = "Update directory listing";
+ }
+
+ /**
+ * Installs the listeners required.
+ *
+ * @param fc the file chooser.
+ */
+ protected void installListeners(JFileChooser fc)
+ {
+ directoryComboBox.setAction(new DirectoryComboBoxAction());
+ fc.addPropertyChangeListener(filterModel);
+ listSelList = createListSelectionListener(fc);
+ doubleClickList = this.createDoubleClickListener(fc, fileList);
+ singleClickList = new SingleClickListener(fileList);
+ fileList.addListSelectionListener(listSelList);
+ fileList.addMouseListener(doubleClickList);
+ fileList.addMouseListener(singleClickList);
+ super.installListeners(fc);
+ }
+
+ protected void uninstallListeners(JFileChooser fc)
+ {
+ super.uninstallListeners(fc);
+ fc.removePropertyChangeListener(filterModel);
+ directoryComboBox.setAction(null);
+ fileList.removeListSelectionListener(listSelList);
+ fileList.removeMouseListener(doubleClickList);
+ fileList.removeMouseListener(singleClickList);
+
+ if (fileTable != null)
+ fileTable.removeMouseListener(tableClickList);
+ }
+
+ protected ActionMap getActionMap()
+ {
+ if (actionMap == null)
+ actionMap = createActionMap();
+ return actionMap;
+ }
+
+ /**
+ * Creates and returns an action map.
+ *
+ * @return The action map.
+ */
+ protected ActionMap createActionMap()
+ {
+ ActionMap map = new ActionMap();
+ map.put("approveSelection", getApproveSelectionAction());
+ map.put("cancelSelection", getCancelSelectionAction());
+ map.put("Go Up", getChangeToParentDirectoryAction());
+ return map;
+ }
+
+ /**
+ * Creates a panel containing a list of files.
+ *
+ * @param fc the file chooser.
+ *
+ * @return A panel.
+ */
+ protected JPanel createList(JFileChooser fc)
+ {
+ if (fileList == null)
+ {
+ fileListPanel = new JPanel(new BorderLayout());
+ fileList = new JList(getModel());
+ scrollPane = new JScrollPane(fileList);
+ fileList.setLayoutOrientation(JList.VERTICAL_WRAP);
+ fileList.setCellRenderer(new FileRenderer());
+ }
+ else
+ {
+ fileList.setModel(getModel());
+ fileListPanel.removeAll();
+ scrollPane.getViewport().setView(fileList);
+ }
+ fileListPanel.add(scrollPane);
+ // This size was determined using BeanShell and dumping the JFileChooser
+ // component hierarchy. Sun has an internal FilePane class in there, but
+ // that probably doesn't matter atm.
+ fileListPanel.setPreferredSize(new Dimension(405, 135));
+ return fileListPanel;
+ }
+
+ /**
+ * Creates a panel containing a table within a scroll pane.
+ *
+ * @param fc the file chooser.
+ *
+ * @return The details view.
+ */
+ protected JPanel createDetailsView(JFileChooser fc)
+ {
+ fileTablePanel = new JPanel(new BorderLayout());
+
+ Object[] cols = new Object[] {"Name", "Size", "Modified"};
+ Object[][] rows = new Object[fileList.getModel().getSize()][3];
+
+ fileTable = new JTable(new DefaultTableModel(rows, cols));
+
+ if (fc.isMultiSelectionEnabled())
+ fileTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ else
+ fileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ fileTable.setShowGrid(false);
+ fileTable.setColumnSelectionAllowed(false);
+ fileTable.setDefaultRenderer(Object.class, new TableFileRenderer());
+
+ tableClickList = new TableClickListener(fileTable, fc);
+ fileTable.addMouseListener(tableClickList);
+
+ return updateTable();
+ }
+
+ /**
+ * Sets the values in the table, and puts it in the panel.
+ *
+ * @return the panel containing the table.
+ */
+ JPanel updateTable()
+ {
+ DefaultTableModel mod = (DefaultTableModel) fileTable.getModel();
+ ListModel lm = fileList.getModel();
+ DateFormat dt = DateFormat.getDateTimeInstance(DateFormat.SHORT,
+ DateFormat.SHORT);
+ File curr = null;
+ int size = lm.getSize();
+ int rc = mod.getRowCount();
+
+ // If there are not enough rows
+ for (int x = rc; x < size; x++)
+ mod.addRow(new Object[3]);
+
+ for (int i = 0; i < size; i++)
+ {
+ curr = (File) lm.getElementAt(i);
+ fileTable.setValueAt(curr.getName(), i, 0);
+ fileTable.setValueAt(formatSize(curr.length()), i, 1);
+ fileTable.setValueAt(dt.format(new Date(curr.lastModified())), i, 2);
+ }
+
+ // If there are too many rows
+ while (rc > size)
+ mod.removeRow(--rc);
+
+ scrollPane.getViewport().setView(fileTable);
+ scrollPane.setColumnHeaderView(fileTable.getTableHeader());
+
+ fileTablePanel.removeAll();
+ fileTablePanel.add(scrollPane);
+
+ return fileTablePanel;
+ }
+
+ /**
+ * Formats bytes into the appropriate size.
+ *
+ * @param bytes the number of bytes to convert
+ * @return a string representation of the size
+ */
+ private String formatSize(long bytes)
+ {
+ NumberFormat nf = NumberFormat.getNumberInstance();
+ long mb = (long) Math.pow(2, 20);
+ long kb = (long) Math.pow(2, 10);
+ long gb = (long) Math.pow(2, 30);
+ double size = 0;
+ String id = "";
+
+ if ((bytes / gb) >= 1)
+ {
+ size = (double) bytes / (double) gb;
+ id = "GB";
+ }
+ else if ((bytes / mb) >= 1)
+ {
+ size = (double) bytes / (double) mb;
+ id = "MB";
+ }
+ else if ((bytes / kb) >= 1)
+ {
+ size = (double) bytes / (double) kb;
+ id = "KB";
+ }
+ else
+ {
+ size = bytes;
+ id = "Bytes";
+ }
+
+ return nf.format(size) + " " + id;
+ }
+ /**
+ * Creates a listener that monitors selections in the directory/file list
+ * and keeps the {@link JFileChooser} component up to date.
+ *
+ * @param fc the file chooser.
+ *
+ * @return The listener.
+ *
+ * @see #installListeners(JFileChooser)
+ */
+ public ListSelectionListener createListSelectionListener(JFileChooser fc)
+ {
+ return new MetalFileChooserSelectionListener();
+ }
+
+ /**
+ * Returns the preferred size for the file chooser component.
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ Dimension tp = topPanel.getPreferredSize();
+ Dimension bp = bottomPanel.getPreferredSize();
+ Dimension fl = fileListPanel.getPreferredSize();
+ return new Dimension(fl.width, tp.height + bp.height + fl.height);
+ }
+
+ /**
+ * Returns the minimum size for the file chooser component.
+ *
+ * @return The minimum size.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ Dimension tp = topPanel.getMinimumSize();
+ Dimension bp = bottomPanel.getMinimumSize();
+ Dimension fl = fileListPanel.getMinimumSize();
+ return new Dimension(fl.width, tp.height + bp.height + fl.height);
+ }
+
+ /**
+ * Returns the maximum size for the file chooser component.
+ *
+ * @return The maximum size.
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Creates a property change listener that monitors the {@link JFileChooser}
+ * for property change events and updates the component display accordingly.
+ *
+ * @param fc the file chooser.
+ *
+ * @return The property change listener.
+ *
+ * @see #installListeners(JFileChooser)
+ */
+ public PropertyChangeListener createPropertyChangeListener(JFileChooser fc)
+ {
+ return new MetalFileChooserPropertyChangeListener();
+ }
+
+ /**
+ * Creates and returns a new instance of {@link DirectoryComboBoxModel}.
+ *
+ * @return A new instance of {@link DirectoryComboBoxModel}.
+ */
+ protected MetalFileChooserUI.DirectoryComboBoxModel
+ createDirectoryComboBoxModel(JFileChooser fc)
+ {
+ return new DirectoryComboBoxModel();
+ }
+
+ /**
+ * Creates a new instance of the renderer used in the directory
+ * combo box.
+ *
+ * @param fc the file chooser.
+ *
+ * @return The renderer.
+ */
+ protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(
+ JFileChooser fc)
+ {
+ return new DirectoryComboBoxRenderer(fc);
+ }
+
+ /**
+ * Creates and returns a new instance of {@link FilterComboBoxModel}.
+ *
+ * @return A new instance of {@link FilterComboBoxModel}.
+ */
+ protected FilterComboBoxModel createFilterComboBoxModel()
+ {
+ return new FilterComboBoxModel();
+ }
+
+ /**
+ * Creates and returns a new instance of {@link FilterComboBoxRenderer}.
+ *
+ * @return A new instance of {@link FilterComboBoxRenderer}.
+ */
+ protected MetalFileChooserUI.FilterComboBoxRenderer
+ createFilterComboBoxRenderer()
+ {
+ return new FilterComboBoxRenderer();
+ }
+
+ /**
+ * Adds the control buttons ('up', 'home' etc.) to the panel.
+ */
+ protected void addControlButtons()
+ {
+ JButton upButton = new JButton(getChangeToParentDirectoryAction());
+ upButton.setText(null);
+ upButton.setIcon(this.upFolderIcon);
+ upButton.setMargin(new Insets(0, 0, 0, 0));
+ controls.add(upButton);
+
+ JButton homeButton = new JButton(getGoHomeAction());
+ homeButton.setText(null);
+ homeButton.setIcon(this.homeFolderIcon);
+ homeButton.setMargin(new Insets(0, 0, 0, 0));
+ controls.add(homeButton);
+
+ JButton newFolderButton = new JButton(getNewFolderAction());
+ newFolderButton.setText(null);
+ newFolderButton.setIcon(this.newFolderIcon);
+ newFolderButton.setMargin(new Insets(0, 0, 0, 0));
+ controls.add(newFolderButton);
+
+ JToggleButton listButton = new JToggleButton(this.listViewIcon);
+ listButton.setMargin(new Insets(0, 0, 0, 0));
+ listButton.addActionListener(new ListViewActionListener());
+ listButton.setSelected(true);
+ listView = true;
+ controls.add(listButton);
+
+ JToggleButton detailButton = new JToggleButton(this.detailsViewIcon);
+ detailButton.setMargin(new Insets(0, 0, 0, 0));
+ detailButton.addActionListener(new DetailViewActionListener());
+ detailButton.setSelected(false);
+ controls.add(detailButton);
+
+ ButtonGroup buttonGroup = new ButtonGroup();
+ buttonGroup.add(listButton);
+ buttonGroup.add(detailButton);
+ }
+
+ /**
+ * Removes all the buttons from the control panel.
+ */
+ protected void removeControlButtons()
+ {
+ controls.removeAll();
+ controls.revalidate();
+ controls.repaint();
+ }
+
+ /**
+ * Updates the current directory.
+ *
+ * @param fc the file chooser to update.
+ */
+ public void rescanCurrentDirectory(JFileChooser fc)
+ {
+ directoryModel.setSelectedItem(fc.getCurrentDirectory());
+ getModel().validateFileCache();
+ if (!listView)
+ updateTable();
+ else
+ createList(fc);
+ }
+
+ /**
+ * Returns the file name in the text field.
+ *
+ * @return The file name.
+ */
+ public String getFileName()
+ {
+ String result = null;
+ if (fileTextField != null)
+ result = fileTextField.getText();
+ return result;
+ }
+
+ /**
+ * Sets the file name in the text field.
+ *
+ * @param filename the file name.
+ */
+ public void setFileName(String filename)
+ {
+ fileTextField.setText(filename);
+ }
+
+ /**
+ * DOCUMENT ME!!
+ *
+ * @param e - DOCUMENT ME!
+ */
+ public void valueChanged(ListSelectionEvent e)
+ {
+ // FIXME: Not sure what we should be doing here, if anything.
+ }
+
+ /**
+ * Returns the approve button.
+ *
+ * @return The approve button.
+ */
+ protected JButton getApproveButton(JFileChooser fc)
+ {
+ return approveButton;
+ }
+
+ /**
+ * A layout manager that is used to arrange the subcomponents of the
+ * {@link JFileChooser}.
+ */
+ class VerticalMidLayout implements LayoutManager
+ {
+ /**
+ * Performs the layout.
+ *
+ * @param parent the container.
+ */
+ public void layoutContainer(Container parent)
+ {
+ int count = parent.getComponentCount();
+ if (count > 0)
+ {
+ Insets insets = parent.getInsets();
+ Component c = parent.getComponent(0);
+ Dimension prefSize = c.getPreferredSize();
+ int h = parent.getHeight() - insets.top - insets.bottom;
+ int adj = Math.max(0, (h - prefSize.height) / 2);
+ c.setBounds(insets.left, insets.top + adj, parent.getWidth()
+ - insets.left - insets.right,
+ (int) Math.min(prefSize.getHeight(), h));
+ }
+ }
+
+ /**
+ * Returns the minimum layout size.
+ *
+ * @param parent the container.
+ *
+ * @return The minimum layout size.
+ */
+ public Dimension minimumLayoutSize(Container parent)
+ {
+ return preferredLayoutSize(parent);
+ }
+
+ /**
+ * Returns the preferred layout size.
+ *
+ * @param parent the container.
+ *
+ * @return The preferred layout size.
+ */
+ public Dimension preferredLayoutSize(Container parent)
+ {
+ if (parent.getComponentCount() > 0)
+ {
+ return parent.getComponent(0).getPreferredSize();
+ }
+ else return null;
+ }
+
+ /**
+ * This layout manager does not need to track components, so this
+ * method does nothing.
+ *
+ * @param name the name the component is associated with.
+ * @param component the component.
+ */
+ public void addLayoutComponent(String name, Component component)
+ {
+ // do nothing
+ }
+
+ /**
+ * This layout manager does not need to track components, so this
+ * method does nothing.
+ *
+ * @param component the component.
+ */
+ public void removeLayoutComponent(Component component)
+ {
+ // do nothing
+ }
+ }
+
+ /**
+ * A layout manager that is used to arrange buttons for the
+ * {@link JFileChooser}.
+ */
+ class ButtonLayout implements LayoutManager
+ {
+ static final int GAP = 4;
+
+ /**
+ * Performs the layout.
+ *
+ * @param parent the container.
+ */
+ public void layoutContainer(Container parent)
+ {
+ int count = parent.getComponentCount();
+ if (count > 0)
+ {
+ // first find the widest button
+ int maxW = 0;
+ for (int i = 0; i < count; i++)
+ {
+ Component c = parent.getComponent(i);
+ Dimension prefSize = c.getPreferredSize();
+ maxW = Math.max(prefSize.width, maxW);
+ }
+
+ // then position the buttons
+ Insets insets = parent.getInsets();
+ int availableH = parent.getHeight() - insets.top - insets.bottom;
+ int currentX = parent.getWidth() - insets.right;
+ for (int i = count - 1; i >= 0; i--)
+ {
+ Component c = parent.getComponent(i);
+ Dimension prefSize = c.getPreferredSize();
+ int adj = Math.max(0, (availableH - prefSize.height) / 2);
+ currentX = currentX - prefSize.width;
+ c.setBounds(currentX, insets.top + adj, prefSize.width,
+ (int) Math.min(prefSize.getHeight(), availableH));
+ currentX = currentX - GAP;
+ }
+ }
+ }
+
+ /**
+ * Returns the minimum layout size.
+ *
+ * @param parent the container.
+ *
+ * @return The minimum layout size.
+ */
+ public Dimension minimumLayoutSize(Container parent)
+ {
+ return preferredLayoutSize(parent);
+ }
+
+ /**
+ * Returns the preferred layout size.
+ *
+ * @param parent the container.
+ *
+ * @return The preferred layout size.
+ */
+ public Dimension preferredLayoutSize(Container parent)
+ {
+ Insets insets = parent.getInsets();
+ int maxW = 0;
+ int maxH = 0;
+ int count = parent.getComponentCount();
+ if (count > 0)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ Component c = parent.getComponent(i);
+ Dimension d = c.getPreferredSize();
+ maxW = Math.max(d.width, maxW);
+ maxH = Math.max(d.height, maxH);
+ }
+ }
+ return new Dimension(maxW * count + GAP * (count - 1) + insets.left
+ + insets.right, maxH + insets.top + insets.bottom);
+ }
+
+ /**
+ * This layout manager does not need to track components, so this
+ * method does nothing.
+ *
+ * @param name the name the component is associated with.
+ * @param component the component.
+ */
+ public void addLayoutComponent(String name, Component component)
+ {
+ // do nothing
+ }
+
+ /**
+ * This layout manager does not need to track components, so this
+ * method does nothing.
+ *
+ * @param component the component.
+ */
+ public void removeLayoutComponent(Component component)
+ {
+ // do nothing
+ }
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java
new file mode 100644
index 000000000..5382577c3
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java
@@ -0,0 +1,2626 @@
+/* MetalIconFactory.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.Graphics;
+import java.io.Serializable;
+
+import javax.swing.AbstractButton;
+import javax.swing.Icon;
+import javax.swing.JCheckBox;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JFileChooser;
+import javax.swing.JInternalFrame;
+import javax.swing.JRadioButton;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JSlider;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+import javax.swing.plaf.UIResource;
+
+
+/**
+ * Creates icons for the {@link MetalLookAndFeel}.
+ */
+public class MetalIconFactory implements Serializable
+{
+
+ /** A constant representing "dark". */
+ public static final boolean DARK = false;
+
+ /** A constant representing "light". */
+ public static final boolean LIGHT = true;
+
+ /** A shared instance of the MenuArrowIcon. */
+ private static Icon menuArrow;
+
+ /** A shared instance of the MenuItemArrowIcon. */
+ private static Icon menuItemArrow;
+
+ /**
+ * An icon displayed for {@link JCheckBoxMenuItem} components.
+ */
+ private static class CheckBoxMenuItemIcon
+ implements Icon, UIResource, Serializable
+ {
+ /**
+ * Creates a new icon instance.
+ */
+ public CheckBoxMenuItemIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon (10 pixels).
+ */
+ public int getIconWidth()
+ {
+ return 10;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon (10 pixels).
+ */
+ public int getIconHeight()
+ {
+ return 10;
+ }
+
+ /**
+ * Paints the icon.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ JCheckBoxMenuItem item = (JCheckBoxMenuItem) c;
+
+ if (item.isArmed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y, x + 8, y);
+ g.drawLine(x, y + 1, x, y + 8);
+ g.drawLine(x + 2, y + 8, x + 8, y + 8);
+ g.drawLine(x + 8, y + 2, x + 8, y + 7);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 1, y + 1, x + 7, y + 1);
+ g.drawLine(x + 1, y + 2, x + 1, y + 7);
+ g.drawLine(x + 1, y + 9, x + 9, y + 9);
+ g.drawLine(x + 9, y + 1, x + 9, y + 8);
+
+ // if the item is selected, we should draw a tick
+ if (item.isSelected())
+ {
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.fillRect(x + 2, y + 2, 2, 5);
+ for (int i = 0; i < 6; i++)
+ g.drawLine(x + 8 - i, y + i, x + 9 - i, y + i);
+ }
+
+ }
+ }
+
+ /**
+ * An icon used for the "detail view" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserDetailViewIcon()
+ */
+ private static class FileChooserDetailViewIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserDetailViewIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+
+ // file 1 outline
+ g.drawLine(x + 2, y + 2, x + 5, y + 2);
+ g.drawLine(x + 6, y + 3, x + 6, y + 7);
+ g.drawLine(x + 2, y + 7, x + 6, y + 7);
+ g.drawLine(x + 2, y + 2, x + 2, y + 7);
+
+ // file 2 outline
+ g.drawLine(x + 2, y + 10, x + 5, y + 10);
+ g.drawLine(x + 6, y + 11, x + 6, y + 15);
+ g.drawLine(x + 2, y + 15, x + 6, y + 15);
+ g.drawLine(x + 2, y + 10, x + 2, y + 15);
+
+ // detail lines
+ g.drawLine(x + 8, y + 5, x + 15, y + 5);
+ g.drawLine(x + 8, y + 13, x + 15, y + 13);
+
+ // fill files
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 3, y + 3, 3, 4);
+ g.fillRect(x + 3, y + 11, 3, 4);
+
+ // highlight files
+ g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
+ g.drawLine(x + 4, y + 4, x + 4, y + 5);
+ g.drawLine(x + 4, y + 12, x + 4, y + 13);
+
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the "home folder" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserHomeFolderIcon()
+ */
+ private static class FileChooserHomeFolderIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserHomeFolderIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+
+ // roof
+ g.drawLine(x + 1, y + 8, x + 8, y + 1);
+ g.drawLine(x + 8, y + 1, x + 15, y + 8);
+
+ // base of house
+ g.drawLine(x + 3, y + 6, x + 3, y + 15);
+ g.drawLine(x + 3, y + 15, x + 13, y + 15);
+ g.drawLine(x + 13, y + 6, x + 13, y + 15);
+
+ // door frame
+ g.drawLine(x + 6, y + 9, x + 6, y + 15);
+ g.drawLine(x + 6, y + 9, x + 10, y + 9);
+ g.drawLine(x + 10, y + 9, x + 10, y + 15);
+
+ // chimney
+ g.drawLine(x + 11, y + 2, x + 11, y + 4);
+ g.drawLine(x + 12, y + 2, x + 12, y + 5);
+
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+
+ // roof paint
+ int xx = x + 8;
+ for (int i = 0; i < 4; i++)
+ g.drawLine(xx - i, y + 2 + i, xx + i, y + 2 + i);
+ g.fillRect(x + 4, y + 6, 9, 2);
+
+ // door knob
+ g.drawLine(x + 9, y + 12, x + 9, y + 12);
+
+ // house paint
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.drawLine(x + 4, y + 8, x + 12, y + 8);
+ g.fillRect(x + 4, y + 9, 2, 6);
+ g.fillRect(x + 11, y + 9, 2, 6);
+
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the "list view" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserListViewIcon()
+ */
+ private static class FileChooserListViewIcon
+ implements Icon, UIResource, Serializable
+ {
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserListViewIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+
+ // file 1 outline
+ g.drawLine(x + 2, y + 2, x + 5, y + 2);
+ g.drawLine(x + 6, y + 3, x + 6, y + 7);
+ g.drawLine(x + 2, y + 7, x + 6, y + 7);
+ g.drawLine(x + 2, y + 2, x + 2, y + 7);
+
+ // file 2 outline
+ g.drawLine(x + 2, y + 10, x + 5, y + 10);
+ g.drawLine(x + 6, y + 11, x + 6, y + 15);
+ g.drawLine(x + 2, y + 15, x + 6, y + 15);
+ g.drawLine(x + 2, y + 10, x + 2, y + 15);
+
+ // file 3 outline
+ g.drawLine(x + 10, y + 2, x + 13, y + 2);
+ g.drawLine(x + 14, y + 3, x + 14, y + 7);
+ g.drawLine(x + 10, y + 7, x + 14, y + 7);
+ g.drawLine(x + 10, y + 2, x + 10, y + 7);
+
+ // file 4 outline
+ g.drawLine(x + 10, y + 10, x + 13, y + 10);
+ g.drawLine(x + 14, y + 11, x + 14, y + 15);
+ g.drawLine(x + 10, y + 15, x + 14, y + 15);
+ g.drawLine(x + 10, y + 10, x + 10, y + 15);
+
+ g.drawLine(x + 8, y + 5, x + 8, y + 5);
+ g.drawLine(x + 8, y + 13, x + 8, y + 13);
+ g.drawLine(x + 16, y + 5, x + 16, y + 5);
+ g.drawLine(x + 16, y + 13, x + 16, y + 13);
+
+ // fill files
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 3, y + 3, 3, 4);
+ g.fillRect(x + 3, y + 11, 3, 4);
+ g.fillRect(x + 11, y + 3, 3, 4);
+ g.fillRect(x + 11, y + 11, 3, 4);
+
+ // highlight files
+ g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
+ g.drawLine(x + 4, y + 4, x + 4, y + 5);
+ g.drawLine(x + 4, y + 12, x + 4, y + 13);
+ g.drawLine(x + 12, y + 4, x + 12, y + 5);
+ g.drawLine(x + 12, y + 12, x + 12, y + 13);
+
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the "new folder" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserNewFolderIcon()
+ */
+ private static class FileChooserNewFolderIcon
+ implements Icon, UIResource, Serializable
+ {
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserNewFolderIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+
+ g.drawLine(x + 2, y + 5, x + 9, y + 5);
+ g.drawLine(x + 10, y + 6, x + 15, y + 6);
+ g.drawLine(x + 15, y + 5, x + 15, y + 14);
+ g.drawLine(x + 2, y + 14, x + 15, y + 14);
+ g.drawLine(x + 1, y + 6, x + 1, y + 14);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.drawLine(x + 11, y + 3, x + 15, y + 3);
+ g.drawLine(x + 10, y + 4, x + 15, y + 4);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 3, y + 7, 7, 7);
+ g.fillRect(x + 10, y + 8, 5, 6);
+ g.drawLine(x + 10, y + 5, x + 14, y + 5);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
+ g.drawLine(x + 10, y + 7, x + 14, y + 7);
+ g.drawLine(x + 2, y + 6, x + 9, y + 6);
+ g.drawLine(x + 2, y + 6, x + 2, y + 13);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the "up folder" button on a {@link JFileChooser} under
+ * the {@link MetalLookAndFeel}.
+ *
+ * @see MetalIconFactory#getFileChooserNewFolderIcon()
+ */
+ private static class FileChooserUpFolderIcon extends FileChooserNewFolderIcon
+ {
+ /**
+ * Creates a new icon.
+ */
+ public FileChooserUpFolderIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+
+ // draw the folder
+ super.paintIcon(c, g, x, y);
+
+ // now draw the up arrow
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 8, y + 9, x + 8, y + 16);
+ int xx = x + 8;
+ for (int i = 0; i < 4; i++)
+ g.drawLine(xx - i, y + 9 + i, xx + i, y + 9 + i);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon representing a file (drawn as a piece of paper with the top-right
+ * corner turned down).
+ */
+ public static class FileIcon16 implements Icon, Serializable
+ {
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels. The height returned is
+ * <code>16</code> plus the value returned by
+ * {@link #getAdditionalHeight()}.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 16 + getAdditionalHeight();
+ }
+
+ /**
+ * Paints the icon at the location (x, y).
+ *
+ * @param c the component.
+ * @param g the graphics context.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ y = y + getShift();
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x, y, x + 9, y);
+ g.drawLine(x, y + 1, x, y + 15);
+ g.drawLine(x, y + 15, x + 12, y + 15);
+ g.drawLine(x + 12, y + 15, x + 12, y + 6);
+ g.drawLine(x + 12, y + 6, x + 9, y);
+
+ g.drawLine(x + 7, y + 2, x + 11, y + 6);
+ g.drawLine(x + 8, y + 1, x + 9, y + 1);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.drawLine(x + 1, y + 1, x + 7, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + 14);
+ g.drawLine(x + 1, y + 14, x + 11, y + 14);
+ g.drawLine(x + 11, y + 14, x + 11, y + 7);
+ g.drawLine(x + 8, y + 2, x + 10, y + 4);
+ }
+
+ /**
+ * Returns the additional height for the icon. The
+ * {@link #getIconHeight()} method adds this value to the icon height it
+ * returns. Subclasses can override this method to adjust the icon height.
+ *
+ * @return The additional height (<code>0</code> unless overridden).
+ */
+ public int getAdditionalHeight()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the vertical shift, in pixels, applied when painting the icon.
+ * The default value is zero, but subclasses may override this (for
+ * example, see {@link TreeLeafIcon}).
+ *
+ * @return The shift.
+ */
+ public int getShift()
+ {
+ return 0;
+ }
+
+ }
+
+ /**
+ * An icon representing a folder.
+ */
+ public static class FolderIcon16 implements Icon, Serializable
+ {
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels. The height returned is
+ * <code>16</code> plus the value returned by
+ * {@link #getAdditionalHeight()}.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 16 + getAdditionalHeight();
+ }
+
+ /**
+ * Paints the icon at the location (x, y).
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ y = y + getShift();
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x, y + 6, x, y + 15);
+ g.drawLine(x, y + 15, x + 15, y + 15);
+ g.drawLine(x + 15, y + 15, x + 15, y + 5);
+ g.drawLine(x + 14, y + 6, x + 9, y + 6);
+ g.drawLine(x + 8, y + 5, x + 1, y + 5);
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 7, 7, 8);
+ g.fillRect(x + 9, y + 8, 6, 7);
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ g.drawLine(x + 9, y + 5, x + 14, y + 5);
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.drawLine(x + 9, y + 4, x + 15, y + 4);
+ g.drawLine(x + 10, y + 3, x + 15, y + 3);
+ }
+
+ /**
+ * Returns the additional height for the icon. The
+ * {@link #getIconHeight()} method adds this value to the icon height it
+ * returns. Subclasses can override this method to adjust the icon height.
+ *
+ * @return The additional height (<code>0</code> unless overridden).
+ */
+ public int getAdditionalHeight()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the vertical shift, in pixels, applied when painting the icon.
+ * The default value is zero, but subclasses may override this (for
+ * example, see {@link TreeFolderIcon}).
+ *
+ * @return The shift.
+ */
+ public int getShift()
+ {
+ return 0;
+ }
+
+ }
+
+ /**
+ * An icon used by the {@link MetalInternalFrameUI} class when the frame
+ * is displayed as a palette.
+ *
+ * @since 1.3
+ */
+ public static class PaletteCloseIcon
+ implements Icon, Serializable, UIResource
+ {
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 7;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 7;
+ }
+
+ /**
+ * Paints the icon using colors from the {@link MetalLookAndFeel}.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ AbstractButton button = (AbstractButton) c;
+ if (button.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.fillRect(x + 2, y + 2, 3, 3);
+ g.drawLine(x + 1, y, x + 1, y + 2);
+ g.drawLine(x, y + 1, x + 2, y + 1);
+ g.drawLine(x + 5, y, x + 5, y + 2);
+ g.drawLine(x + 4, y + 1, x + 6, y + 1);
+ g.drawLine(x + 1, y + 4, x + 1, y + 6);
+ g.drawLine(x, y + 5, x + 2, y + 5);
+ g.drawLine(x + 5, y + 4, x + 5, y + 6);
+ g.drawLine(x + 4, y + 5, x + 6, y + 5);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(x + 2, y + 6, x + 3, y + 5);
+ g.drawLine(x + 5, y + 3, x + 6, y + 2);
+ g.drawLine(x + 6, y + 6, x + 6, y + 6);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An {@link Icon} implementation for {@link JCheckBox}es in the
+ * Metal Look &amp; Feel.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+ static class RadioButtonIcon implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * This is used as a mask when painting the gradient. See
+ * {@link MetalUtils#paintGradient(java.awt.Graphics, int, int, int, int,
+ * float, float, java.awt.Color, java.awt.Color, java.awt.Color, int,
+ * int[][])} for details.
+ */
+ private static int[][] gradientMask = new int[][] {{3, 7}, {1, 9}, {1, 9},
+ {0, 10}, {0, 10}, {0, 10},
+ {0, 10}, {1, 9}, {1, 9},
+ {3, 7}};
+
+ /**
+ * Returns the width of the icon in pixels.
+ *
+ * @return the width of the icon in pixels
+ */
+ public int getIconWidth()
+ {
+ return 13;
+ }
+
+ /**
+ * Returns the height of the icon in pixels.
+ *
+ * @return the height of the icon in pixels
+ */
+ public int getIconHeight()
+ {
+ return 13;
+ }
+
+ /**
+ * Paints the icon, taking into account whether or not the component is
+ * enabled, selected and/or armed.
+ *
+ * @param c the Component to draw on (must be an instance of
+ * {@link JRadioButton})
+ * @param g the Graphics context to draw with
+ * @param x the X position
+ * @param y the Y position
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ if (UIManager.get("RadioButton.gradient") != null)
+ MetalUtils.paintGradient(g, x + 2, y + 2, 8, 8,
+ SwingConstants.VERTICAL, "RadioButton.gradient",
+ gradientMask);
+
+ Color savedColor = g.getColor();
+ JRadioButton b = (JRadioButton) c;
+
+ // draw outer circle
+ if (b.isEnabled())
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(x + 2, y + 1, x + 3, y + 1);
+ g.drawLine(x + 4, y, x + 7, y);
+ g.drawLine(x + 8, y + 1, x + 9, y + 1);
+ g.drawLine(x + 10, y + 2, x + 10, y + 3);
+ g.drawLine(x + 11, y + 4, x + 11, y + 7);
+ g.drawLine(x + 10, y + 8, x + 10, y + 9);
+ g.drawLine(x + 8, y + 10, x + 9, y + 10);
+ g.drawLine(x + 4, y + 11, x + 7, y + 11);
+ g.drawLine(x + 2, y + 10, x + 3, y + 10);
+ g.drawLine(x + 1, y + 9, x + 1, y + 8);
+ g.drawLine(x, y + 7, x, y + 4);
+ g.drawLine(x + 1, y + 2, x + 1, y + 3);
+
+ if (b.getModel().isArmed())
+ {
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x + 4, y + 1, x + 7, y + 1);
+ g.drawLine(x + 4, y + 10, x + 7, y + 10);
+ g.drawLine(x + 1, y + 4, x + 1, y + 7);
+ g.drawLine(x + 10, y + 4, x + 10, y + 7);
+ g.fillRect(x + 2, y + 2, 8, 8);
+ }
+ else
+ {
+ // only draw inner highlight if not filled
+ if (b.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+
+ g.drawLine(x + 2, y + 8, x + 2, y + 9);
+ g.drawLine(x + 1, y + 4, x + 1, y + 7);
+ g.drawLine(x + 2, y + 2, x + 2, y + 3);
+ g.drawLine(x + 3, y + 2, x + 3, y + 2);
+ g.drawLine(x + 4, y + 1, x + 7, y + 1);
+ g.drawLine(x + 8, y + 2, x + 9, y + 2);
+ }
+ }
+
+ // draw outer highlight
+ if (b.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+
+ // outer
+ g.drawLine(x + 10, y + 1, x + 10, y + 1);
+ g.drawLine(x + 11, y + 2, x + 11, y + 3);
+ g.drawLine(x + 12, y + 4, x + 12, y + 7);
+ g.drawLine(x + 11, y + 8, x + 11, y + 9);
+ g.drawLine(x + 10, y + 10, x + 10, y + 10);
+ g.drawLine(x + 8, y + 11, x + 9, y + 11);
+ g.drawLine(x + 4, y + 12, x + 7, y + 12);
+ g.drawLine(x + 2, y + 11, x + 3, y + 11);
+ }
+
+ if (b.isSelected())
+ {
+ if (b.isEnabled())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(x + 4, y + 3, x + 7, y + 3);
+ g.fillRect(x + 3, y + 4, 6, 4);
+ g.drawLine(x + 4, y + 8, x + 7, y + 8);
+ }
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon displayed for {@link JRadioButtonMenuItem} components.
+ */
+ private static class RadioButtonMenuItemIcon
+ implements Icon, UIResource, Serializable
+ {
+ /**
+ * Creates a new icon instance.
+ */
+ public RadioButtonMenuItemIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 10;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 10;
+ }
+
+ /**
+ * Paints the icon.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ JRadioButtonMenuItem item = (JRadioButtonMenuItem) c;
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 2, y, x + 6, y);
+ g.drawLine(x + 7, y + 1, x + 7, y + 1);
+ g.drawLine(x + 8, y + 2, x + 8, y + 6);
+ g.drawLine(x + 7, y + 7, x + 7, y + 7);
+ g.drawLine(x + 2, y + 8, x + 6, y + 8);
+ g.drawLine(x + 1, y + 7, x + 1, y + 7);
+ g.drawLine(x, y + 2, x, y + 6);
+ g.drawLine(x + 1, y + 1, x + 1, y + 1);
+
+ if (item.isSelected())
+ {
+ g.drawLine(x + 3, y + 2, x + 5, y + 2);
+ g.fillRect(x + 2, y + 3, 5, 3);
+ g.drawLine(x + 3, y + 6, x + 5, y + 6);
+ }
+
+ // highlight
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(x + 3, y + 1, x + 6, y + 1);
+ g.drawLine(x + 8, y + 1, x + 8, y + 1);
+ g.drawLine(x + 9, y + 2, x + 9, y + 7);
+ g.drawLine(x + 8, y + 8, x + 8, y + 8);
+ g.drawLine(x + 2, y + 9, x + 7, y + 9);
+ g.drawLine(x + 1, y + 8, x + 1, y + 8);
+ g.drawLine(x + 1, y + 3, x + 1, y + 6);
+ g.drawLine(x + 2, y + 2, x + 2, y + 2);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * The icon used to display the thumb control on a horizontally oriented
+ * {@link JSlider} component.
+ */
+ private static class HorizontalSliderThumbIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * This mask is used to paint the gradient in the shape of the thumb.
+ */
+ int[][] gradientMask = new int[][] { {0, 12}, {0, 12}, {0, 12}, {0, 12},
+ {0, 12}, {0, 12}, {0, 12}, {1, 11},
+ {2, 10}, {3, 9}, {4, 8}, {5, 7},
+ {6, 6}};
+
+ /**
+ * Creates a new instance.
+ */
+ public HorizontalSliderThumbIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 15;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon, taking into account whether or not the component has
+ * the focus.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ boolean enabled = false;
+ boolean focus = false;
+ if (c != null)
+ {
+ enabled = c.isEnabled();
+ focus = c.hasFocus();
+ }
+
+ // draw the outline
+ if (enabled)
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x + 1, y, x + 13, y);
+ g.drawLine(x + 14, y + 1, x + 14, y + 7);
+ g.drawLine(x + 14, y + 8, x + 7, y + 15);
+ g.drawLine(x + 6, y + 14, x, y + 8);
+ g.drawLine(x, y + 7, x, y + 1);
+
+// The following is commented out until the masking for the gradient painting
+// is working correctly
+// // Fill the icon.
+// if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme
+// && enabled)
+// {
+// String gradient;
+// if (focus)
+// gradient = "Slider.focusGradient";
+// else
+// gradient = "Slider.gradient";
+// MetalUtils.paintGradient(g, x + 1, y + 2, 12, 13,
+// SwingConstants.VERTICAL, gradient,
+// gradientMask);
+// }
+// else
+ {
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(x + 1, y + 2, 13, 7);
+ g.drawLine(x + 2, y + 9, x + 12, y + 9);
+ g.drawLine(x + 3, y + 10, x + 11, y + 10);
+ g.drawLine(x + 4, y + 11, x + 10, y + 11);
+ g.drawLine(x + 5, y + 12, x + 9, y + 12);
+ g.drawLine(x + 6, y + 13, x + 8, y + 13);
+ g.drawLine(x + 7, y + 14, x + 7, y + 14);
+ }
+
+ // If the slider is enabled, draw dots and highlights.
+ if (c.isEnabled()
+ && !(MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme))
+ {
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 3, y + 3, x + 3, y + 3);
+ g.drawLine(x + 7, y + 3, x + 7, y + 3);
+ g.drawLine(x + 11, y + 3, x + 11, y + 3);
+
+ g.drawLine(x + 5, y + 5, x + 5, y + 5);
+ g.drawLine(x + 9, y + 5, x + 9, y + 5);
+
+ g.drawLine(x + 3, y + 7, x + 3, y + 7);
+ g.drawLine(x + 7, y + 7, x + 7, y + 7);
+ g.drawLine(x + 11, y + 7, x + 11, y + 7);
+
+ // Draw highlights
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ else
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 1, y + 1, x + 13, y + 1);
+ g.drawLine(x + 1, y + 2, x + 1, y + 8);
+ g.drawLine(x + 2, y + 2, x + 2, y + 2);
+ g.drawLine(x + 6, y + 2, x + 6, y + 2);
+ g.drawLine(x + 10, y + 2, x + 10, y + 2);
+
+ g.drawLine(x + 4, y + 4, x + 4, y + 4);
+ g.drawLine(x + 8, y + 4, x + 8, y + 4);
+
+ g.drawLine(x + 2, y + 6, x + 2, y + 6);
+ g.drawLine(x + 6, y + 6, x + 6, y + 6);
+ g.drawLine(x + 10, y + 6, x + 10, y + 6);
+ }
+
+ }
+ }
+
+ /**
+ * An icon used for the 'close' button in the title frame of a
+ * {@link JInternalFrame}.
+ */
+ private static class InternalFrameCloseIcon
+ implements Icon, UIResource, Serializable
+ {
+ /** The icon size in pixels. */
+ private int size;
+
+ /**
+ * Creates a new icon.
+ *
+ * @param size the icon size (width and height) in pixels.
+ */
+ public InternalFrameCloseIcon(int size)
+ {
+ this.size = size;
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return size;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return size;
+ }
+
+ /**
+ * Paints the icon.
+ *
+ * @param c the component (an {@link JInternalFrame} is expected).
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+ AbstractButton b = (AbstractButton) c;
+
+ // fill the interior
+ if (b.getModel().isPressed())
+ // FIXME: also need to take into account whether the internal frame is
+ // selected
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 2, 10, 10);
+
+ // draw the outline box and the cross
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ {
+ // FIXME: also need to take into account whether the internal frame is
+ // selected
+ boolean selected = true;
+ if (selected)
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ }
+ g.drawLine(x + 1, y + 1, x + 13, y + 1);
+ g.drawLine(x + 1, y + 2, x + 1, y + 12);
+ g.drawLine(x + 1, y + 13, x + 13, y + 13);
+ g.drawLine(x + 13, y + 2, x + 13, y + 12);
+ g.drawLine(x + 2, y + 12, x + 2, y + 12);
+ g.drawLine(x + 12, y + 2, x + 12, y + 2);
+
+ g.fillRect(x + 4, y + 4, 2, 2);
+ g.fillRect(x + 5, y + 5, 4, 4);
+ g.drawLine(x + 9, y + 4, x + 10, y + 4);
+ g.drawLine(x + 9, y + 4, x + 9, y + 5);
+ g.drawLine(x + 4, y + 9, x + 4, y + 10);
+ g.drawLine(x + 4, y + 9, x + 5, y + 9);
+ g.drawLine(x + 9, y + 8, x + 9, y + 10);
+ g.drawLine(x + 8, y + 9, x + 10, y + 9);
+
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x, y, x + 13, y);
+ g.drawLine(x, y + 1, x, y + 13);
+ g.drawLine(x + 3, y + 4, x + 4, y + 3);
+ g.drawLine(x + 3, y + 9, x + 5, y + 7);
+ g.drawLine(x + 7, y + 5, x + 9, y + 3);
+
+ g.drawLine(x + 12, y + 3, x + 12, y + 11);
+ g.drawLine(x + 3, y + 12, x + 12, y + 12);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 1, y + 14, x + 14, y + 14);
+ g.drawLine(x + 14, y + 1, x + 14, y + 14);
+
+ if (!b.getModel().isPressed())
+ {
+ g.drawLine(x + 5, y + 10, x + 5, y + 10);
+ g.drawLine(x + 6, y + 9, x + 7, y + 9);
+ g.drawLine(x + 10, y + 5, x + 10, y + 5);
+ g.drawLine(x + 9, y + 6, x + 9, y + 7);
+ g.drawLine(x + 10, y + 10, x + 11, y + 10);
+ g.drawLine(x + 10, y + 11, x + 10, y + 11);
+ }
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * The icon displayed at the top-left corner of a {@link JInternalFrame}.
+ */
+ private static class InternalFrameDefaultMenuIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * Creates a new instance.
+ */
+ public InternalFrameDefaultMenuIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.fillRect(x + 1, y, 14, 2);
+ g.fillRect(x, y + 1, 2, 14);
+ g.fillRect(x + 1, y + 14, 14, 2);
+ g.fillRect(x + 14, y + 1, 2, 14);
+ g.drawLine(x + 2, y + 5, x + 14, y + 5);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 2, 12, 3);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.drawLine(x + 3, y + 3, x + 3, y + 3);
+ g.drawLine(x + 6, y + 3, x + 6, y + 3);
+ g.drawLine(x + 9, y + 3, x + 9, y + 3);
+ g.drawLine(x + 12, y + 3, x + 12, y + 3);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.fillRect(x + 2, y + 6, 12, 8);
+ g.drawLine(x + 2, y + 2, x + 2, y + 2);
+ g.drawLine(x + 5, y + 2, x + 5, y + 2);
+ g.drawLine(x + 8, y + 2, x + 8, y + 2);
+ g.drawLine(x + 11, y + 2, x + 11, y + 2);
+ }
+ }
+
+ /**
+ * An icon used in the title frame of a {@link JInternalFrame}. When you
+ * maximise an internal frame, this icon will replace the 'maximise' icon to
+ * provide a 'restore' option.
+ */
+ private static class InternalFrameAltMaximizeIcon
+ implements Icon, UIResource, Serializable
+ {
+ /** The icon size in pixels. */
+ private int size;
+
+ /**
+ * Creates a new icon.
+ *
+ * @param size the icon size in pixels.
+ */
+ public InternalFrameAltMaximizeIcon(int size)
+ {
+ this.size = size;
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return size;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return size;
+ }
+
+ /**
+ * Paints the icon at the specified location.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+
+ AbstractButton b = (AbstractButton) c;
+
+ // fill the small box interior
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 6, 7, 7);
+
+
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+
+ g.drawLine(x + 12, y + 1, x + 13, y + 1);
+ g.drawLine(x + 11, y + 2, x + 12, y + 2);
+ g.drawLine(x + 10, y + 3, x + 11, y + 3);
+ g.drawLine(x + 8, y + 2, x + 8, y + 3);
+ g.fillRect(x + 8, y + 4, 3, 3);
+ g.drawLine(x + 11, y + 6, x + 12, y + 6);
+
+ g.drawLine(x + 1, y + 5, x + 5, y + 5);
+ g.drawLine(x + 1, y + 6, x + 1, y + 12);
+ g.drawLine(x + 9, y + 9, x + 9, y + 12);
+ g.drawLine(x + 1, y + 13, x + 9, y + 13);
+
+ g.drawLine(x + 2, y + 12, x + 2, y + 12);
+
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 12, y, x + 9, y + 3);
+ g.drawLine(x + 7, y + 1, x + 8, y + 1);
+ g.drawLine(x + 7, y + 2, x + 7, y + 6);
+ g.drawLine(x + 11, y + 5, x + 12, y + 5);
+ g.drawLine(x, y + 4, x + 5, y + 4);
+ g.drawLine(x, y + 5, x, y + 13);
+ g.drawLine(x + 3, y + 12, x + 8, y + 12);
+ g.drawLine(x + 8, y + 8, x + 8, y + 11);
+ g.drawLine(x + 9, y + 8, x + 9, y + 8);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 9, y + 2, x + 9, y + 2);
+ g.drawLine(x + 11, y + 4, x + 13, y + 2);
+ g.drawLine(x + 13, y + 6, x + 13, y + 6);
+ g.drawLine(x + 8, y + 7, x + 13, y + 7);
+ g.drawLine(x + 6, y + 5, x + 6, y + 5);
+ g.drawLine(x + 10, y + 8, x + 10, y + 13);
+ g.drawLine(x + 1, y + 14, x + 10, y + 14);
+
+ if (!b.getModel().isPressed())
+ {
+ g.drawLine(x + 2, y + 6, x + 6, y + 6);
+ g.drawLine(x + 2, y + 6, x + 2, y + 11);
+ }
+
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used for the 'maximize' button in the title frame of a
+ * {@link JInternalFrame}.
+ */
+ private static class InternalFrameMaximizeIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * Creates a new instance.
+ */
+ public InternalFrameMaximizeIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+
+ AbstractButton b = (AbstractButton) c;
+
+ // fill the interior
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 6, 7, 7);
+
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+
+ g.drawLine(x + 9, y + 1, x + 10, y + 1);
+ g.fillRect(x + 11, y + 1, 3, 3);
+ g.fillRect(x + 12, y + 4, 2, 2);
+ g.drawLine(x + 10, y + 3, x + 10, y + 3);
+ g.drawLine(x + 9, y + 4, x + 10, y + 4);
+ g.drawLine(x + 1, y + 5, x + 9, y + 5);
+ g.drawLine(x + 1, y + 6, x + 1, y + 12);
+ g.drawLine(x + 9, y + 6, x + 9, y + 12);
+ g.drawLine(x + 1, y + 13, x + 9, y + 13);
+
+ // fill
+ g.drawLine(x + 7, y + 6, x + 8, y + 6);
+ g.drawLine(x + 6, y + 7, x + 8, y + 7);
+ g.drawLine(x + 5, y + 8, x + 6, y + 8);
+ g.drawLine(x + 4, y + 9, x + 5, y + 9);
+ g.drawLine(x + 3, y + 10, x + 4, y + 10);
+ g.drawLine(x + 2, y + 11, x + 3, y + 11);
+ g.drawLine(x + 2, y + 12, x + 4, y + 12);
+ g.drawLine(x + 8, y + 8, x + 8, y + 8);
+
+ // draw black
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 8, y, x + 13, y);
+ g.drawLine(x + 8, y + 1, x + 8, y + 1);
+ g.drawLine(x + 10, y + 2, x + 9, y + 3);
+ g.drawLine(x, y + 4, x + 8, y + 4);
+ g.drawLine(x, y + 5, x, y + 13);
+
+ g.drawLine(x + 2, y + 10, x + 6, y + 6);
+ g.drawLine(x + 8, y + 9, x + 8, y + 11);
+ g.drawLine(x + 5, y + 12, x + 8, y + 12);
+
+ // draw white
+ g.setColor(MetalLookAndFeel.getWhite());
+ if (!b.getModel().isPressed())
+ {
+ g.drawLine(x + 2, y + 6, x + 5, y + 6);
+ g.drawLine(x + 2, y + 7, x + 2, y + 9);
+ g.drawLine(x + 4, y + 11, x + 7, y + 8);
+ }
+
+ g.drawLine(x + 1, y + 14, x + 10, y + 14);
+ g.drawLine(x + 10, y + 5, x + 10, y + 13);
+
+ g.drawLine(x + 9, y + 2, x + 9, y + 2);
+ g.drawLine(x + 11, y + 4, x + 11, y + 5);
+ g.drawLine(x + 13, y + 6, x + 14, y + 6);
+ g.drawLine(x + 14, y + 1, x + 14, y + 5);
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * An icon used in the title frame of a {@link JInternalFrame}.
+ */
+ private static class InternalFrameMinimizeIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * Creates a new instance.
+ */
+ public InternalFrameMinimizeIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color savedColor = g.getColor();
+
+ AbstractButton b = (AbstractButton) c;
+
+ if (b.getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ // FIXME: here the color depends on whether or not the internal frame
+ // is selected
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+
+ g.drawLine(x + 12, y + 1, x + 13, y + 1);
+ g.drawLine(x + 11, y + 2, x + 12, y + 2);
+ g.drawLine(x + 10, y + 3, x + 11, y + 3);
+ g.drawLine(x + 8, y + 2, x + 8, y + 3);
+ g.fillRect(x + 8, y + 4, 3, 3);
+ g.drawLine(x + 11, y + 6, x + 12, y + 6);
+
+ g.drawLine(x + 1, y + 8, x + 6, y + 8);
+ g.drawLine(x + 1, y + 9, x + 1, y + 12);
+ g.drawLine(x + 6, y + 9, x + 6, y + 12);
+ g.drawLine(x + 1, y + 13, x + 6, y + 13);
+
+ g.drawLine(x + 5, y + 9, x + 5, y + 9);
+ g.drawLine(x + 2, y + 12, x + 2, y + 12);
+
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 12, y, x + 9, y + 3);
+ g.drawLine(x + 7, y + 1, x + 8, y + 1);
+ g.drawLine(x + 7, y + 2, x + 7, y + 6);
+ g.drawLine(x, y + 7, x + 6, y + 7);
+ g.drawLine(x, y + 8, x, y + 13);
+ g.drawLine(x + 3, y + 12, x + 5, y + 12);
+ g.drawLine(x + 5, y + 10, x + 5, y + 11);
+ g.drawLine(x + 11, y + 5, x + 12, y + 5);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 9, y + 2, x + 9, y + 2);
+ g.drawLine(x + 11, y + 4, x + 13, y + 2);
+ g.drawLine(x + 13, y + 6, x + 13, y + 6);
+ g.drawLine(x + 8, y + 7, x + 13, y + 7);
+ g.drawLine(x + 7, y + 9, x + 7, y + 13);
+ g.drawLine(x + 1, y + 14, x + 7, y + 14);
+
+ if (b.getModel().isPressed())
+ {
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ g.fillRect(x + 2, y + 9, 3, 3);
+ }
+ else
+ {
+ g.drawLine(x + 2, y + 9, x + 4, y + 9);
+ g.drawLine(x + 2, y + 10, x + 2, y + 11);
+ }
+
+ g.setColor(savedColor);
+ }
+ }
+
+ /**
+ * The icon used to display the thumb control on a horizontally oriented
+ * {@link JSlider} component.
+ */
+ private static class VerticalSliderThumbIcon
+ implements Icon, UIResource, Serializable
+ {
+ /**
+ * This mask is used to paint the gradient in the shape of the thumb.
+ */
+ int[][] gradientMask = new int[][] { {0, 12}, {0, 12}, {0, 12}, {0, 12},
+ {0, 12}, {0, 12}, {0, 12}, {1, 11},
+ {2, 10}, {3, 9}, {4, 8}, {5, 7},
+ {6, 6}};
+
+ /**
+ * Creates a new instance.
+ */
+ public VerticalSliderThumbIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 15;
+ }
+
+ /**
+ * Paints the icon taking into account whether the slider control has the
+ * focus or not.
+ *
+ * @param c the slider (must be a non-<code>null</code> instance of
+ * {@link JSlider}.
+ * @param g the graphics device.
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ boolean enabled = false;
+ boolean focus = false;
+ if (c != null)
+ {
+ enabled = c.isEnabled();
+ focus = c.hasFocus();
+ }
+
+ // draw the outline
+ if (enabled)
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x + 1, y, x + 7, y);
+ g.drawLine(x + 8, y, x + 15, y + 7);
+ g.drawLine(x + 14, y + 8, x + 8, y + 14);
+ g.drawLine(x + 8, y + 14, x + 1, y + 14);
+ g.drawLine(x, y + 13, x, y + 1);
+
+// The following is commented out until the masking for the gradient painting
+// is working correctly
+// // Fill the icon.
+// if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme
+// && enabled)
+// {
+// String gradient;
+// if (focus)
+// gradient = "Slider.focusGradient";
+// else
+// gradient = "Slider.gradient";
+// MetalUtils.paintGradient(g, x + 2, y + 1, 13, 12,
+// SwingConstants.HORIZONTAL, gradient,
+// gradientMask);
+// }
+// else
+ {
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(x + 2, y + 1, 7, 13);
+ g.drawLine(x + 9, y + 2, x + 9, y + 12);
+ g.drawLine(x + 10, y + 3, x + 10, y + 11);
+ g.drawLine(x + 11, y + 4, x + 11, y + 10);
+ g.drawLine(x + 12, y + 5, x + 12, y + 9);
+ g.drawLine(x + 13, y + 6, x + 13, y + 8);
+ g.drawLine(x + 14, y + 7, x + 14, y + 7);
+ }
+
+ // if the slider is enabled, draw dots and highlights
+ if (enabled
+ && ! (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme))
+ {
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ else
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 3, y + 3, x + 3, y + 3);
+ g.drawLine(x + 3, y + 7, x + 3, y + 7);
+ g.drawLine(x + 3, y + 11, x + 3, y + 11);
+
+ g.drawLine(x + 5, y + 5, x + 5, y + 5);
+ g.drawLine(x + 5, y + 9, x + 5, y + 9);
+
+ g.drawLine(x + 7, y + 3, x + 7, y + 3);
+ g.drawLine(x + 7, y + 7, x + 7, y + 7);
+ g.drawLine(x + 7, y + 11, x + 7, y + 11);
+
+ // draw highlights
+ if (focus)
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ else
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 1, y + 1, x + 8, y + 1);
+ g.drawLine(x + 1, y + 2, x + 1, y + 13);
+ g.drawLine(x + 2, y + 2, x + 2, y + 2);
+ g.drawLine(x + 2, y + 6, x + 2, y + 6);
+ g.drawLine(x + 2, y + 10, x + 2, y + 10);
+
+ g.drawLine(x + 4, y + 4, x + 4, y + 4);
+ g.drawLine(x + 4, y + 8, x + 4, y + 8);
+
+ g.drawLine(x + 6, y + 2, x + 6, y + 2);
+ g.drawLine(x + 6, y + 6, x + 6, y + 6);
+ g.drawLine(x + 6, y + 10, x + 6, y + 10);
+
+ }
+ }
+ }
+
+ /**
+ * A tree control icon. This icon can be in one of two states: expanded and
+ * collapsed.
+ */
+ public static class TreeControlIcon implements Icon, Serializable
+ {
+
+ /** ???. */
+ protected boolean isLight;
+
+ /** A flag that controls whether or not the icon is collapsed. */
+ private boolean collapsed;
+
+ /**
+ * Creates a new icon.
+ *
+ * @param isCollapsed a flag that controls whether the icon is in the
+ * collapsed state or the expanded state.
+ */
+ public TreeControlIcon(boolean isCollapsed)
+ {
+ collapsed = isCollapsed;
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 18;
+ }
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 18;
+ }
+
+ /**
+ * Paints the icon at the location (x, y).
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ // TODO: pick up appropriate UI colors
+ Color dark = new Color(99, 130, 191);
+ Color light = new Color(163, 184, 204);
+ Color white = Color.white;
+
+ x += 8;
+ y += 6;
+
+ final int w = 6;
+ final int wHalf = (w >> 2);
+ g.setColor(light);
+ g.drawOval(x, y, w, w);
+ g.setColor(dark);
+ g.fillOval(x + 1, y + 1, w - 1, w - 1);
+
+ if (collapsed)
+ g.fillRect(x + w, y + wHalf + 1, w, 2);
+ else
+ g.fillRect(x + wHalf + 1, y + w, 2, w);
+
+ g.setColor(white);
+ g.fillRect(x + wHalf + 1, y + wHalf + 1, 2, 2);
+
+ }
+
+ /**
+ * Simply calls {@link #paintIcon(Component, Graphics, int, int)}.
+ *
+ * @param c the component.
+ * @param g the graphics device.
+ * @param x the x coordinate.
+ * @param y the y coordinate.
+ */
+ public void paintMe(Component c, Graphics g, int x, int y)
+ {
+ paintIcon(c, g, x, y);
+ }
+ }
+
+ /**
+ * A tree folder icon.
+ */
+ public static class TreeFolderIcon extends FolderIcon16
+ {
+ /**
+ * Creates a new instance.
+ */
+ public TreeFolderIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the additional height for this icon, in this case <code>2</code>
+ * pixels.
+ *
+ * @return <code>2</code>.
+ */
+ public int getAdditionalHeight()
+ {
+ return 2;
+ }
+
+ /**
+ * Returns the vertical shift, in pixels, applied when painting the icon.
+ * This overridden method returns <code>-1</code>.
+ *
+ * @return The shift.
+ */
+ public int getShift()
+ {
+ return -1;
+ }
+ }
+
+ /**
+ * A tree leaf icon.
+ */
+ public static class TreeLeafIcon extends FileIcon16
+ {
+ /**
+ * Creates a new instance.
+ */
+ public TreeLeafIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the additional height for this icon, in this case <code>4</code>
+ * pixels.
+ *
+ * @return <code>4</code>.
+ */
+ public int getAdditionalHeight()
+ {
+ return 4;
+ }
+
+ /**
+ * Returns the vertical shift, in pixels, applied when painting the icon.
+ * This overridden method returns <code>2</code>.
+ *
+ * @return The shift.
+ */
+ public int getShift()
+ {
+ return 2;
+ }
+ }
+
+ /**
+ * An icon representing a hard disk.
+ *
+ * @see MetalIconFactory#getTreeHardDriveIcon()
+ */
+ private static class TreeHardDriveIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * Creates a new icon instance.
+ */
+ public TreeHardDriveIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location, using colors from the
+ * current theme.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 1, y + 4, x + 1, y + 5);
+ g.drawLine(x + 14, y + 4, x + 14, y + 5);
+ g.drawLine(x + 1, y + 7, x + 1, y + 8);
+ g.drawLine(x + 14, y + 7, x + 14, y + 8);
+ g.drawLine(x + 1, y + 10, x + 1, y + 11);
+ g.drawLine(x + 14, y + 10, x + 14, y + 11);
+
+ g.drawLine(x + 2, y + 3, x + 3, y + 3);
+ g.drawLine(x + 12, y + 3, x + 13, y + 3);
+ g.drawLine(x + 2, y + 6, x + 3, y + 6);
+ g.drawLine(x + 12, y + 6, x + 13, y + 6);
+ g.drawLine(x + 2, y + 9, x + 3, y + 9);
+ g.drawLine(x + 12, y + 9, x + 13, y + 9);
+ g.drawLine(x + 2, y + 12, x + 3, y + 12);
+ g.drawLine(x + 12, y + 12, x + 13, y + 12);
+
+ g.drawLine(x + 4, y + 2, x + 11, y + 2);
+ g.drawLine(x + 4, y + 7, x + 11, y + 7);
+ g.drawLine(x + 4, y + 10, x + 11, y + 10);
+ g.drawLine(x + 4, y + 13, x + 11, y + 13);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.fillRect(x + 4, y + 3, 2, 2);
+ g.drawLine(x + 6, y + 4, x + 6, y + 4);
+ g.drawLine(x + 7, y + 3, x + 9, y + 3);
+ g.drawLine(x + 8, y + 4, x + 8, y + 4);
+ g.drawLine(x + 11, y + 3, x + 11, y + 3);
+ g.fillRect(x + 2, y + 4, 2, 2);
+ g.fillRect(x + 2, y + 7, 2, 2);
+ g.fillRect(x + 2, y + 10, 2, 2);
+ g.drawLine(x + 4, y + 6, x + 4, y + 6);
+ g.drawLine(x + 4, y + 9, x + 4, y + 9);
+ g.drawLine(x + 4, y + 12, x + 4, y + 12);
+
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x + 13, y + 4, x + 13, y + 4);
+ g.drawLine(x + 12, y + 5, x + 13, y + 5);
+ g.drawLine(x + 13, y + 7, x + 13, y + 7);
+ g.drawLine(x + 12, y + 8, x + 13, y + 8);
+ g.drawLine(x + 13, y + 10, x + 13, y + 10);
+ g.drawLine(x + 12, y + 11, x + 13, y + 11);
+
+ g.drawLine(x + 10, y + 5, x + 10, y + 5);
+ g.drawLine(x + 7, y + 6, x + 7, y + 6);
+ g.drawLine(x + 9, y + 6, x + 9, y + 6);
+ g.drawLine(x + 11, y + 6, x + 11, y + 6);
+
+ g.drawLine(x + 10, y + 8, x + 10, y + 8);
+ g.drawLine(x + 7, y + 9, x + 7, y + 9);
+ g.drawLine(x + 9, y + 9, x + 9, y + 9);
+ g.drawLine(x + 11, y + 9, x + 11, y + 9);
+
+ g.drawLine(x + 10, y + 11, x + 10, y + 11);
+ g.drawLine(x + 7, y + 12, x + 7, y + 12);
+ g.drawLine(x + 9, y + 12, x + 9, y + 12);
+ g.drawLine(x + 11, y + 12, x + 11, y + 12);
+
+ g.setColor(saved);
+ }
+ }
+
+ /**
+ * An icon representing a floppy disk.
+ *
+ * @see MetalIconFactory#getTreeFloppyDriveIcon()
+ */
+ private static class TreeFloppyDriveIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * Creates a new icon instance.
+ */
+ public TreeFloppyDriveIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location, using colors from the
+ * current theme.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 1, y + 1, x + 13, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + 14);
+ g.drawLine(x + 1, y + 14, x + 14, y + 14);
+ g.drawLine(x + 14, y + 2, x + 14, y + 14);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 2, y + 2, 12, 12);
+
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.fillRect(x + 5, y + 2, 6, 5);
+ g.drawLine(x + 4, y + 8, x + 11, y + 8);
+ g.drawLine(x + 3, y + 9, x + 3, y + 13);
+ g.drawLine(x + 12, y + 9, x + 12, y + 13);
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.fillRect(x + 8, y + 3, 2, 3);
+ g.fillRect(x + 4, y + 9, 8, 5);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ g.drawLine(x + 5, y + 10, x + 9, y + 10);
+ g.drawLine(x + 5, y + 12, x + 8, y + 12);
+
+ g.setColor(saved);
+ }
+ }
+
+ /**
+ * An icon representing a computer.
+ *
+ * @see MetalIconFactory#getTreeComputerIcon()
+ */
+ private static class TreeComputerIcon
+ implements Icon, UIResource, Serializable
+ {
+
+ /**
+ * Creates a new icon instance.
+ */
+ public TreeComputerIcon()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the width of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconWidth()
+ {
+ return 16;
+ }
+
+ /**
+ * Returns the height of the icon, in pixels.
+ *
+ * @return <code>16</code>.
+ */
+ public int getIconHeight()
+ {
+ return 16;
+ }
+
+ /**
+ * Paints the icon at the specified location, using colors from the
+ * current theme.
+ *
+ * @param c the component (ignored).
+ * @param g the graphics device.
+ * @param x the x-coordinate for the top-left of the icon.
+ * @param y the y-coordinate for the top-left of the icon.
+ */
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+
+ g.setColor(MetalLookAndFeel.getBlack());
+ g.drawLine(x + 3, y + 1, x + 12, y + 1);
+ g.drawLine(x + 2, y + 2, x + 2, y + 8);
+ g.drawLine(x + 13, y + 2, x + 13, y + 8);
+ g.drawLine(x + 3, y + 9, x + 3, y + 9);
+ g.drawLine(x + 12, y + 9, x + 12, y + 9);
+ g.drawRect(x + 1, y + 10, 13, 4);
+ g.drawLine(x + 5, y + 3, x + 10, y + 3);
+ g.drawLine(x + 5, y + 8, x + 10, y + 8);
+ g.drawLine(x + 4, y + 4, x + 4, y + 7);
+ g.drawLine(x + 11, y + 4, x + 11, y + 7);
+
+ g.setColor(MetalLookAndFeel.getPrimaryControl());
+ g.fillRect(x + 5, y + 4, 6, 4);
+
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x + 6, y + 12, x + 8, y + 12);
+ g.drawLine(x + 10, y + 12, x + 12, y + 12);
+ g.setColor(saved);
+ }
+ }
+
+ /** The icon returned by {@link #getCheckBoxIcon()}. */
+ private static Icon checkBoxIcon;
+
+ /** The icon returned by {@link #getCheckBoxMenuItemIcon()}. */
+ private static Icon checkBoxMenuItemIcon;
+
+ /** The icon returned by {@link #getFileChooserDetailViewIcon()}. */
+ private static Icon fileChooserDetailViewIcon;
+
+ /** The icon returned by {@link #getFileChooserHomeFolderIcon()}. */
+ private static Icon fileChooserHomeFolderIcon;
+
+ /** The icon returned by {@link #getFileChooserListViewIcon()}. */
+ private static Icon fileChooserListViewIcon;
+
+ /** The icon returned by {@link #getFileChooserNewFolderIcon()}. */
+ private static Icon fileChooserNewFolderIcon;
+
+ /** The icon returned by {@link #getFileChooserUpFolderIcon()}. */
+ private static Icon fileChooserUpFolderIcon;
+
+ /** The cached RadioButtonIcon instance. */
+ private static RadioButtonIcon radioButtonIcon;
+
+ /** The icon returned by {@link #getRadioButtonMenuItemIcon()}. */
+ private static Icon radioButtonMenuItemIcon;
+
+ /** The icon returned by {@link #getInternalFrameDefaultMenuIcon()}. */
+ private static Icon internalFrameDefaultMenuIcon;
+
+ /** The icon returned by {@link #getTreeComputerIcon()}. */
+ private static Icon treeComputerIcon;
+
+ /** The icon instance returned by {@link #getTreeFloppyDriveIcon()}. */
+ private static Icon treeFloppyDriveIcon;
+
+ /** The icon instance returned by {@link #getTreeHardDriveIcon()}. */
+ private static Icon treeHardDriveIcon;
+
+ /** The icon instance returned by {@link #getHorizontalSliderThumbIcon()}. */
+ private static Icon horizontalSliderThumbIcon;
+
+ /** The icon instance returned by {@link #getVerticalSliderThumbIcon()}. */
+ private static Icon verticalSliderThumbIcon;
+
+ /**
+ * Creates a new instance. All the methods are static, so creating an
+ * instance isn't necessary.
+ */
+ public MetalIconFactory()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns an icon for use when rendering the {@link JCheckBox} component.
+ *
+ * @return A check box icon.
+ *
+ * @since 1.3
+ */
+ public static Icon getCheckBoxIcon()
+ {
+ if (checkBoxIcon == null)
+ checkBoxIcon = new MetalCheckBoxIcon();
+ return checkBoxIcon;
+ }
+
+ /**
+ * Returns an icon for use when rendering the {@link JCheckBoxMenuItem}
+ * component.
+ *
+ * @return An icon.
+ */
+ public static Icon getCheckBoxMenuItemIcon()
+ {
+ if (checkBoxMenuItemIcon == null)
+ checkBoxMenuItemIcon = new CheckBoxMenuItemIcon();
+ return checkBoxMenuItemIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserDetailViewIcon()
+ {
+ if (fileChooserDetailViewIcon == null)
+ fileChooserDetailViewIcon = new FileChooserDetailViewIcon();
+ return fileChooserDetailViewIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserHomeFolderIcon()
+ {
+ if (fileChooserHomeFolderIcon == null)
+ fileChooserHomeFolderIcon = new FileChooserHomeFolderIcon();
+ return fileChooserHomeFolderIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserListViewIcon()
+ {
+ if (fileChooserListViewIcon == null)
+ fileChooserListViewIcon = new FileChooserListViewIcon();
+ return fileChooserListViewIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserNewFolderIcon()
+ {
+ if (fileChooserNewFolderIcon == null)
+ fileChooserNewFolderIcon = new FileChooserNewFolderIcon();
+ return fileChooserNewFolderIcon;
+ }
+
+ /**
+ * Returns an icon for use by the {@link JFileChooser} component.
+ *
+ * @return An icon.
+ */
+ public static Icon getFileChooserUpFolderIcon()
+ {
+ if (fileChooserUpFolderIcon == null)
+ fileChooserUpFolderIcon = new FileChooserUpFolderIcon();
+ return fileChooserUpFolderIcon;
+ }
+
+ /**
+ * Returns an icon for RadioButtons in the Metal L&amp;F.
+ *
+ * @return an icon for RadioButtons in the Metal L&amp;F
+ */
+ public static Icon getRadioButtonIcon()
+ {
+ if (radioButtonIcon == null)
+ radioButtonIcon = new RadioButtonIcon();
+ return radioButtonIcon;
+ }
+
+ /**
+ * Creates a new instance of the icon used in a {@link JRadioButtonMenuItem}.
+ *
+ * @return A new icon instance.
+ */
+ public static Icon getRadioButtonMenuItemIcon()
+ {
+ if (radioButtonMenuItemIcon == null)
+ radioButtonMenuItemIcon = new RadioButtonMenuItemIcon();
+ return radioButtonMenuItemIcon;
+ }
+
+ /**
+ * Returns the icon used to display the thumb for a horizontally oriented
+ * {@link JSlider}.
+ *
+ * @return The icon.
+ */
+ public static Icon getHorizontalSliderThumbIcon()
+ {
+ if (horizontalSliderThumbIcon == null)
+ horizontalSliderThumbIcon = new HorizontalSliderThumbIcon();
+ return horizontalSliderThumbIcon;
+ }
+
+ /**
+ * Creates a new icon used to represent the 'close' button in the title
+ * pane of a {@link JInternalFrame}.
+ *
+ * @param size the icon size.
+ *
+ * @return A close icon.
+ */
+ public static Icon getInternalFrameCloseIcon(int size)
+ {
+ return new InternalFrameCloseIcon(size);
+ }
+
+ /**
+ * Creates a new icon for the menu in a {@link JInternalFrame}. This is the
+ * icon displayed at the top left of the frame.
+ *
+ * @return A menu icon.
+ */
+ public static Icon getInternalFrameDefaultMenuIcon()
+ {
+ if (internalFrameDefaultMenuIcon == null)
+ internalFrameDefaultMenuIcon = new InternalFrameDefaultMenuIcon();
+ return internalFrameDefaultMenuIcon;
+ }
+
+ /**
+ * Creates a new icon for the 'maximize' button in a {@link JInternalFrame}.
+ *
+ * @param size the icon size in pixels.
+ *
+ * @return The icon.
+ *
+ * @see #getInternalFrameAltMaximizeIcon(int)
+ */
+ public static Icon getInternalFrameMaximizeIcon(int size)
+ {
+ return new InternalFrameMaximizeIcon();
+ }
+
+ /**
+ * Returns the icon used for the minimize button in the frame title for a
+ * {@link JInternalFrame}.
+ *
+ * @param size the icon size in pixels (ignored by this implementation).
+ *
+ * @return The icon.
+ */
+ public static Icon getInternalFrameMinimizeIcon(int size)
+ {
+ return new InternalFrameMinimizeIcon();
+ }
+
+ /**
+ * Creates a new icon for the 'restore' button in a {@link JInternalFrame}
+ * that has been maximised.
+ *
+ * @param size the icon size in pixels.
+ *
+ * @return The icon.
+ *
+ * @see #getInternalFrameMaximizeIcon(int)
+ */
+ public static Icon getInternalFrameAltMaximizeIcon(int size)
+ {
+ return new InternalFrameAltMaximizeIcon(size);
+ }
+
+ /**
+ * Returns the icon used to display the thumb for a vertically oriented
+ * {@link JSlider}.
+ *
+ * @return The icon.
+ */
+ public static Icon getVerticalSliderThumbIcon()
+ {
+ if (verticalSliderThumbIcon == null)
+ verticalSliderThumbIcon = new VerticalSliderThumbIcon();
+ return verticalSliderThumbIcon;
+ }
+
+ /**
+ * Creates and returns a new tree folder icon.
+ *
+ * @return A new tree folder icon.
+ */
+ public static Icon getTreeFolderIcon()
+ {
+ return new TreeFolderIcon();
+ }
+
+ /**
+ * Creates and returns a new tree leaf icon.
+ *
+ * @return A new tree leaf icon.
+ */
+ public static Icon getTreeLeafIcon()
+ {
+ return new TreeLeafIcon();
+ }
+
+ /**
+ * Creates and returns a tree control icon.
+ *
+ * @param isCollapsed a flag that controls whether the icon is in the
+ * collapsed or expanded state.
+ *
+ * @return A tree control icon.
+ */
+ public static Icon getTreeControlIcon(boolean isCollapsed)
+ {
+ return new TreeControlIcon(isCollapsed);
+ }
+
+ /**
+ * Returns a <code>16x16</code> icon representing a computer.
+ *
+ * @return The icon.
+ */
+ public static Icon getTreeComputerIcon()
+ {
+ if (treeComputerIcon == null)
+ treeComputerIcon = new TreeComputerIcon();
+ return treeComputerIcon;
+ }
+
+ /**
+ * Returns a <code>16x16</code> icon representing a floppy disk.
+ *
+ * @return The icon.
+ */
+ public static Icon getTreeFloppyDriveIcon()
+ {
+ if (treeFloppyDriveIcon == null)
+ treeFloppyDriveIcon = new TreeFloppyDriveIcon();
+ return treeFloppyDriveIcon;
+ }
+
+ /**
+ * Returns a <code>16x16</code> icon representing a hard disk.
+ *
+ * @return The icon.
+ */
+ public static Icon getTreeHardDriveIcon()
+ {
+ if (treeHardDriveIcon == null)
+ treeHardDriveIcon = new TreeHardDriveIcon();
+ return treeHardDriveIcon;
+ }
+
+ /**
+ * Returns a new instance of a 4 x 8 icon showing a small black triangle that
+ * points to the right. This is displayed in menu items that have a
+ * sub menu.
+ *
+ * @return The icon.
+ */
+ public static Icon getMenuArrowIcon()
+ {
+ if (menuArrow == null)
+ menuArrow = new Icon()
+ {
+ public int getIconHeight()
+ {
+ return 8;
+ }
+
+ public int getIconWidth()
+ {
+ return 4;
+ }
+
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+ g.setColor(Color.BLACK);
+ for (int i = 0; i < 4; i++)
+ g.drawLine(x + i, y + i, x + i, y + 7 - i);
+ g.setColor(saved);
+ }
+ };
+ return menuArrow;
+ }
+
+ /**
+ * Returns a new instance of a 4 x 8 icon showing a small black triangle that
+ * points to the right. This is displayed in menu items that have a sub menu.
+ *
+ * @return The icon.
+ */
+ public static Icon getMenuItemArrowIcon()
+ {
+ if (menuItemArrow == null)
+ menuItemArrow = new Icon()
+ {
+ public int getIconHeight()
+ {
+ return 8;
+ }
+
+ public int getIconWidth()
+ {
+ return 4;
+ }
+
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+ g.setColor(Color.BLACK);
+ for (int i = 0; i < 4; i++)
+ g.drawLine(x + i, y + i, x + i, y + 7 - i);
+ g.setColor(saved);
+ }
+ };
+ return menuItemArrow;
+ }
+
+ /**
+ * Returns a new instance of a 13 x 13 icon showing a small black check mark.
+ *
+ * @return The icon.
+ */
+ public static Icon getMenuItemCheckIcon()
+ {
+ return new Icon()
+ {
+ public int getIconHeight()
+ {
+ return 13;
+ }
+
+ public int getIconWidth()
+ {
+ return 13;
+ }
+
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ Color saved = g.getColor();
+ g.setColor(Color.BLACK);
+ g.drawLine(3 + x, 5 + y, 3 + x, 9 + y);
+ g.drawLine(4 + x, 5 + y, 4 + x, 9 + y);
+ g.drawLine(5 + x, 7 + y, 9 + x, 3 + y);
+ g.drawLine(5 + x, 8 + y, 9 + x, 4 + y);
+ g.setColor(saved);
+ }
+ };
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java
new file mode 100644
index 000000000..08de77446
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java
@@ -0,0 +1,457 @@
+/* MetalInternalFrameTitlePane.java
+ Copyright (C) 2005 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.Graphics;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.Rectangle;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.Icon;
+import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
+
+
+/**
+ * The title pane for a {@link JInternalFrame} (see
+ * {@link MetalInternalFrameUI#createNorthPane(JInternalFrame)}). This can
+ * be displayed in two styles: one for regular internal frames, and the other
+ * for "palette" style internal frames.
+ */
+public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane
+{
+
+ /**
+ * A property change handler that listens for changes to the
+ * <code>JInternalFrame.isPalette</code> property and updates the title
+ * pane as appropriate.
+ */
+ class MetalInternalFrameTitlePanePropertyChangeHandler
+ extends PropertyChangeHandler
+ {
+ /**
+ * Creates a new handler.
+ */
+ public MetalInternalFrameTitlePanePropertyChangeHandler()
+ {
+ super();
+ }
+
+ /**
+ * Handles <code>JInternalFrame.isPalette</code> property changes, with all
+ * other property changes being passed to the superclass.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ String propName = e.getPropertyName();
+ if (e.getPropertyName().equals(JInternalFrame.FRAME_ICON_PROPERTY))
+ {
+ title.setIcon(frame.getFrameIcon());
+ }
+ else if (propName.equals("JInternalFrame.isPalette"))
+ {
+ if (e.getNewValue().equals(Boolean.TRUE))
+ setPalette(true);
+ else
+ setPalette(false);
+ }
+ else
+ super.propertyChange(e);
+ }
+ }
+
+ /**
+ * A layout manager for the title pane.
+ *
+ * @see #createLayout()
+ */
+ 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)
+ {
+ if (isPalette)
+ return new Dimension(paletteTitleHeight, paletteTitleHeight);
+ else
+ 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.
+ }
+ }
+
+ /** A flag indicating whether the title pane uses the palette style. */
+ protected boolean isPalette;
+
+ /**
+ * The icon used for the close button - this is fetched from the look and
+ * feel defaults using the key <code>InternalFrame.paletteCloseIcon</code>.
+ */
+ protected Icon paletteCloseIcon;
+
+ /**
+ * The height of the title pane when <code>isPalette</code> is
+ * <code>true</code>. This value is fetched from the look and feel defaults
+ * using the key <code>InternalFrame.paletteTitleHeight</code>.
+ */
+ protected int paletteTitleHeight;
+
+ /** The label used to display the title for the internal frame. */
+ JLabel title;
+
+ /**
+ * Creates a new title pane for the specified frame.
+ *
+ * @param f the internal frame.
+ */
+ public MetalInternalFrameTitlePane(JInternalFrame f)
+ {
+ super(f);
+ isPalette = false;
+ }
+
+ /**
+ * Fetches the colors used in the title pane.
+ */
+ protected void installDefaults()
+ {
+ super.installDefaults();
+ selectedTextColor = MetalLookAndFeel.getControlTextColor();
+ selectedTitleColor = MetalLookAndFeel.getWindowTitleBackground();
+ notSelectedTextColor = MetalLookAndFeel.getInactiveControlTextColor();
+ notSelectedTitleColor = MetalLookAndFeel.getWindowTitleInactiveBackground();
+
+ paletteTitleHeight = UIManager.getInt("InternalFrame.paletteTitleHeight");
+ paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon");
+ minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16);
+
+ title = new JLabel(frame.getTitle(),
+ MetalIconFactory.getInternalFrameDefaultMenuIcon(),
+ SwingConstants.LEFT);
+ }
+
+ /**
+ * Clears the colors used for the title pane.
+ */
+ protected void uninstallDefaults()
+ {
+ super.uninstallDefaults();
+ selectedTextColor = null;
+ selectedTitleColor = null;
+ notSelectedTextColor = null;
+ notSelectedTitleColor = null;
+ paletteCloseIcon = null;
+ minIcon = null;
+ title = null;
+ }
+
+ /**
+ * Calls the super class to create the buttons, then calls
+ * <code>setBorderPainted(false)</code> and
+ * <code>setContentAreaFilled(false)</code> for each button.
+ */
+ protected void createButtons()
+ {
+ super.createButtons();
+ closeButton.setBorderPainted(false);
+ closeButton.setContentAreaFilled(false);
+ iconButton.setBorderPainted(false);
+ iconButton.setContentAreaFilled(false);
+ maxButton.setBorderPainted(false);
+ maxButton.setContentAreaFilled(false);
+ }
+
+ /**
+ * Overridden to do nothing.
+ */
+ protected void addSystemMenuItems(JMenu systemMenu)
+ {
+ // do nothing
+ }
+
+ /**
+ * Overridden to do nothing.
+ */
+ protected void showSystemMenu()
+ {
+ // do nothing
+ }
+
+ /**
+ * Adds the sub components of the title pane.
+ */
+ protected void addSubComponents()
+ {
+ // FIXME: this method is probably overridden to only add the required
+ // buttons
+ add(title);
+ add(closeButton);
+ add(iconButton);
+ add(maxButton);
+ }
+
+ /**
+ * Creates a new instance of <code>MetalTitlePaneLayout</code> (not part of
+ * the public API).
+ *
+ * @return A new instance of <code>MetalTitlePaneLayout</code>.
+ */
+ protected LayoutManager createLayout()
+ {
+ return new MetalTitlePaneLayout();
+ }
+
+ /**
+ * Draws the title pane in the palette style.
+ *
+ * @param g the graphics device.
+ *
+ * @see #paintComponent(Graphics)
+ */
+ public void paintPalette(Graphics g)
+ {
+ Color savedColor = g.getColor();
+ Rectangle b = SwingUtilities.getLocalBounds(this);
+
+ if (UIManager.get("InternalFrame.activeTitleGradient") != null
+ && frame.isSelected())
+ {
+ MetalUtils.paintGradient(g, b.x, b.y, b.width, b.height,
+ SwingConstants.VERTICAL,
+ "InternalFrame.activeTitleGradient");
+ }
+ MetalUtils.fillMetalPattern(this, g, b.x + 4, b.y + 2, b.width
+ - paletteCloseIcon.getIconWidth() - 13, b.height - 5,
+ MetalLookAndFeel.getPrimaryControlHighlight(),
+ MetalLookAndFeel.getBlack());
+
+ // draw a line separating the title pane from the frame content
+ Dimension d = getSize();
+ g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
+ g.drawLine(0, d.height - 1, d.width - 1, d.height - 1);
+
+ g.setColor(savedColor);
+ }
+
+ /**
+ * Paints a representation of the current state of the internal frame.
+ *
+ * @param g the graphics device.
+ */
+ public void paintComponent(Graphics g)
+ {
+ Color savedColor = g.getColor();
+ if (isPalette)
+ paintPalette(g);
+ else
+ {
+ paintTitleBackground(g);
+ paintChildren(g);
+ Dimension d = getSize();
+ if (frame.isSelected())
+ 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.isSelected())
+ {
+ 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);
+ }
+
+ /**
+ * Sets the flag that controls whether the title pane is drawn in the
+ * palette style or the regular style.
+ *
+ * @param b the new value of the flag.
+ */
+ public void setPalette(boolean b)
+ {
+ isPalette = b;
+ title.setVisible(!isPalette);
+ iconButton.setVisible(!isPalette && frame.isIconifiable());
+ maxButton.setVisible(!isPalette && frame.isMaximizable());
+ if (isPalette)
+ closeButton.setIcon(paletteCloseIcon);
+ else
+ closeButton.setIcon(closeIcon);
+ }
+
+ /**
+ * Creates and returns a property change handler for the title pane.
+ *
+ * @return The property change handler.
+ */
+ protected PropertyChangeListener createPropertyChangeListener()
+ {
+ return new MetalInternalFrameTitlePanePropertyChangeHandler();
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java
new file mode 100644
index 000000000..5eda2ff5e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java
@@ -0,0 +1,183 @@
+/* MetalInternalFrameUI.java
+ Copyright (C) 2005 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.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.ActionMap;
+import javax.swing.JComponent;
+import javax.swing.JInternalFrame;
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicInternalFrameUI;
+
+/**
+ * A UI delegate for the {@link JInternalFrame} component.
+ */
+public class MetalInternalFrameUI
+ extends BasicInternalFrameUI
+{
+ /**
+ * The key (<code>JInternalFrame.isPalette</code>) for the client property
+ * that controls whether the internal frame is displayed using the palette
+ * style.
+ */
+ protected static String IS_PALETTE = "JInternalFrame.isPalette";
+
+ /**
+ * Constructs a new instance of <code>MetalInternalFrameUI</code>.
+ *
+ * @param frame the frame.
+ */
+ public MetalInternalFrameUI(JInternalFrame frame)
+ {
+ super(frame);
+ }
+
+ /**
+ * Returns an instance of <code>MetalInternalFrameUI</code>.
+ *
+ * @param component the internal frame.
+ *
+ * @return an instance of <code>MetalInternalFrameUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalInternalFrameUI((JInternalFrame) component);
+ }
+
+ /**
+ * Sets the fields and properties for the component.
+ *
+ * @param c the component.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ JInternalFrame f = (JInternalFrame) c;
+ boolean isPalette = false;
+ Boolean p = (Boolean) f.getClientProperty(IS_PALETTE);
+ if (p != null)
+ isPalette = p.booleanValue();
+ setPalette(isPalette);
+ }
+
+ /**
+ * Creates and returns the component that will be used for the north pane
+ * of the {@link JInternalFrame}.
+ *
+ * @param w the internal frame.
+ *
+ * @return A new instance of {@link MetalInternalFrameTitlePane}.
+ */
+ protected JComponent createNorthPane(JInternalFrame w)
+ {
+ titlePane = new MetalInternalFrameTitlePane(w);
+ return titlePane;
+ }
+
+ /**
+ * Sets the state of the {@link JInternalFrame} to reflect whether or not
+ * it is using the palette style. When a frame is displayed as a palette,
+ * it uses a different border and the title pane is drawn differently.
+ *
+ * @param isPalette use the palette style?
+ */
+ public void setPalette(boolean isPalette)
+ {
+ MetalInternalFrameTitlePane title = (MetalInternalFrameTitlePane) northPane;
+ title.setPalette(isPalette);
+ if (isPalette)
+ frame.setBorder(new MetalBorders.PaletteBorder());
+ else
+ frame.setBorder(new MetalBorders.InternalFrameBorder());
+ }
+
+ /** A listener that is used to handle IS_PALETTE property changes. */
+ private PropertyChangeListener paletteListener;
+
+ /**
+ * Adds the required listeners.
+ */
+ protected void installListeners()
+ {
+ super.installListeners();
+ paletteListener = new PropertyChangeListener()
+ {
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(IS_PALETTE))
+ {
+ if (Boolean.TRUE.equals(e.getNewValue()))
+ setPalette(true);
+ else
+ setPalette(false);
+ }
+ }
+ };
+ frame.addPropertyChangeListener(paletteListener);
+ }
+
+ /**
+ * Removes the listeners used.
+ */
+ protected void uninstallListeners()
+ {
+ super.uninstallListeners();
+ frame.removePropertyChangeListener(IS_PALETTE, paletteListener);
+ paletteListener = null;
+ }
+
+ /**
+ * Installs keyboard actions. This is overridden to remove the
+ * <code>showSystemMenu</code> Action that is installed by the
+ * <code>BasicInternalFrameUI</code>, since Metal JInternalFrames don't have
+ * a system menu.
+ */
+ protected void installKeyboardActions()
+ {
+ super.installKeyboardActions();
+ ActionMap am = SwingUtilities.getUIActionMap(frame);
+ if (am != null)
+ {
+ am.remove("showSystemMenu");
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java
new file mode 100644
index 000000000..915e5016d
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java
@@ -0,0 +1,108 @@
+/* MetalLabelUI.java
+ Copyright (C) 2005 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.Graphics;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicGraphicsUtils;
+import javax.swing.plaf.basic.BasicLabelUI;
+
+/**
+ * A UI delegate for the {@link JLabel} component.
+ */
+public class MetalLabelUI
+ extends BasicLabelUI
+{
+
+ /** The shared instance of the UI delegate. */
+ protected static MetalLabelUI metalLabelUI;
+
+ /**
+ * Constructs a new instance of <code>MetalLabelUI</code>.
+ */
+ public MetalLabelUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a shared instance of <code>MetalLabelUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A shared instance of <code>MetalLabelUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ if (metalLabelUI == null)
+ metalLabelUI = new MetalLabelUI();
+ return metalLabelUI;
+ }
+
+ /**
+ * Draws the text for a disabled label, using the color defined in the
+ * {@link UIManager} defaults with the key
+ * <code>Label.disabledForeground</code>.
+ *
+ * @param l the label.
+ * @param g the graphics device.
+ * @param s the label text.
+ * @param textX the x-coordinate for the label.
+ * @param textY the y-coordinate for the label.
+ */
+ protected void paintDisabledText(JLabel l, Graphics g, String s, int textX,
+ int textY)
+ {
+ Color savedColor = g.getColor();
+ g.setColor(UIManager.getColor("Label.disabledForeground"));
+ int mnemIndex = l.getDisplayedMnemonicIndex();
+ if (mnemIndex != -1)
+ BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX,
+ textY);
+ else
+ g.drawString(s, textX, textY);
+
+ g.setColor(savedColor);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java
new file mode 100644
index 000000000..acc3fedde
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java
@@ -0,0 +1,1372 @@
+/* MetalLookAndFeel.java
+ Copyright (C) 2002, 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 gnu.classpath.SystemProperties;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import javax.swing.LookAndFeel;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.plaf.BorderUIResource;
+import javax.swing.plaf.ColorUIResource;
+import javax.swing.plaf.FontUIResource;
+import javax.swing.plaf.InsetsUIResource;
+import javax.swing.plaf.BorderUIResource.LineBorderUIResource;
+import javax.swing.plaf.basic.BasicLookAndFeel;
+
+
+/**
+ * A custom look and feel that is designed to look similar across different
+ * operating systems. To install this look and feel, add the following code
+ * (or something similar) near the start of your application:</p>
+ * <pre>
+ * try
+ * {
+ * &nbsp;&nbsp;UIManager.setLookAndFeel(new MetalLookAndFeel());
+ * }
+ * catch (UnsupportedLookAndFeelException e)
+ * {
+ * &nbsp;&nbsp;e.printStackTrace();
+ * }</pre>
+ */
+public class MetalLookAndFeel extends BasicLookAndFeel
+{
+ private static final long serialVersionUID = 6680646159193457980L;
+
+ /** The current theme. */
+ private static MetalTheme theme;
+
+ /**
+ * Creates a new instance of the Metal look and feel.
+ */
+ public MetalLookAndFeel()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the current theme to a new instance of {@link DefaultMetalTheme}.
+ */
+ protected void createDefaultTheme()
+ {
+ getCurrentTheme();
+ }
+
+ /**
+ * Returns <code>false</code> to indicate that this look and feel does not
+ * attempt to emulate the look and feel of native applications on the host
+ * platform.
+ *
+ * @return <code>false</code>.
+ */
+ public boolean isNativeLookAndFeel()
+ {
+ return false;
+ }
+
+ /**
+ * Returns <code>true</code> to indicate that this look and feel is supported
+ * on all platforms.
+ *
+ * @return <code>true</code>.
+ */
+ public boolean isSupportedLookAndFeel()
+ {
+ return true;
+ }
+
+ /**
+ * Returns a string describing the look and feel. In this case, the method
+ * returns "Metal look and feel".
+ *
+ * @return A string describing the look and feel.
+ */
+ public String getDescription()
+ {
+ return "The Java(tm) Look and Feel";
+ }
+
+ /**
+ * Returns the look and feel identifier.
+ *
+ * @return "MetalLookAndFeel".
+ */
+ public String getID()
+ {
+ return "Metal";
+ }
+
+ /**
+ * Returns the look and feel name.
+ *
+ * @return "MetalLookAndFeel".
+ */
+ public String getName()
+ {
+ return "Metal";
+ }
+
+ public UIDefaults getDefaults()
+ {
+ createDefaultTheme();
+ UIDefaults def = super.getDefaults();
+
+ theme.addCustomEntriesToTable(def);
+ return def;
+ }
+
+ /**
+ * Returns the accelerator foreground color from the installed theme.
+ *
+ * @return The accelerator foreground color.
+ */
+ public static ColorUIResource getAcceleratorForeground()
+ {
+ if (theme != null)
+ return theme.getAcceleratorForeground();
+ return null;
+ }
+
+ /**
+ * Returns the accelerator selected foreground color from the installed
+ * theme.
+ *
+ * @return The accelerator selected foreground color.
+ */
+ public static ColorUIResource getAcceleratorSelectedForeground()
+ {
+ if (theme != null)
+ return theme.getAcceleratorSelectedForeground();
+ return null;
+ }
+
+ /**
+ * Returns the color black from the installed theme.
+ *
+ * @return The color black.
+ */
+ public static ColorUIResource getBlack()
+ {
+ if (theme != null)
+ return theme.getBlack();
+ return null;
+ }
+
+ /**
+ * Returns the control color from the installed theme.
+ *
+ * @return The control color.
+ */
+ public static ColorUIResource getControl()
+ {
+ if (theme != null)
+ return theme.getControl();
+ return null;
+ }
+
+ /**
+ * Returns the color used for dark shadows on controls, from the installed
+ * theme.
+ *
+ * @return The color used for dark shadows on controls.
+ */
+ public static ColorUIResource getControlDarkShadow()
+ {
+ if (theme != null)
+ return theme.getControlDarkShadow();
+ return null;
+ }
+
+ /**
+ * Returns the color used for disabled controls, from the installed theme.
+ *
+ * @return The color used for disabled controls.
+ */
+ public static ColorUIResource getControlDisabled()
+ {
+ if (theme != null)
+ return theme.getControlDisabled();
+ return null;
+ }
+
+ /**
+ * Returns the color used to draw highlights for controls, from the installed
+ * theme.
+ *
+ * @return The color used to draw highlights for controls.
+ */
+ public static ColorUIResource getControlHighlight()
+ {
+ if (theme != null)
+ return theme.getControlHighlight();
+ return null;
+ }
+
+ /**
+ * Returns the color used to display control info, from the installed
+ * theme.
+ *
+ * @return The color used to display control info.
+ */
+ public static ColorUIResource getControlInfo()
+ {
+ if (theme != null)
+ return theme.getControlInfo();
+ return null;
+ }
+
+ /**
+ * Returns the color used to draw shadows for controls, from the installed
+ * theme.
+ *
+ * @return The color used to draw shadows for controls.
+ */
+ public static ColorUIResource getControlShadow()
+ {
+ if (theme != null)
+ return theme.getControlShadow();
+ return null;
+ }
+
+ /**
+ * Returns the color used for text on controls, from the installed theme.
+ *
+ * @return The color used for text on controls.
+ */
+ public static ColorUIResource getControlTextColor()
+ {
+ if (theme != null)
+ return theme.getControlTextColor();
+ return null;
+ }
+
+ /**
+ * Returns the font used for text on controls, from the installed theme.
+ *
+ * @return The font used for text on controls.
+ */
+ public static FontUIResource getControlTextFont()
+ {
+ if (theme != null)
+ return theme.getControlTextFont();
+ return null;
+ }
+
+ /**
+ * Returns the color used for the desktop background, from the installed
+ * theme.
+ *
+ * @return The color used for the desktop background.
+ */
+ public static ColorUIResource getDesktopColor()
+ {
+ if (theme != null)
+ return theme.getDesktopColor();
+ return null;
+ }
+
+ /**
+ * Returns the color used to draw focus highlights, from the installed
+ * theme.
+ *
+ * @return The color used to draw focus highlights.
+ */
+ public static ColorUIResource getFocusColor()
+ {
+ if (theme != null)
+ return theme.getFocusColor();
+ return null;
+ }
+
+ /**
+ * Returns the color used to draw highlighted text, from the installed
+ * theme.
+ *
+ * @return The color used to draw highlighted text.
+ */
+ public static ColorUIResource getHighlightedTextColor()
+ {
+ if (theme != null)
+ return theme.getHighlightedTextColor();
+ return null;
+ }
+
+ /**
+ * Returns the color used to draw text on inactive controls, from the
+ * installed theme.
+ *
+ * @return The color used to draw text on inactive controls.
+ */
+ public static ColorUIResource getInactiveControlTextColor()
+ {
+ if (theme != null)
+ return theme.getInactiveControlTextColor();
+ return null;
+ }
+
+ /**
+ * Returns the color used to draw inactive system text, from the installed
+ * theme.
+ *
+ * @return The color used to draw inactive system text.
+ */
+ public static ColorUIResource getInactiveSystemTextColor()
+ {
+ if (theme != null)
+ return theme.getInactiveSystemTextColor();
+ return null;
+ }
+
+ /**
+ * Returns the background color for menu items, from the installed theme.
+ *
+ * @return The background color for menu items.
+ *
+ * @see #getMenuSelectedBackground()
+ */
+ public static ColorUIResource getMenuBackground()
+ {
+ if (theme != null)
+ return theme.getMenuBackground();
+ return null;
+ }
+
+ /**
+ * Returns the foreground color for disabled menu items, from the installed
+ * theme.
+ *
+ * @return The foreground color for disabled menu items.
+ *
+ * @see #getMenuForeground()
+ */
+ public static ColorUIResource getMenuDisabledForeground()
+ {
+ if (theme != null)
+ return theme.getMenuDisabledForeground();
+ return null;
+ }
+
+ /**
+ * Returns the foreground color for menu items, from the installed theme.
+ *
+ * @return The foreground color for menu items.
+ *
+ * @see #getMenuDisabledForeground()
+ * @see #getMenuSelectedForeground()
+ */
+ public static ColorUIResource getMenuForeground()
+ {
+ if (theme != null)
+ return theme.getMenuForeground();
+ return null;
+ }
+
+ /**
+ * Returns the background color for selected menu items, from the installed
+ * theme.
+ *
+ * @return The background color for selected menu items.
+ *
+ * @see #getMenuBackground()
+ */
+ public static ColorUIResource getMenuSelectedBackground()
+ {
+ if (theme != null)
+ return theme.getMenuSelectedBackground();
+ return null;
+ }
+
+ /**
+ * Returns the foreground color for selected menu items, from the installed
+ * theme.
+ *
+ * @return The foreground color for selected menu items.
+ *
+ * @see #getMenuForeground()
+ */
+ public static ColorUIResource getMenuSelectedForeground()
+ {
+ if (theme != null)
+ return theme.getMenuSelectedForeground();
+ return null;
+ }
+
+ /**
+ * Returns the font used for text in menus, from the installed theme.
+ *
+ * @return The font used for text in menus.
+ */
+ public static FontUIResource getMenuTextFont()
+ {
+ if (theme != null)
+ return theme.getMenuTextFont();
+ return null;
+ }
+
+ /**
+ * Returns the primary color for controls, from the installed theme.
+ *
+ * @return The primary color for controls.
+ */
+ public static ColorUIResource getPrimaryControl()
+ {
+ if (theme != null)
+ return theme.getPrimaryControl();
+ return null;
+ }
+
+ /**
+ * Returns the primary color for the dark shadow on controls, from the
+ * installed theme.
+ *
+ * @return The primary color for the dark shadow on controls.
+ */
+ public static ColorUIResource getPrimaryControlDarkShadow()
+ {
+ if (theme != null)
+ return theme.getPrimaryControlDarkShadow();
+ return null;
+ }
+
+ /**
+ * Returns the primary color for the highlight on controls, from the
+ * installed theme.
+ *
+ * @return The primary color for the highlight on controls.
+ */
+ public static ColorUIResource getPrimaryControlHighlight()
+ {
+ if (theme != null)
+ return theme.getPrimaryControlHighlight();
+ return null;
+ }
+
+ /**
+ * Returns the primary color for the information on controls, from the
+ * installed theme.
+ *
+ * @return The primary color for the information on controls.
+ */
+ public static ColorUIResource getPrimaryControlInfo()
+ {
+ if (theme != null)
+ return theme.getPrimaryControlInfo();
+ return null;
+ }
+
+ /**
+ * Returns the primary color for the shadow on controls, from the installed
+ * theme.
+ *
+ * @return The primary color for the shadow on controls.
+ */
+ public static ColorUIResource getPrimaryControlShadow()
+ {
+ if (theme != null)
+ return theme.getPrimaryControlShadow();
+ return null;
+ }
+
+ /**
+ * Returns the background color for separators, from the installed theme.
+ *
+ * @return The background color for separators.
+ */
+ public static ColorUIResource getSeparatorBackground()
+ {
+ if (theme != null)
+ return theme.getSeparatorBackground();
+ return null;
+ }
+
+ /**
+ * Returns the foreground color for separators, from the installed theme.
+ *
+ * @return The foreground color for separators.
+ */
+ public static ColorUIResource getSeparatorForeground()
+ {
+ if (theme != null)
+ return theme.getSeparatorForeground();
+ return null;
+ }
+
+ /**
+ * Returns the font used for sub text, from the installed theme.
+ *
+ * @return The font used for sub text.
+ */
+ public static FontUIResource getSubTextFont()
+ {
+ if (theme != null)
+ return theme.getSubTextFont();
+ return null;
+ }
+
+ /**
+ * Returns the color used for system text, from the installed theme.
+ *
+ * @return The color used for system text.
+ */
+ public static ColorUIResource getSystemTextColor()
+ {
+ if (theme != null)
+ return theme.getSystemTextColor();
+ return null;
+ }
+
+ /**
+ * Returns the font used for system text, from the installed theme.
+ *
+ * @return The font used for system text.
+ */
+ public static FontUIResource getSystemTextFont()
+ {
+ if (theme != null)
+ return theme.getSystemTextFont();
+ return null;
+ }
+
+ /**
+ * Returns the color used to highlight text, from the installed theme.
+ *
+ * @return The color used to highlight text.
+ */
+ public static ColorUIResource getTextHighlightColor()
+ {
+ if (theme != null)
+ return theme.getTextHighlightColor();
+ return null;
+ }
+
+ /**
+ * Returns the color used to display user text, from the installed theme.
+ *
+ * @return The color used to display user text.
+ */
+ public static ColorUIResource getUserTextColor()
+ {
+ if (theme != null)
+ return theme.getUserTextColor();
+ return null;
+ }
+
+ /**
+ * Returns the font used for user text, obtained from the current theme.
+ *
+ * @return The font used for user text.
+ */
+ public static FontUIResource getUserTextFont()
+ {
+ if (theme != null)
+ return theme.getUserTextFont();
+ return null;
+ }
+
+ /**
+ * Returns the color used for white, from the installed theme.
+ *
+ * @return The color used for white.
+ */
+ public static ColorUIResource getWhite()
+ {
+ if (theme != null)
+ return theme.getWhite();
+ return null;
+ }
+
+ /**
+ * Returns the window background color, from the installed theme.
+ *
+ * @return The window background color.
+ */
+ public static ColorUIResource getWindowBackground()
+ {
+ if (theme != null)
+ return theme.getWindowBackground();
+ return null;
+ }
+
+ /**
+ * Returns the window title background color, from the installed theme.
+ *
+ * @return The window title background color.
+ */
+ public static ColorUIResource getWindowTitleBackground()
+ {
+ if (theme != null)
+ return theme.getWindowTitleBackground();
+ return null;
+ }
+
+ /**
+ * Returns the window title font from the current theme.
+ *
+ * @return The window title font.
+ *
+ * @see MetalTheme
+ */
+ public static FontUIResource getWindowTitleFont()
+ {
+ if (theme != null)
+ return theme.getWindowTitleFont();
+ return null;
+ }
+
+ /**
+ * Returns the window title foreground color, from the installed theme.
+ *
+ * @return The window title foreground color.
+ */
+ public static ColorUIResource getWindowTitleForeground()
+ {
+ if (theme != null)
+ return theme.getWindowTitleForeground();
+ return null;
+ }
+
+ /**
+ * Returns the background color for an inactive window title, from the
+ * installed theme.
+ *
+ * @return The background color for an inactive window title.
+ */
+ public static ColorUIResource getWindowTitleInactiveBackground()
+ {
+ if (theme != null)
+ return theme.getWindowTitleInactiveBackground();
+ return null;
+ }
+
+ /**
+ * Returns the foreground color for an inactive window title, from the
+ * installed theme.
+ *
+ * @return The foreground color for an inactive window title.
+ */
+ public static ColorUIResource getWindowTitleInactiveForeground()
+ {
+ if (theme != null)
+ return theme.getWindowTitleInactiveForeground();
+ return null;
+ }
+
+ /**
+ * Sets the current theme for the look and feel. Note that the theme must be
+ * set <em>before</em> the look and feel is installed. To change the theme
+ * for an already running application that is using the
+ * {@link MetalLookAndFeel}, first set the theme with this method, then
+ * create a new instance of {@link MetalLookAndFeel} and install it in the
+ * usual way (see {@link UIManager#setLookAndFeel(LookAndFeel)}).
+ *
+ * @param theme the theme (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>theme</code> is <code>null</code>.
+ *
+ * @see #getCurrentTheme()
+ */
+ public static void setCurrentTheme(MetalTheme theme)
+ {
+ if (theme == null)
+ throw new NullPointerException("Null 'theme' not permitted.");
+ MetalLookAndFeel.theme = theme;
+ }
+
+ /**
+ * Sets the ComponentUI classes for all Swing components to the Metal
+ * implementations.
+ *
+ * In particular this sets the following keys:
+ *
+ * <table>
+ * <tr>
+ * <th>Key</th><th>Value</th>
+ * </tr><tr>
+ * <td>ButtonUI</td><td>{@link MetalButtonUI}</td>
+ * </tr><tr>
+ * <td>CheckBoxUI</td><td>{@link MetalCheckBoxUI}</td>
+ * </tr><tr>
+ * <td>ComboBoxUI</td><td>{@link MetalComboBoxUI}</td>
+ * </tr><tr>
+ * <td>DesktopIconUI</td><td>{@link MetalDesktopIconUI}</td>
+ * </tr><tr>
+ * <td>InternalFrameUI</td><td>{@link MetalInternalFrameUI}</td>
+ * </tr><tr>
+ * <td>LabelUI</td><td>{@link MetalLabelUI}</td>
+ * </tr><tr>
+ * <td>PopupMenuSeparatorUI</td><td>{@link MetalPopupMenuSeparatorUI}</td>
+ * </tr><tr>
+ * <td>ProgressBarUI</td><td>{@link MetalProgressBarUI}</td>
+ * </tr><tr>
+ * <td>RadioButtonUI</td><td>{@link MetalRadioButtonUI}</td>
+ * </tr><tr>
+ * <td>RootPaneUI</td><td>{@link MetalRootPaneUI}</td>
+ * </tr><tr>
+ * <td>ScrollBarUI</td><td>{@link MetalScrollBarUI}</td>
+ * </tr><tr>
+ * <td>ScrollPaneUI</td><td>{@link MetalScrollPaneUI}</td>
+ * </tr><tr>
+ * <td>SeparatorUI</td><td>{@link MetalSeparatorUI}</td>
+ * </tr><tr>
+ * <td>SliderUI</td><td>{@link MetalSliderUI}</td>
+ * </tr><tr>
+ * <td>SplitPaneUI</td><td>{@link MetalSplitPaneUI}</td>
+ * </tr><tr>
+ * <td>TabbedPaneUI</td><td>{@link MetalTabbedPaneUI}</td>
+ * </tr><tr>
+ * <td>TextFieldUI</td><td>{@link MetalTextFieldUI}</td>
+ * </tr><tr>
+ * <td>ToggleButtonUI</td><td>{@link MetalToggleButtonUI}</td>
+ * </tr><tr>
+ * <td>ToolBarUI</td><td>{@link MetalToolBarUI}</td>
+ * </tr><tr>
+ * <td>ToolTipUI</td><td>{@link MetalToolTipUI}</td>
+ * </tr><tr>
+ * <td>TreeUI</td><td>{@link MetalTreeUI}</td>
+ * </tr><tr>
+ * </table>
+ *
+ * @param defaults the UIDefaults where the class defaults are added
+ */
+ protected void initClassDefaults(UIDefaults defaults)
+ {
+ super.initClassDefaults(defaults);
+
+ // Variables
+ Object[] uiDefaults;
+ // Initialize Class Defaults
+ uiDefaults = new Object[] {
+ "ButtonUI", "javax.swing.plaf.metal.MetalButtonUI",
+ "CheckBoxUI", "javax.swing.plaf.metal.MetalCheckBoxUI",
+ "ComboBoxUI", "javax.swing.plaf.metal.MetalComboBoxUI",
+ "DesktopIconUI", "javax.swing.plaf.metal.MetalDesktopIconUI",
+ "FileChooserUI", "javax.swing.plaf.metal.MetalFileChooserUI",
+ "InternalFrameUI", "javax.swing.plaf.metal.MetalInternalFrameUI",
+ "LabelUI", "javax.swing.plaf.metal.MetalLabelUI",
+ "MenuBarUI", "javax.swing.plaf.metal.MetalMenuBarUI",
+ "PopupMenuSeparatorUI",
+ "javax.swing.plaf.metal.MetalPopupMenuSeparatorUI",
+ "ProgressBarUI", "javax.swing.plaf.metal.MetalProgressBarUI",
+ "RadioButtonUI", "javax.swing.plaf.metal.MetalRadioButtonUI",
+ "RootPaneUI", "javax.swing.plaf.metal.MetalRootPaneUI",
+ "ScrollBarUI", "javax.swing.plaf.metal.MetalScrollBarUI",
+ "ScrollPaneUI", "javax.swing.plaf.metal.MetalScrollPaneUI",
+ "SeparatorUI", "javax.swing.plaf.metal.MetalSeparatorUI",
+ "SliderUI", "javax.swing.plaf.metal.MetalSliderUI",
+ "SplitPaneUI", "javax.swing.plaf.metal.MetalSplitPaneUI",
+ "TabbedPaneUI", "javax.swing.plaf.metal.MetalTabbedPaneUI",
+ "TextFieldUI", "javax.swing.plaf.metal.MetalTextFieldUI",
+ "ToggleButtonUI", "javax.swing.plaf.metal.MetalToggleButtonUI",
+ "ToolBarUI", "javax.swing.plaf.metal.MetalToolBarUI",
+ "ToolTipUI", "javax.swing.plaf.metal.MetalToolTipUI",
+ "TreeUI", "javax.swing.plaf.metal.MetalTreeUI",
+ };
+ // Add Class Defaults to UI Defaults table
+ defaults.putDefaults(uiDefaults);
+ }
+
+ /**
+ * Initializes the component defaults for the Metal Look &amp; Feel.
+ *
+ * In particular this sets the following keys (the colors are given
+ * as RGB hex values):
+ *
+ * <table>
+ * <tr>
+ * <th>Key</th><th>Value</th>
+ * </tr><tr>
+ * <td>Button.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>Button.border</td><td>{@link MetalBorders#getButtonBorder()}</td>
+ * </tr><tr>
+ * <td>Button.font</td><td>{@link #getControlTextFont}</td>
+ * </tr><tr>
+ * <td>Button.margin</td><td><code>new java.awt.Insets(2, 14, 2, 14)</code>
+ * </td>
+ * </tr><tr>
+ * <td>CheckBox.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>CheckBoxMenuItem.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>ToolBar.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>Panel.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>Slider.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>OptionPane.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>ProgressBar.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>TabbedPane.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>Label.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>Label.font</td><td>{@link #getControlTextFont}</td>
+ * </tr><tr>
+ * <td>Menu.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>MenuBar.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>MenuItem.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>ScrollBar.background</td><td>0xcccccc</td>
+ * </tr><tr>
+ * <td>PopupMenu.border</td>
+ * <td><code>new javax.swing.plaf.metal.MetalBorders.PopupMenuBorder()</td>
+ * </tr><tr>
+ * </table>
+ *
+ * @param defaults the UIDefaults instance to which the values are added
+ */
+ protected void initComponentDefaults(UIDefaults defaults)
+ {
+ super.initComponentDefaults(defaults);
+ Object[] myDefaults = new Object[] {
+ "Button.background", getControl(),
+ "Button.border", MetalBorders.getButtonBorder(),
+ "Button.darkShadow", getControlDarkShadow(),
+ "Button.disabledText", getInactiveControlTextColor(),
+ "Button.focus", getFocusColor(),
+ "Button.font", getControlTextFont(),
+ "Button.foreground", getControlTextColor(),
+ "Button.highlight", getControlHighlight(),
+ "Button.light", getControlHighlight(),
+ "Button.margin", new InsetsUIResource(2, 14, 2, 14),
+ "Button.select", getControlShadow(),
+ "Button.shadow", getControlShadow(),
+
+ "CheckBox.background", getControl(),
+ "CheckBox.border", MetalBorders.getButtonBorder(),
+ "CheckBox.disabledText", getInactiveControlTextColor(),
+ "CheckBox.focus", getFocusColor(),
+ "CheckBox.font", getControlTextFont(),
+ "CheckBox.foreground", getControlTextColor(),
+ "CheckBox.icon",
+ new UIDefaults.ProxyLazyValue("javax.swing.plaf.metal.MetalCheckBoxIcon"),
+ "CheckBox.checkIcon",
+ new UIDefaults.ProxyLazyValue("javax.swing.plaf.metal.MetalCheckBoxIcon"),
+ "Checkbox.select", getControlShadow(),
+
+ "CheckBoxMenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10),
+ "CheckBoxMenuItem.acceleratorForeground", getAcceleratorForeground(),
+ "CheckBoxMenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(),
+ "CheckBoxMenuItem.background", getMenuBackground(),
+ "CheckBoxMenuItem.borderPainted", Boolean.TRUE,
+ "CheckBoxMenuItem.commandSound", "sounds/MenuItemCommand.wav",
+ "CheckBoxMenuItem.checkIcon", MetalIconFactory.getCheckBoxMenuItemIcon(),
+ "CheckBoxMenuItem.disabledForeground", getMenuDisabledForeground(),
+ "CheckBoxMenuItem.font", getMenuTextFont(),
+ "CheckBoxMenuItem.foreground", getMenuForeground(),
+ "CheckBoxMenuItem.selectionBackground", getMenuSelectedBackground(),
+ "CheckBoxMenuItem.selectionForeground", getMenuSelectedForeground(),
+
+ "ColorChooser.background", getControl(),
+ "ColorChooser.foreground", getControlTextColor(),
+ "ColorChooser.rgbBlueMnemonic", new Integer(0),
+ "ColorChooser.rgbGreenMnemonic", new Integer(0),
+ "ColorChooser.rgbRedMnemonic", new Integer(0),
+ "ColorChooser.swatchesDefaultRecentColor", getControl(),
+
+ "ComboBox.background", getControl(),
+ "ComboBox.buttonBackground", getControl(),
+ "ComboBox.buttonDarkShadow", getControlDarkShadow(),
+ "ComboBox.buttonHighlight", getControlHighlight(),
+ "ComboBox.buttonShadow", getControlShadow(),
+ "ComboBox.disabledBackground", getControl(),
+ "ComboBox.disabledForeground", getInactiveSystemTextColor(),
+ "ComboBox.font", getControlTextFont(),
+ "ComboBox.foreground", getControlTextColor(),
+ "ComboBox.selectionBackground", getPrimaryControlShadow(),
+ "ComboBox.selectionForeground", getControlTextColor(),
+
+ "Desktop.background", getDesktopColor(),
+
+ "DesktopIcon.background", getControl(),
+ "DesktopIcon.foreground", getControlTextColor(),
+ "DesktopIcon.width", new Integer(160),
+ "DesktopIcon.border", MetalBorders.getDesktopIconBorder(),
+ "DesktopIcon.font", getControlTextFont(),
+
+ "EditorPane.background", getWindowBackground(),
+ "EditorPane.caretForeground", getUserTextColor(),
+ "EditorPane.font", getControlTextFont(),
+ "EditorPane.foreground", getUserTextColor(),
+ "EditorPane.inactiveForeground", getInactiveSystemTextColor(),
+ "EditorPane.selectionBackground", getTextHighlightColor(),
+ "EditorPane.selectionForeground", getHighlightedTextColor(),
+
+ "FormattedTextField.background", getWindowBackground(),
+ "FormattedTextField.border",
+ new BorderUIResource(MetalBorders.getTextFieldBorder()),
+ "FormattedTextField.caretForeground", getUserTextColor(),
+ "FormattedTextField.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "FormattedTextField.foreground", getUserTextColor(),
+ "FormattedTextField.inactiveBackground", getControl(),
+ "FormattedTextField.inactiveForeground", getInactiveSystemTextColor(),
+ "FormattedTextField.selectionBackground", getTextHighlightColor(),
+ "FormattedTextField.selectionForeground", getHighlightedTextColor(),
+
+ "FileChooser.upFolderIcon",
+ MetalIconFactory.getFileChooserUpFolderIcon(),
+ "FileChooser.listViewIcon",
+ MetalIconFactory.getFileChooserListViewIcon(),
+ "FileChooser.newFolderIcon",
+ MetalIconFactory.getFileChooserNewFolderIcon(),
+ "FileChooser.homeFolderIcon",
+ MetalIconFactory.getFileChooserHomeFolderIcon(),
+ "FileChooser.detailsViewIcon",
+ MetalIconFactory.getFileChooserDetailViewIcon(),
+ "FileChooser.fileNameLabelMnemonic", new Integer(78),
+ "FileChooser.filesOfTypeLabelMnemonic", new Integer(84),
+ "FileChooser.lookInLabelMnemonic", new Integer(73),
+ "FileView.computerIcon", MetalIconFactory.getTreeComputerIcon(),
+ "FileView.directoryIcon", MetalIconFactory.getTreeFolderIcon(),
+ "FileView.fileIcon", MetalIconFactory.getTreeLeafIcon(),
+ "FileView.floppyDriveIcon", MetalIconFactory.getTreeFloppyDriveIcon(),
+ "FileView.hardDriveIcon", MetalIconFactory.getTreeHardDriveIcon(),
+
+ "InternalFrame.activeTitleBackground", getWindowTitleBackground(),
+ "InternalFrame.activeTitleForeground", getWindowTitleForeground(),
+ "InternalFrame.border", new MetalBorders.InternalFrameBorder(),
+ "InternalFrame.borderColor", getControl(),
+ "InternalFrame.borderDarkShadow", getControlDarkShadow(),
+ "InternalFrame.borderHighlight", getControlHighlight(),
+ "InternalFrame.borderLight", getControlHighlight(),
+ "InternalFrame.borderShadow", getControlShadow(),
+ "InternalFrame.icon", MetalIconFactory.getInternalFrameDefaultMenuIcon(),
+ "InternalFrame.closeIcon",
+ MetalIconFactory.getInternalFrameCloseIcon(16),
+ "InternalFrame.closeSound", "sounds/FrameClose.wav",
+ "InternalFrame.inactiveTitleBackground", getWindowTitleInactiveBackground(),
+ "InternalFrame.inactiveTitleForeground", getWindowTitleInactiveForeground(),
+ "InternalFrame.maximizeIcon",
+ MetalIconFactory.getInternalFrameMaximizeIcon(16),
+ "InternalFrame.maximizeSound", "sounds/FrameMaximize.wav",
+ "InternalFrame.iconifyIcon",
+ MetalIconFactory.getInternalFrameMinimizeIcon(16),
+ "InternalFrame.minimizeSound", "sounds/FrameMinimize.wav",
+ "InternalFrame.paletteBorder", new MetalBorders.PaletteBorder(),
+ "InternalFrame.paletteCloseIcon", new MetalIconFactory.PaletteCloseIcon(),
+ "InternalFrame.paletteTitleHeight", new Integer(11),
+ "InternalFrame.restoreDownSound", "sounds/FrameRestoreDown.wav",
+ "InternalFrame.restoreUpSound", "sounds/FrameRestoreUp.wav",
+
+ "Label.background", getControl(),
+ "Label.disabledForeground", getInactiveSystemTextColor(),
+ "Label.disabledShadow", getControlShadow(),
+ "Label.font", getControlTextFont(),
+ "Label.foreground", getSystemTextColor(),
+
+ "List.font", getControlTextFont(),
+ "List.background", getWindowBackground(),
+ "List.foreground", getUserTextColor(),
+ "List.selectionBackground", getTextHighlightColor(),
+ "List.selectionForeground", getHighlightedTextColor(),
+ "List.focusCellHighlightBorder",
+ new LineBorderUIResource(MetalLookAndFeel.getFocusColor()),
+
+ "Menu.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10),
+ "Menu.acceleratorForeground", getAcceleratorForeground(),
+ "Menu.acceleratorSelectionForeground", getAcceleratorSelectedForeground(),
+ "Menu.arrowIcon", MetalIconFactory.getMenuArrowIcon(),
+ "Menu.background", getMenuBackground(),
+ "Menu.border", new MetalBorders.MenuItemBorder(),
+ "Menu.borderPainted", Boolean.TRUE,
+ "MenuItem.commandSound", "sounds/MenuItemCommand.wav",
+ "Menu.disabledForeground", getMenuDisabledForeground(),
+ "Menu.font", getMenuTextFont(),
+ "Menu.foreground", getMenuForeground(),
+ "Menu.selectionBackground", getMenuSelectedBackground(),
+ "Menu.selectionForeground", getMenuSelectedForeground(),
+ "Menu.submenuPopupOffsetX", new Integer(-4),
+ "Menu.submenuPopupOffsetY", new Integer(-3),
+
+ "MenuBar.background", getMenuBackground(),
+ "MenuBar.border", new MetalBorders.MenuBarBorder(),
+ "MenuBar.font", getMenuTextFont(),
+ "MenuBar.foreground", getMenuForeground(),
+ "MenuBar.highlight", getControlHighlight(),
+ "MenuBar.shadow", getControlShadow(),
+
+ "MenuItem.acceleratorDelimiter", "-",
+ "MenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10),
+ "MenuItem.acceleratorForeground", getAcceleratorForeground(),
+ "MenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(),
+ "MenuItem.arrowIcon", MetalIconFactory.getMenuItemArrowIcon(),
+ "MenuItem.background", getMenuBackground(),
+ "MenuItem.border", new MetalBorders.MenuItemBorder(),
+ "MenuItem.borderPainted", Boolean.TRUE,
+ "MenuItem.disabledForeground", getMenuDisabledForeground(),
+ "MenuItem.font", getMenuTextFont(),
+ "MenuItem.foreground", getMenuForeground(),
+ "MenuItem.selectionBackground", getMenuSelectedBackground(),
+ "MenuItem.selectionForeground", getMenuSelectedForeground(),
+
+ "OptionPane.background", getControl(),
+ "OptionPane.errorSound", "sounds/OptionPaneError.wav",
+ "OptionPane.informationSound", "sounds/OptionPaneInformation.wav",
+ "OptionPane.questionSound", "sounds/OptionPaneQuestion.wav",
+ "OptionPane.warningSound", "sounds/OptionPaneWarning.wav",
+ "OptionPane.errorDialog.border.background", new ColorUIResource(153, 51, 51),
+ "OptionPane.errorDialog.titlePane.background", new ColorUIResource(255, 153, 153),
+ "OptionPane.errorDialog.titlePane.foreground", new ColorUIResource(51, 0, 0),
+ "OptionPane.errorDialog.titlePane.shadow", new ColorUIResource(204, 102, 102),
+ "OptionPane.foreground", getControlTextColor(),
+ "OptionPane.messageForeground", getControlTextColor(),
+ "OptionPane.questionDialog.border.background", new ColorUIResource(51, 102, 51),
+ "OptionPane.questionDialog.titlePane.background", new ColorUIResource(153, 204, 153),
+ "OptionPane.questionDialog.titlePane.foreground", new ColorUIResource(0, 51, 0),
+ "OptionPane.questionDialog.titlePane.shadow", new ColorUIResource(102, 153, 102),
+ "OptionPane.warningDialog.border.background", new ColorUIResource(153, 102, 51),
+ "OptionPane.warningDialog.titlePane.background", new ColorUIResource(255, 204, 153),
+ "OptionPane.warningDialog.titlePane.foreground", new ColorUIResource(102, 51, 0),
+ "OptionPane.warningDialog.titlePane.shadow", new ColorUIResource(204, 153, 102),
+
+ "Panel.background", getControl(),
+ "Panel.foreground", getUserTextColor(),
+
+ "PasswordField.background", getWindowBackground(),
+ "PasswordField.border",
+ new BorderUIResource(MetalBorders.getTextFieldBorder()),
+ "PasswordField.caretForeground", getUserTextColor(),
+ "PasswordField.foreground", getUserTextColor(),
+ "PasswordField.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "PasswordField.inactiveBackground", getControl(),
+ "PasswordField.inactiveForeground", getInactiveSystemTextColor(),
+ "PasswordField.selectionBackground", getTextHighlightColor(),
+ "PasswordField.selectionForeground", getHighlightedTextColor(),
+
+ "PopupMenu.background", getMenuBackground(),
+ "PopupMenu.border", new MetalBorders.PopupMenuBorder(),
+ "PopupMenu.font", getMenuTextFont(),
+ "PopupMenu.foreground", getMenuForeground(),
+ "PopupMenu.popupSound", "sounds/PopupMenuPopup.wav",
+
+ "ProgressBar.background", getControl(),
+ "ProgressBar.border", new BorderUIResource.LineBorderUIResource(getControlDarkShadow(), 1),
+ "ProgressBar.font", getControlTextFont(),
+ "ProgressBar.foreground", getPrimaryControlShadow(),
+ "ProgressBar.selectionBackground", getPrimaryControlDarkShadow(),
+ "ProgressBar.selectionForeground", getControl(),
+
+ "RadioButton.background", getControl(),
+ "RadioButton.darkShadow", getControlDarkShadow(),
+ "RadioButton.disabledText", getInactiveControlTextColor(),
+ "RadioButton.icon",
+ new UIDefaults.LazyValue()
+ {
+ public Object createValue(UIDefaults def)
+ {
+ return MetalIconFactory.getRadioButtonIcon();
+ }
+ },
+ "RadioButton.focus", MetalLookAndFeel.getFocusColor(),
+ "RadioButton.font", MetalLookAndFeel.getControlTextFont(),
+ "RadioButton.foreground", getControlTextColor(),
+ "RadioButton.highlight", getControlHighlight(),
+ "RadioButton.light", getControlHighlight(),
+ "RadioButton.select", getControlShadow(),
+ "RadioButton.shadow", getControlShadow(),
+
+ "RadioButtonMenuItem.acceleratorFont", new Font("Dialog", Font.PLAIN, 10),
+ "RadioButtonMenuItem.acceleratorForeground", getAcceleratorForeground(),
+ "RadioButtonMenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(),
+ "RadioButtonMenuItem.background", getMenuBackground(),
+ "RadioButtonMenuItem.border", new MetalBorders.MenuItemBorder(),
+ "RadioButtonMenuItem.borderPainted", Boolean.TRUE,
+ "RadioButtonMenuItem.checkIcon",
+ MetalIconFactory.getRadioButtonMenuItemIcon(),
+ "RadioButtonMenuItem.commandSound", "sounds/MenuItemCommand.wav",
+ "RadioButtonMenuItem.disabledForeground", getMenuDisabledForeground(),
+ "RadioButtonMenuItem.font", getMenuTextFont(),
+ "RadioButtonMenuItem.foreground", getMenuForeground(),
+ "RadioButtonMenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
+ "RadioButtonMenuItem.selectionBackground",
+ MetalLookAndFeel.getMenuSelectedBackground(),
+ "RadioButtonMenuItem.selectionForeground",
+ MetalLookAndFeel.getMenuSelectedForeground(),
+
+ "ScrollBar.allowsAbsolutePositioning", Boolean.TRUE,
+ "ScrollBar.background", getControl(),
+ "ScrollBar.darkShadow", getControlDarkShadow(),
+ "ScrollBar.foreground", getControl(),
+ "ScrollBar.highlight", getControlHighlight(),
+ "ScrollBar.shadow", getControlShadow(),
+ "ScrollBar.thumb", getPrimaryControlShadow(),
+ "ScrollBar.thumbDarkShadow", getControlDarkShadow(),
+ "ScrollBar.thumbHighlight", getPrimaryControl(),
+ "ScrollBar.thumbShadow", getPrimaryControlDarkShadow(),
+ "ScrollBar.track", getControl(),
+ "ScrollBar.trackHighlight", getControlDarkShadow(),
+ "ScrollBar.width", new Integer(17),
+
+ "ScrollPane.background", getControl(),
+ "ScrollPane.border", new MetalBorders.ScrollPaneBorder(),
+ "ScrollPane.foreground", getControlTextColor(),
+
+ "Separator.background", getSeparatorBackground(),
+ "Separator.foreground", getSeparatorForeground(),
+ "Separator.highlight", getControlHighlight(),
+ "Separator.shadow", getControlShadow(),
+
+ "Slider.background", getControl(),
+ "Slider.focus", getFocusColor(),
+ "Slider.focusInsets", new InsetsUIResource(0, 0, 0, 0),
+ "Slider.foreground", getPrimaryControlShadow(),
+ "Slider.highlight", getControlHighlight(),
+ "Slider.horizontalThumbIcon",
+ MetalIconFactory.getHorizontalSliderThumbIcon(),
+ "Slider.majorTickLength", new Integer(6),
+ "Slider.shadow", getControlShadow(),
+ "Slider.trackWidth", new Integer(7),
+ "Slider.verticalThumbIcon",
+ MetalIconFactory.getVerticalSliderThumbIcon(),
+
+ "Spinner.arrowButtonInsets", new InsetsUIResource(0, 0, 0, 0),
+ "Spinner.background", getControl(),
+ "Spinner.border", MetalBorders.getTextFieldBorder(),
+ "Spinner.font", getControlTextFont(),
+ "Spinner.foreground", getControl(),
+
+ "SplitPane.background", getControl(),
+ "SplitPane.darkShadow", getControlDarkShadow(),
+ "SplitPane.dividerFocusColor", getPrimaryControl(),
+ "SplitPane.dividerSize", new Integer(10),
+ "SplitPane.highlight", getControlHighlight(),
+ "SplitPane.shadow", getControlShadow(),
+
+ "SplitPaneDivider.draggingColor", Color.DARK_GRAY,
+
+ "TabbedPane.background", getControlShadow(),
+ "TabbedPane.contentBorderInsets", new InsetsUIResource(2, 2, 3, 3),
+ "TabbedPane.contentOpaque", Boolean.TRUE,
+ "TabbedPane.darkShadow", getControlDarkShadow(),
+ "TabbedPane.focus", getPrimaryControlDarkShadow(),
+ "TabbedPane.font", getControlTextFont(),
+ "TabbedPane.foreground", getControlTextColor(),
+ "TabbedPane.highlight", getControlHighlight(),
+ "TabbedPane.light", getControl(),
+ "TabbedPane.selected", getControl(), // overridden in OceanTheme
+ "TabbedPane.selectHighlight", getControlHighlight(),
+ "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 2, 1),
+ "TabbedPane.shadow", getControlShadow(),
+ "TabbedPane.tabAreaBackground", getControl(), // overridden in OceanTheme
+ "TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6), // dito
+ "TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9),
+
+ // new properties in OceanTheme:
+ // TabbedPane.contentAreaColor
+ // TabbedPane.unselectedBackground
+
+ "Table.background", getWindowBackground(),
+ "Table.focusCellBackground", getWindowBackground(),
+ "Table.focusCellForeground", getControlTextColor(),
+ "Table.foreground", getControlTextColor(),
+ "Table.focusCellHighlightBorder",
+ new BorderUIResource.LineBorderUIResource(getFocusColor()),
+ "Table.focusCellBackground", getWindowBackground(),
+ "Table.gridColor", getControlDarkShadow(),
+ "Table.selectionBackground", new ColorUIResource(204, 204, 255),
+ "Table.selectionForeground", new ColorUIResource(0, 0, 0),
+
+ "TableHeader.background", getControl(),
+ "TableHeader.cellBorder", new MetalBorders.TableHeaderBorder(),
+ "TableHeader.foreground", getControlTextColor(),
+
+ "TextArea.background", getWindowBackground(),
+ "TextArea.caretForeground", getUserTextColor(),
+ "TextArea.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "TextArea.foreground", getUserTextColor(),
+ "TextArea.inactiveForeground", getInactiveSystemTextColor(),
+ "TextArea.selectionBackground", getTextHighlightColor(),
+ "TextArea.selectionForeground", getHighlightedTextColor(),
+
+ "TextField.background", getWindowBackground(),
+ "TextField.border",
+ new BorderUIResource(MetalBorders.getTextFieldBorder()),
+ "TextField.caretForeground", getUserTextColor(),
+ "TextField.darkShadow", getControlDarkShadow(),
+ "TextField.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "TextField.foreground", getUserTextColor(),
+ "TextField.highlight", getControlHighlight(),
+ "TextField.inactiveBackground", getControl(),
+ "TextField.inactiveForeground", getInactiveSystemTextColor(),
+ "TextField.light", getControlHighlight(),
+ "TextField.selectionBackground", getTextHighlightColor(),
+ "TextField.selectionForeground", getHighlightedTextColor(),
+ "TextField.shadow", getControlShadow(),
+
+ "TextPane.background", getWindowBackground(),
+ "TextPane.caretForeground", getUserTextColor(),
+ "TextPane.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "TextPane.foreground", getUserTextColor(),
+ "TextPane.inactiveForeground", getInactiveSystemTextColor(),
+ "TextPane.selectionBackground", getTextHighlightColor(),
+ "TextPane.selectionForeground", getHighlightedTextColor(),
+
+ "TitledBorder.border", new LineBorderUIResource(getPrimaryControl(), 1),
+ "TitledBorder.font", getControlTextFont(),
+ "TitledBorder.titleColor", getSystemTextColor(),
+
+ "ToggleButton.background", getControl(),
+ "ToggleButton.border", MetalBorders.getToggleButtonBorder(),
+ "ToggleButton.darkShadow", getControlDarkShadow(),
+ "ToggleButton.disabledText", getInactiveControlTextColor(),
+ "ToggleButton.focus", getFocusColor(),
+ "ToggleButton.font", getControlTextFont(),
+ "ToggleButton.foreground", getControlTextColor(),
+ "ToggleButton.highlight", getControlHighlight(),
+ "ToggleButton.light", getControlHighlight(),
+ "ToggleButton.margin", new InsetsUIResource(2, 14, 2, 14),
+ "ToggleButton.select", getControlShadow(),
+ "ToggleButton.shadow", getControlShadow(),
+
+ "ToolBar.background", getMenuBackground(),
+ "ToolBar.darkShadow", getControlDarkShadow(),
+ "ToolBar.dockingBackground", getMenuBackground(),
+ "ToolBar.dockingForeground", getPrimaryControlDarkShadow(),
+ "ToolBar.floatingBackground", getMenuBackground(),
+ "ToolBar.floatingForeground", getPrimaryControl(),
+ "ToolBar.font", getMenuTextFont(),
+ "ToolBar.foreground", getMenuForeground(),
+ "ToolBar.highlight", getControlHighlight(),
+ "ToolBar.light", getControlHighlight(),
+ "ToolBar.shadow", getControlShadow(),
+ "ToolBar.border", new MetalBorders.ToolBarBorder(),
+ "ToolBar.rolloverBorder", MetalBorders.getToolbarButtonBorder(),
+ "ToolBar.nonrolloverBorder", MetalBorders.getToolbarButtonBorder(),
+
+ "ToolTip.background", getPrimaryControl(),
+ "ToolTip.backgroundInactive", getControl(),
+ "ToolTip.border", new BorderUIResource.LineBorderUIResource(getPrimaryControlDarkShadow(), 1),
+ "ToolTip.borderInactive", new BorderUIResource.LineBorderUIResource(getControlDarkShadow(), 1),
+ "ToolTip.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "ToolTip.foreground", getPrimaryControlInfo(),
+ "ToolTip.foregroundInactive", getControlDarkShadow(),
+ "ToolTip.hideAccelerator", Boolean.FALSE,
+
+ "Tree.background", getWindowBackground(),
+ "Tree.closedIcon", MetalIconFactory.getTreeFolderIcon(),
+ "Tree.collapsedIcon", MetalIconFactory.getTreeControlIcon(true),
+ "Tree.expandedIcon", MetalIconFactory.getTreeControlIcon(false),
+ "Tree.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "Tree.foreground", getUserTextColor(),
+ "Tree.hash", getPrimaryControl(),
+ "Tree.leafIcon", MetalIconFactory.getTreeLeafIcon(),
+ "Tree.leftChildIndent", new Integer(7),
+ "Tree.line", getPrimaryControl(),
+ "Tree.openIcon", MetalIconFactory.getTreeFolderIcon(),
+ "Tree.rightChildIndent", new Integer(13),
+ "Tree.rowHeight", new Integer(0),
+ "Tree.scrollsOnExpand", Boolean.TRUE,
+ "Tree.selectionBackground", getTextHighlightColor(),
+ "Tree.selectionBorder", new BorderUIResource.LineBorderUIResource(new Color(102, 102, 153)),
+ "Tree.selectionBorderColor", getFocusColor(),
+ "Tree.selectionForeground", getHighlightedTextColor(),
+ "Tree.textBackground", getWindowBackground(),
+ "Tree.textForeground", getUserTextColor(),
+
+ "Viewport.background", getControl(),
+ "Viewport.foreground", getUserTextColor()
+ };
+ defaults.putDefaults(myDefaults);
+ }
+
+ /**
+ * Initializes the system color defaults.
+ *
+ * In particular this sets the following keys:
+ *
+ * <table>
+ * <tr>
+ * <th>Key</th><th>Value</th><th>Description</th>
+ * </tr><tr>
+ * <td>control</td><td>0xcccccc</td><td>The default color for components</td>
+ * </tr>
+ * </table>
+ */
+ protected void initSystemColorDefaults(UIDefaults defaults)
+ {
+ super.initSystemColorDefaults(defaults);
+ Object[] uiDefaults;
+ uiDefaults = new Object[] {
+ "control", new ColorUIResource(getControl()),
+ "desktop", new ColorUIResource(getDesktopColor())
+ };
+ defaults.putDefaults(uiDefaults);
+ }
+
+ /**
+ * Returns the current theme for the Metal look and feel. The default is
+ * an instance of {@link OceanTheme}.
+ *
+ * @return The current theme (never <code>null</code>).
+ *
+ * @see #setCurrentTheme(MetalTheme)
+ */
+ public static MetalTheme getCurrentTheme()
+ {
+ if (theme == null)
+ {
+ // swing.metalTheme property documented here:
+ // http://java.sun.com/j2se/1.5.0/docs/guide/swing/1.5/index.html
+ if ("steel".equals(SystemProperties.getProperty("swing.metalTheme")))
+ theme = new DefaultMetalTheme();
+ else
+ theme = new OceanTheme();
+ }
+ return theme;
+ }
+
+ /**
+ * Returns <code>true</code> because the Metal look
+ * and feel supports window decorations for toplevel
+ * containers.
+ *
+ * @return <code>true</code>
+ */
+ public boolean getSupportsWindowDecorations()
+ {
+ return true;
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalMenuBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalMenuBarUI.java
new file mode 100644
index 000000000..35f2b05c0
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalMenuBarUI.java
@@ -0,0 +1,94 @@
+/* MetalMenuBarUI.java -- MenuBar UI for the Metal L&F
+ 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.Graphics;
+
+import javax.swing.JComponent;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.basic.BasicMenuBarUI;
+
+/**
+ * A UI implementation for MenuBar in the Metal Look &amp; Feel.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ *
+ * @since 1.5
+ */
+public class MetalMenuBarUI extends BasicMenuBarUI
+{
+ /**
+ * Creates and returns a new instance of this UI for the specified component.
+ *
+ * @param c the component to create a UI for
+ *
+ * @return the UI for the component
+ */
+ public static ComponentUI createUI(JComponent c)
+ {
+ return new MetalMenuBarUI();
+ }
+
+
+ /**
+ * If the property <code>MenuBar.gradient</code> is set, then a gradient
+ * is painted as background, otherwise the normal superclass behaviour is
+ * called.
+ */
+ public void update(Graphics g, JComponent c)
+ {
+ int height = c.getHeight();
+ if (c.isOpaque()
+ && UIManager.get("MenuBar.gradient") != null
+ && c.getBackground() instanceof UIResource
+ && height > 2)
+ {
+ MetalUtils.paintGradient(g, 0, 0, c.getWidth(), height,
+ SwingConstants.VERTICAL, "MenuBar.gradient");
+
+ paint(g, c);
+ }
+ else
+ super.update(g, c);
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java
new file mode 100644
index 000000000..7c580f90f
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java
@@ -0,0 +1,77 @@
+/* MetalPopupMenuSeparatorUI.java
+ Copyright (C) 2005 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 javax.swing.JComponent;
+import javax.swing.JPopupMenu;
+import javax.swing.plaf.ComponentUI;
+
+/**
+ * A UI delegate for the {@link JPopupMenu.Separator} component.
+ */
+public class MetalPopupMenuSeparatorUI
+ extends MetalSeparatorUI
+{
+
+ // FIXME: maybe replace by a Map of instances when this becomes stateful
+ /** The shared UI instance for MetalPopupMenuSeparatorUIs */
+ private static MetalPopupMenuSeparatorUI instance;
+
+ /**
+ * Constructs a new instance of <code>MetalPopupMenuSeparatorUI</code>.
+ */
+ public MetalPopupMenuSeparatorUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a shared instance of <code>MetalPopupMenuSeparatorUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A shared instance of <code>MetalPopupMenuSeparatorUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ if (instance == null)
+ instance = new MetalPopupMenuSeparatorUI();
+ return instance;
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java
new file mode 100644
index 000000000..005c5f0d8
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java
@@ -0,0 +1,147 @@
+/* MetalProgressBarUI.java
+ Copyright (C) 2005 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.Graphics;
+import java.awt.Insets;
+
+import javax.swing.JComponent;
+import javax.swing.JProgressBar;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicProgressBarUI;
+
+/**
+ * A UI delegate for the {@link JProgressBar} component.
+ */
+public class MetalProgressBarUI extends BasicProgressBarUI
+{
+ /**
+ * Constructs a new instance of <code>MetalProgressBarUI</code>.
+ */
+ public MetalProgressBarUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new instance of <code>MetalProgressBarUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A new instance of <code>MetalProgressBarUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalProgressBarUI();
+ }
+
+ /**
+ * Performs the painting for determinate progress bars. This calls the
+ * superclass behaviour and then adds some highlighting to the upper and left
+ * edge of the progress bar.
+ *
+ * @param g the graphics context
+ * @param c not used here
+ */
+ public void paintDeterminate(Graphics g, JComponent c)
+ {
+ super.paintDeterminate(g, c);
+ Color saved = g.getColor();
+ Insets i = progressBar.getInsets();
+ int w = progressBar.getWidth();
+ int h = progressBar.getHeight();
+ int orientation = progressBar.getOrientation();
+
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ g.setColor(shadow);
+
+ g.drawLine(i.left, i.top, w - i.right, i.top);
+ g.drawLine(i.left, i.top, i.left, h - i.bottom);
+ int full = getAmountFull(i, w, h);
+ if (full > 0)
+ {
+ Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
+ g.setColor(darkShadow);
+ if (orientation == JProgressBar.HORIZONTAL)
+ {
+ g.drawLine(i.left, i.top, i.left, h - i.bottom);
+ g.drawLine(i.left, i.top, i.left + full - 1, i.top);
+ }
+ else
+ {
+ if (full >= (h - i.top - i.bottom))
+ g.drawLine(i.left, i.top, w - i.right, i.top);
+ g.drawLine(i.left, h - i.bottom, i.left, h - i.bottom - full);
+ }
+ }
+ g.setColor(saved);
+ }
+
+ /**
+ * Performs the painting for indeterminate progress bars. This calls the
+ * superclass behaviour and then adds some highlighting to the upper and left
+ * edge of the progress bar.
+ *
+ * @param g the graphics context
+ * @param c not used here
+ */
+ public void paintIndeterminate(Graphics g, JComponent c)
+ {
+ super.paintIndeterminate(g, c);
+ Color saved = g.getColor();
+ Insets i = progressBar.getInsets();
+ int w = progressBar.getWidth();
+ int h = progressBar.getHeight();
+ Color shadow = MetalLookAndFeel.getControlShadow();
+ g.setColor(shadow);
+ g.drawLine(i.left, i.top, w - i.right, i.top);
+ g.drawLine(i.left, i.top, i.left, h - i.bottom);
+
+ boxRect = getBox(boxRect);
+ Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
+ g.setColor(darkShadow);
+ int orientation = progressBar.getOrientation();
+ if (orientation == JProgressBar.HORIZONTAL)
+ g.drawLine(boxRect.x, i.top, boxRect.x + boxRect.width - 1, i.top);
+ else
+ g.drawLine(i.left, boxRect.y, i.left, boxRect.y + boxRect.height - 1);
+ g.setColor(saved);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java
new file mode 100644
index 000000000..0f7f3b101
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java
@@ -0,0 +1,183 @@
+/* MetalRadioButtonUI.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.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.AbstractButton;
+import javax.swing.JComponent;
+import javax.swing.JRadioButton;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicRadioButtonUI;
+
+
+/**
+ * A UI delegate for the {@link JRadioButton} component.
+ */
+public class MetalRadioButtonUI
+ extends BasicRadioButtonUI
+{
+
+ /** Used to draw the focus rectangle. */
+ protected Color focusColor;
+
+ /** Used to fill the icon when the button is pressed. */
+ protected Color selectColor;
+
+ /** Used to draw disabled text. */
+ protected Color disabledTextColor;
+
+ /**
+ * Constructs a new instance of <code>MetalRadioButtonUI</code>.
+ */
+ public MetalRadioButtonUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new instance of <code>MetalRadioButtonUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A new instance of <code>MetalRadioButtonUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalRadioButtonUI();
+ }
+
+ /**
+ * Sets the default values for the specified button.
+ *
+ * @param b the button.
+ */
+ public void installDefaults(AbstractButton b)
+ {
+ super.installDefaults(b);
+ String prefix = getPropertyPrefix();
+ disabledTextColor = UIManager.getColor(prefix + "disabledText");
+ focusColor = UIManager.getColor(prefix + "focus");
+ selectColor = UIManager.getColor(prefix + "select");
+ }
+
+ /**
+ * Clears any defaults set in the installDefaults() method.
+ *
+ * @param b the {@link JRadioButton}.
+ */
+ protected void uninstallDefaults(AbstractButton b)
+ {
+ super.uninstallDefaults(b);
+ disabledTextColor = null;
+ focusColor = null;
+ selectColor = null;
+ }
+
+ /**
+ * Returns the color used to fill the {@link JRadioButton}'s icon when the
+ * button is pressed. The default color is obtained from the
+ * {@link UIManager} defaults via an entry with the key
+ * <code>RadioButton.select</code>.
+ *
+ * @return The select color.
+ */
+ protected Color getSelectColor()
+ {
+ return selectColor;
+ }
+
+ /**
+ * Returns the color for the {@link JRadioButton}'s text when the button is
+ * disabled. The default color is obtained from the {@link UIManager}
+ * defaults via an entry with the key <code>RadioButton.disabledText</code>.
+ *
+ * @return The disabled text color.
+ */
+ protected Color getDisabledTextColor()
+ {
+ return disabledTextColor;
+ }
+
+ /**
+ * Returns the color used to draw the focus rectangle when the
+ * {@link JRadioButton} has the focus. The default color is obtained from
+ * the {@link UIManager} defaults via an entry with the key
+ * <code>RadioButton.focus</code>.
+ *
+ * @return The color used to draw the focus rectangle.
+ *
+ * @see #paintFocus(Graphics, Rectangle, Dimension)
+ */
+ protected Color getFocusColor()
+ {
+ return focusColor;
+ }
+
+ /**
+ * Paints the {@link JRadioButton}.
+ *
+ * @param g the graphics device.
+ * @param c the component (an instance of {@link JRadioButton}).
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ super.paint(g, c);
+ // FIXME: disabled text isn't being drawn correctly, it's possible that
+ // it could be done here...
+ }
+
+ /**
+ * Paints the focus rectangle for the {@link JRadioButton}.
+ *
+ * @param g the graphics device.
+ * @param t the bounding rectangle for the text.
+ * @param d ???
+ */
+ protected void paintFocus(Graphics g, Rectangle t, Dimension d)
+ {
+ g.setColor(focusColor);
+ g.drawRect(t.x - 1, t.y - 1, t.width + 1, t.height + 1);
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java
new file mode 100644
index 000000000..84f1303f6
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java
@@ -0,0 +1,1075 @@
+/* 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;
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
new file mode 100644
index 000000000..5f0cbe4be
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java
@@ -0,0 +1,584 @@
+/* MetalScrollBarUI.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.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JScrollBar;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicScrollBarUI;
+
+/**
+ * A UI delegate for the {@link JScrollBar} component.
+ */
+public class MetalScrollBarUI extends BasicScrollBarUI
+{
+
+ /**
+ * A property change handler for the UI delegate that monitors for
+ * changes to the "JScrollBar.isFreeStanding" property, and updates
+ * the buttons and track rendering as appropriate.
+ */
+ class MetalScrollBarPropertyChangeHandler
+ extends BasicScrollBarUI.PropertyChangeHandler
+ {
+ /**
+ * Creates a new handler.
+ *
+ * @see #createPropertyChangeListener()
+ */
+ public MetalScrollBarPropertyChangeHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles a property change event. If the event name is
+ * <code>JSlider.isFreeStanding</code>, this method updates the
+ * delegate, otherwise the event is passed up to the super class.
+ *
+ * @param e the property change event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(FREE_STANDING_PROP))
+ {
+ Boolean prop = (Boolean) e.getNewValue();
+ isFreeStanding = prop == null ? true : prop.booleanValue();
+ if (increaseButton != null)
+ increaseButton.setFreeStanding(isFreeStanding);
+ if (decreaseButton != null)
+ decreaseButton.setFreeStanding(isFreeStanding);
+ }
+ else
+ super.propertyChange(e);
+ }
+ }
+
+ /** The name for the 'free standing' property. */
+ public static final String FREE_STANDING_PROP = "JScrollBar.isFreeStanding";
+
+ /** The minimum thumb size for a scroll bar that is not free standing. */
+ private static final Dimension MIN_THUMB_SIZE = new Dimension(15, 15);
+
+ /** The minimum thumb size for a scroll bar that is free standing. */
+ private static final Dimension MIN_THUMB_SIZE_FREE_STANDING
+ = new Dimension(17, 17);
+
+ /** The button that increases the value in the scroll bar. */
+ protected MetalScrollButton increaseButton;
+
+ /** The button that decreases the value in the scroll bar. */
+ protected MetalScrollButton decreaseButton;
+
+ /**
+ * The scroll bar width.
+ */
+ protected int scrollBarWidth;
+
+ /**
+ * A flag that indicates whether the scroll bar is "free standing", which
+ * means it has complete borders and can be used anywhere in the UI. A
+ * scroll bar which is not free standing has borders missing from one
+ * side, and relies on being part of another container with its own borders
+ * to look right visually. */
+ protected boolean isFreeStanding = true;
+
+ /**
+ * The color for the scroll bar shadow (this is read from the UIDefaults in
+ * the installDefaults() method).
+ */
+ Color scrollBarShadowColor;
+
+ /**
+ * Constructs a new instance of <code>MetalScrollBarUI</code>, with no
+ * specific initialisation.
+ */
+ public MetalScrollBarUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new instance of <code>MetalScrollBarUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return An instance of MetalScrollBarUI
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalScrollBarUI();
+ }
+
+ /**
+ * Installs the defaults.
+ */
+ protected void installDefaults()
+ {
+ // need to initialise isFreeStanding before calling the super class,
+ // so that the value is set when createIncreaseButton() and
+ // createDecreaseButton() are called (unless there is somewhere earlier
+ // that we can do this).
+ Boolean prop = (Boolean) scrollbar.getClientProperty(FREE_STANDING_PROP);
+ isFreeStanding = prop == null ? true : prop.booleanValue();
+ scrollBarShadowColor = UIManager.getColor("ScrollBar.shadow");
+ scrollBarWidth = UIManager.getInt("ScrollBar.width");
+ super.installDefaults();
+ }
+
+ /**
+ * Creates a property change listener for the delegate to use. This
+ * overrides the method to provide a custom listener for the
+ * {@link MetalLookAndFeel} that can handle the
+ * <code>JScrollBar.isFreeStanding</code> property.
+ *
+ * @return A property change listener.
+ */
+ protected PropertyChangeListener createPropertyChangeListener()
+ {
+ return new MetalScrollBarPropertyChangeHandler();
+ }
+
+ /**
+ * Creates a new button to use as the control at the lower end of the
+ * {@link JScrollBar}. This method assigns the new button (an instance of
+ * {@link MetalScrollButton} to the {@link #decreaseButton} field, and also
+ * returns the button. The button width is determined by the
+ * <code>ScrollBar.width</code> setting in the UI defaults.
+ *
+ * @param orientation the orientation of the button ({@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} or {@link #WEST}).
+ *
+ * @return The button.
+ */
+ protected JButton createDecreaseButton(int orientation)
+ {
+ decreaseButton = new MetalScrollButton(orientation, scrollBarWidth,
+ isFreeStanding);
+ return decreaseButton;
+ }
+
+ /**
+ * Creates a new button to use as the control at the upper end of the
+ * {@link JScrollBar}. This method assigns the new button (an instance of
+ * {@link MetalScrollButton} to the {@link #increaseButton} field, and also
+ * returns the button. The button width is determined by the
+ * <code>ScrollBar.width</code> setting in the UI defaults.
+ *
+ * @param orientation the orientation of the button ({@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} or {@link #WEST}).
+ *
+ * @return The button.
+ */
+ protected JButton createIncreaseButton(int orientation)
+ {
+ increaseButton = new MetalScrollButton(orientation, scrollBarWidth,
+ isFreeStanding);
+ return increaseButton;
+ }
+
+ /**
+ * Paints the track for the scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param trackBounds the track bounds.
+ */
+ protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
+ {
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width,
+ trackBounds.height);
+ if (scrollbar.getOrientation() == HORIZONTAL)
+ paintTrackHorizontal(g, c, trackBounds.x, trackBounds.y,
+ trackBounds.width, trackBounds.height);
+ else
+ paintTrackVertical(g, c, trackBounds.x, trackBounds.y,
+ trackBounds.width, trackBounds.height);
+
+ }
+
+ /**
+ * Paints the track for a horizontal scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param x the x-coordinate for the track bounds.
+ * @param y the y-coordinate for the track bounds.
+ * @param w the width for the track bounds.
+ * @param h the height for the track bounds.
+ */
+ private void paintTrackHorizontal(Graphics g, JComponent c,
+ int x, int y, int w, int h)
+ {
+ if (c.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+
+ g.setColor(scrollBarShadowColor);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 1);
+ g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
+
+ if (isFreeStanding)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y + h - 2, x + w - 1, y + h - 2);
+ g.setColor(scrollBarShadowColor);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ if (isFreeStanding)
+ g.drawRect(x, y, w - 1, h - 1);
+ else
+ {
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ }
+ }
+ }
+
+ /**
+ * Paints the track for a vertical scrollbar.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param x the x-coordinate for the track bounds.
+ * @param y the y-coordinate for the track bounds.
+ * @param w the width for the track bounds.
+ * @param h the height for the track bounds.
+ */
+ private void paintTrackVertical(Graphics g, JComponent c,
+ int x, int y, int w, int h)
+ {
+ if (c.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+
+ g.setColor(scrollBarShadowColor);
+ g.drawLine(x + 1, y + 1, x + w - 1, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
+
+ if (isFreeStanding)
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(x + w - 2, y, x + w - 2, y + h - 1);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ }
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ if (isFreeStanding)
+ g.drawRect(x, y, w - 1, h - 1);
+ else
+ {
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
+ }
+ }
+
+ /**
+ * Paints the slider button of the ScrollBar.
+ *
+ * @param g the Graphics context to use
+ * @param c the JComponent on which we paint
+ * @param thumbBounds the rectangle that is the slider button
+ */
+ protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
+ {
+ // a disabled scrollbar has no thumb in the metal look and feel
+ if (!c.isEnabled())
+ return;
+ if (scrollbar.getOrientation() == HORIZONTAL)
+ paintThumbHorizontal(g, c, thumbBounds);
+ else
+ paintThumbVertical(g, c, thumbBounds);
+
+ // Draw the pattern when the theme is not Ocean.
+ if (! (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme))
+ {
+ MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3,
+ thumbBounds.width - 6,
+ thumbBounds.height - 6,
+ thumbHighlightColor,
+ thumbLightShadowColor);
+ }
+ }
+
+ /**
+ * Paints the thumb for a horizontal scroll bar.
+ *
+ * @param g the graphics device.
+ * @param c the scroll bar component.
+ * @param thumbBounds the thumb bounds.
+ */
+ private void paintThumbHorizontal(Graphics g, JComponent c,
+ Rectangle thumbBounds)
+ {
+ int x = thumbBounds.x;
+ int y = thumbBounds.y;
+ int w = thumbBounds.width;
+ int h = thumbBounds.height;
+
+ // First we fill the background.
+ MetalTheme theme = MetalLookAndFeel.getCurrentTheme();
+ if (theme instanceof OceanTheme
+ && UIManager.get("ScrollBar.gradient") != null)
+ {
+ MetalUtils.paintGradient(g, x + 2, y + 2, w - 4, h - 2,
+ SwingConstants.VERTICAL,
+ "ScrollBar.gradient");
+ }
+ else
+ {
+ g.setColor(thumbColor);
+ if (isFreeStanding)
+ g.fillRect(x, y, w, h - 1);
+ else
+ g.fillRect(x, y, w, h);
+ }
+
+ // then draw the dark box
+ g.setColor(thumbLightShadowColor);
+ if (isFreeStanding)
+ g.drawRect(x, y, w - 1, h - 2);
+ else
+ {
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ }
+
+ // then the highlight
+ g.setColor(thumbHighlightColor);
+ if (isFreeStanding)
+ {
+ g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+ }
+ else
+ {
+ g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 1);
+ }
+
+ // draw the shadow line
+ g.setColor(UIManager.getColor("ScrollBar.shadow"));
+ g.drawLine(x + w, y + 1, x + w, y + h - 1);
+
+ // For the OceanTheme, draw the 3 lines in the middle.
+ if (theme instanceof OceanTheme)
+ {
+ g.setColor(thumbLightShadowColor);
+ int middle = x + w / 2;
+ g.drawLine(middle - 2, y + 4, middle - 2, y + h - 5);
+ g.drawLine(middle, y + 4, middle, y + h - 5);
+ g.drawLine(middle + 2, y + 4, middle + 2, y + h - 5);
+ g.setColor(UIManager.getColor("ScrollBar.highlight"));
+ g.drawLine(middle - 1, y + 5, middle - 1, y + h - 4);
+ g.drawLine(middle + 1, y + 5, middle + 1, y + h - 4);
+ g.drawLine(middle + 3, y + 5, middle + 3, y + h - 4);
+ }
+ }
+
+ /**
+ * Paints the thumb for a vertical scroll bar.
+ *
+ * @param g the graphics device.
+ * @param c the scroll bar component.
+ * @param thumbBounds the thumb bounds.
+ */
+ private void paintThumbVertical(Graphics g, JComponent c,
+ Rectangle thumbBounds)
+ {
+ int x = thumbBounds.x;
+ int y = thumbBounds.y;
+ int w = thumbBounds.width;
+ int h = thumbBounds.height;
+
+ // First we fill the background.
+ MetalTheme theme = MetalLookAndFeel.getCurrentTheme();
+ if (theme instanceof OceanTheme
+ && UIManager.get("ScrollBar.gradient") != null)
+ {
+ MetalUtils.paintGradient(g, x + 2, y + 2, w - 2, h - 4,
+ SwingConstants.HORIZONTAL,
+ "ScrollBar.gradient");
+ }
+ else
+ {
+ g.setColor(thumbColor);
+ if (isFreeStanding)
+ g.fillRect(x, y, w - 1, h);
+ else
+ g.fillRect(x, y, w, h);
+ }
+
+ // then draw the dark box
+ g.setColor(thumbLightShadowColor);
+ if (isFreeStanding)
+ g.drawRect(x, y, w - 2, h - 1);
+ else
+ {
+ g.drawLine(x, y, x + w - 1, y);
+ g.drawLine(x, y, x, y + h - 1);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
+
+ // then the highlight
+ g.setColor(thumbHighlightColor);
+ if (isFreeStanding)
+ {
+ g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+ }
+ else
+ {
+ g.drawLine(x + 1, y + 1, x + w - 1, y + 1);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
+ }
+
+ // draw the shadow line
+ g.setColor(UIManager.getColor("ScrollBar.shadow"));
+ g.drawLine(x + 1, y + h, x + w - 2, y + h);
+
+ // For the OceanTheme, draw the 3 lines in the middle.
+ if (theme instanceof OceanTheme)
+ {
+ g.setColor(thumbLightShadowColor);
+ int middle = y + h / 2;
+ g.drawLine(x + 4, middle - 2, x + w - 5, middle - 2);
+ g.drawLine(x + 4, middle, x + w - 5, middle);
+ g.drawLine(x + 4, middle + 2, x + w - 5, middle + 2);
+ g.setColor(UIManager.getColor("ScrollBar.highlight"));
+ g.drawLine(x + 5, middle - 1, x + w - 4, middle - 1);
+ g.drawLine(x + 5, middle + 1, x + w - 4, middle + 1);
+ g.drawLine(x + 5, middle + 3, x + w - 4, middle + 3);
+ }
+ }
+
+ /**
+ * Returns the minimum thumb size. For a free standing scroll bar the
+ * minimum size is <code>17 x 17</code> pixels, whereas for a non free
+ * standing scroll bar the minimum size is <code>15 x 15</code> pixels.
+ *
+ * @return The minimum thumb size.
+ */
+ protected Dimension getMinimumThumbSize()
+ {
+ Dimension retVal;
+ if (scrollbar != null)
+ {
+ if (isFreeStanding)
+ retVal = MIN_THUMB_SIZE_FREE_STANDING;
+ else
+ retVal = MIN_THUMB_SIZE;
+ }
+ else
+ retVal = new Dimension(0, 0);
+ return retVal;
+ }
+
+ /**
+ * Returns the <code>preferredSize</code> for the specified scroll bar.
+ * For a vertical scrollbar the height is the sum of the preferred heights
+ * of the buttons plus <code>30</code>. The width is fetched from the
+ * <code>UIManager</code> property <code>ScrollBar.width</code>.
+ *
+ * For horizontal scrollbars the width is the sum of the preferred widths
+ * of the buttons plus <code>30</code>. The height is fetched from the
+ * <code>UIManager</code> property <code>ScrollBar.height</code>.
+ *
+ * @param c the scrollbar for which to calculate the preferred size
+ *
+ * @return the <code>preferredSize</code> for the specified scroll bar
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ int height;
+ int width;
+ height = width = 0;
+
+ if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
+ {
+ width += incrButton.getPreferredSize().getWidth();
+ width += decrButton.getPreferredSize().getWidth();
+ width += 30;
+ height = UIManager.getInt("ScrollBar.width");
+ }
+ else
+ {
+ height += incrButton.getPreferredSize().getHeight();
+ height += decrButton.getPreferredSize().getHeight();
+ height += 30;
+ width = UIManager.getInt("ScrollBar.width");
+ }
+
+ Insets insets = scrollbar.getInsets();
+
+ height += insets.top + insets.bottom;
+ width += insets.left + insets.right;
+
+ return new Dimension(width, height);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java
new file mode 100644
index 000000000..3273908b3
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java
@@ -0,0 +1,483 @@
+/* MetalScrollButton.java
+ Copyright (C) 2005 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.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.basic.BasicArrowButton;
+
+/**
+ * A button used by the {@link MetalScrollBarUI}. The button appearance
+ * varies according to the button direction, whether or not it is part of a
+ * "free standing" scroll bar, and the current state of the button.
+ */
+public class MetalScrollButton extends BasicArrowButton
+{
+
+ /**
+ * The maximum size for buttons.
+ * @see #getMaximumSize()
+ */
+ private static Dimension maximumSize;
+
+ /** The width of the button. */
+ private int buttonWidth;
+
+ /**
+ * A flag that indicates whether the button is part of a free standing
+ * scroll bar. This affects how the border is drawn.
+ */
+ private boolean freeStanding;
+
+ /**
+ * Creates a new button.
+ *
+ * @param direction the direction (this should be one of {@link #NORTH},
+ * {@link #SOUTH}, {@link #EAST} and {@link #WEST}, but
+ * this is not enforced).
+ * @param width the button width.
+ * @param freeStanding a flag indicating whether the scroll button is free
+ * standing or not.
+ */
+ public MetalScrollButton(int direction, int width, boolean freeStanding)
+ {
+ super(direction);
+ buttonWidth = width;
+ this.freeStanding = freeStanding;
+ setFocusable(false);
+ }
+
+ /**
+ * Returns the button width.
+ *
+ * @return The button width.
+ */
+ public int getButtonWidth()
+ {
+ return buttonWidth;
+ }
+
+ /**
+ * Sets the free standing flag. This controls how the button border is
+ * drawn.
+ *
+ * @param freeStanding the new value of the flag.
+ */
+ public void setFreeStanding(boolean freeStanding)
+ {
+ this.freeStanding = freeStanding;
+ }
+
+ /**
+ * Paints the button.
+ *
+ * @param g the graphics device.
+ */
+ public void paint(Graphics g)
+ {
+ Rectangle bounds = SwingUtilities.getLocalBounds(this);
+
+ // fill the background
+ if (getModel().isPressed())
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ else
+ g.setColor(MetalLookAndFeel.getControl());
+ g.fillRect(0, 0, bounds.width, bounds.height);
+
+ paintArrow(g, bounds.width, bounds.height);
+
+ // paint a border manually - I tried using a real (custom) Border
+ // but couldn't get it to stay set for the button, something was
+ // overwriting it...
+ if (freeStanding)
+ {
+ if (direction == WEST)
+ paintWestBorderFreeStanding(g, bounds.width, bounds.height);
+ else if (direction == EAST)
+ paintEastBorderFreeStanding(g, bounds.width, bounds.height);
+ else if (direction == SOUTH)
+ paintSouthBorderFreeStanding(g, bounds.width, bounds.height);
+ else // asume NORTH
+ paintNorthBorderFreeStanding(g, bounds.width, bounds.height);
+ }
+ else
+ {
+ if (direction == WEST)
+ paintWestBorder(g, bounds.width, bounds.height);
+ else if (direction == EAST)
+ paintEastBorder(g, bounds.width, bounds.height);
+ else if (direction == SOUTH)
+ paintSouthBorder(g, bounds.width, bounds.height);
+ else // asume NORTH
+ paintNorthBorder(g, bounds.width, bounds.height);
+ }
+ }
+
+ private void paintArrow(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ g.setColor(MetalLookAndFeel.getBlack());
+ else
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+
+ if (direction == SOUTH)
+ {
+ int x = w / 2;
+ int y = h / 2 + 2;
+ for (int i = 1; i < 5; i++)
+ g.drawLine(x - i, y - i, x + i - 1, y - i);
+ }
+ else if (direction == EAST)
+ {
+ int x = w / 2 + 2;
+ int y = h / 2;
+ for (int i = 1; i < 5; i++)
+ g.drawLine(x - i, y - i, x - i, y + i - 1);
+ }
+ else if (direction == WEST)
+ {
+ int x = w / 2 - 3;
+ int y = h / 2;
+ for (int i = 1; i < 5; i++)
+ g.drawLine(x + i, y - i, x + i, y + i - 1);
+ }
+ else // assume NORTH
+ {
+ int x = w / 2;
+ int y = h / 2 - 3;
+ for (int i = 1; i < 5; i++)
+ g.drawLine(x - i, y + i, x + i - 1, y + i);
+ }
+ }
+ /**
+ * Paints the border for a button with a {@link #NORTH} direction that
+ * belongs to a free standing scroll bar.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintNorthBorderFreeStanding(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 2, 0);
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(2, h - 1, w - 2, h - 1);
+ g.drawLine(w - 2, 2, w - 2, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 1, 1, h - 2);
+ g.drawLine(1, 1, w - 3, 1);
+ g.drawLine(w - 1, 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 1, 1, h - 1);
+ g.drawLine(w - 2, 1, w - 2, 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(w - 1, 0, w - 1, h - 1);
+ g.drawLine(0, 0, 0, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #SOUTH} direction that
+ * belongs to a free standing scroll bar.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintSouthBorderFreeStanding(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 2, 0);
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(2, h - 1, w - 2, h - 1);
+ g.drawLine(w - 2, 2, w - 2, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 1, 1, h - 1);
+ g.drawLine(1, 1, w - 1, 1);
+ g.drawLine(w - 1, 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 1, 1, h - 1);
+ g.drawLine(w - 1, 1, w - 1, 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, h - 1, w - 1, h - 1);
+ g.drawLine(w - 1, 0, w - 1, h - 1);
+ g.drawLine(0, 0, 0, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with an {@link #EAST} direction that
+ * belongs to a free standing scroll bar.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintEastBorderFreeStanding(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 2, 0);
+ g.drawLine(w - 2, 0, w - 2, h - 2);
+ g.drawLine(0, h - 2, w - 2, h - 2);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(0, 1, w - 1, 1);
+ g.drawLine(w - 1, 1, w - 1, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(w - 2, 1, w - 2, 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(w - 1, 0, w - 1, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #WEST} direction that
+ * belongs to a free standing scroll bar.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintWestBorderFreeStanding(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(0, 0, 0, h - 2);
+ g.drawLine(0, h - 2, w - 1, h - 2);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 1, w - 1, 1);
+ g.drawLine(1, 1, 1, h - 1);
+ g.drawLine(1, h - 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 2, 1, h - 2);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #NORTH} direction that
+ * belongs to a scroll bar that is not free standing.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintNorthBorder(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, 0, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 0, 1, h - 1);
+ g.drawLine(1, 0, w - 1, 0);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, 0, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #SOUTH} direction that
+ * belongs to a scroll bar that is not free standing.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintSouthBorder(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, 0, h - 1);
+ g.drawLine(0, h - 1, w - 1, h - 1);
+
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(1, 0, 1, h - 1);
+ g.drawLine(1, 0, w - 1, 0);
+
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(1, h - 1, 1, h - 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, 0, h - 1);
+ }
+ }
+
+ /**
+ * Paints the border for a button with an {@link #EAST} direction that
+ * belongs to a scroll bar that is not free standing.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintEastBorder(Graphics g, int w, int h)
+ {
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, w - 1, 0);
+ g.drawLine(w - 1, 2, w - 1, h - 1);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(0, 1, w - 2, 1);
+ g.drawLine(0, 1, 0, h - 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, w - 1, 0);
+ }
+ }
+
+ /**
+ * Paints the border for a button with a {@link #WEST} direction that
+ * belongs to a scroll bar that is not free standing.
+ *
+ * @param g the graphics device.
+ * @param w the button width.
+ * @param h the button height.
+ */
+ private void paintWestBorder(Graphics g, int w, int h)
+ {
+ Rectangle bounds = SwingUtilities.getLocalBounds(this);
+ if (isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControlDarkShadow());
+ g.drawLine(0, 0, bounds.width - 1, 0);
+ g.setColor(MetalLookAndFeel.getControlHighlight());
+ g.drawLine(0, 1, bounds.width - 1, 1);
+ g.drawLine(0, 1, 0, bounds.height - 1);
+ }
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlDisabled());
+ g.drawLine(0, 0, bounds.width - 1, 0);
+ }
+ }
+
+ /**
+ * Returns the preferred size for the button, which varies depending on
+ * the direction of the button and whether or not it is free standing.
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize()
+ {
+ int adj = 1;
+ if (!freeStanding)
+ adj = 2;
+
+ if (direction == EAST)
+ return new Dimension(buttonWidth - adj, buttonWidth);
+ else if (direction == WEST)
+ return new Dimension(buttonWidth - 2, buttonWidth);
+ else if (direction == SOUTH)
+ return new Dimension(buttonWidth, buttonWidth - adj);
+ else // assume NORTH
+ return new Dimension(buttonWidth, buttonWidth - 2);
+ }
+
+ /**
+ * Returns the minimum size for the button.
+ *
+ * @return The minimum size for the button.
+ */
+ public Dimension getMinimumSize()
+ {
+ return getPreferredSize();
+ }
+
+ /**
+ * Returns the maximum size for the button.
+ *
+ * @return <code>Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)</code>.
+ */
+ public Dimension getMaximumSize()
+ {
+ if (maximumSize == null)
+ maximumSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ return maximumSize;
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java
new file mode 100644
index 000000000..09a47c300
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java
@@ -0,0 +1,159 @@
+/* MetalScrollPaneUI.java
+ Copyright (C) 2005 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.beans.PropertyChangeListener;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicScrollPaneUI;
+
+/**
+ * A UI delegate for the {@link JScrollPane} component.
+ */
+public class MetalScrollPaneUI
+ extends BasicScrollPaneUI
+{
+ /**
+ * Constructs a new instance of <code>MetalScrollPaneUI</code>.
+ */
+ public MetalScrollPaneUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a shared instance of <code>MetalScrollPaneUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A shared instance of <code>MetalScrollPaneUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalScrollPaneUI();
+ }
+
+ /**
+ * Configures the specified component appropriate for the look and feel.
+ * This method is invoked when the ComponentUI instance is being installed
+ * as the UI delegate on the specified component. This method should
+ * completely configure the component for the look and feel,
+ * including the following:
+ * 1. Install any default property values for color, fonts, borders,
+ * icons, opacity, etc. on the component. Whenever possible, property
+ * values initialized by the client program should not be overridden.
+ * 2. Install a LayoutManager on the component if necessary.
+ * 3. Create/add any required sub-components to the component.
+ * 4. Create/install event listeners on the component.
+ * 5. Create/install a PropertyChangeListener on the component in order
+ * to detect and respond to component property changes appropriately.
+ * 6. Install keyboard UI (mnemonics, traversal, etc.) on the component.
+ * 7. Initialize any appropriate instance data.
+ *
+ * @param c - the component to install the ui on
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ JScrollBar hsb = scrollpane.getHorizontalScrollBar();
+ hsb.putClientProperty(MetalScrollBarUI.FREE_STANDING_PROP, Boolean.FALSE);
+ JScrollBar vsb = scrollpane.getVerticalScrollBar();
+ vsb.putClientProperty(MetalScrollBarUI.FREE_STANDING_PROP, Boolean.FALSE);
+ }
+
+ /**
+ * Reverses configuration which was done on the specified component
+ * during installUI. This method is invoked when this UIComponent
+ * instance is being removed as the UI delegate for the specified
+ * component. This method should undo the configuration performed in
+ * installUI, being careful to leave the JComponent instance in a
+ * clean state (no extraneous listeners, look-and-feel-specific property
+ * objects, etc.). This should include the following:
+ * 1. Remove any UI-set borders from the component.
+ * 2. Remove any UI-set layout managers on the component.
+ * 3. Remove any UI-added sub-components from the component.
+ * 4. Remove any UI-added event/property listeners from the component.
+ * 5. Remove any UI-installed keyboard UI from the component.
+ * 6. Nullify any allocated instance data objects to allow for GC.
+ *
+ * @param c - the component to uninstall the ui on
+ */
+ public void uninstallUI(JComponent c)
+ {
+ JScrollBar hsb = scrollpane.getHorizontalScrollBar();
+ hsb.putClientProperty(MetalScrollBarUI.FREE_STANDING_PROP, null);
+ JScrollBar vsb = scrollpane.getVerticalScrollBar();
+ vsb.putClientProperty(MetalScrollBarUI.FREE_STANDING_PROP, null);
+ super.uninstallUI(c);
+ }
+
+ /**
+ * Installs listeners on scrollPane
+ *
+ * @param scrollPane - the component to install the listeners on
+ */
+ public void installListeners(JScrollPane scrollPane)
+ {
+ super.installListeners(scrollPane);
+ }
+
+ /**
+ * Uninstalls listeners on scrollPane
+ *
+ * @param scrollPane - the component to uninstall the listeners on
+ */
+ public void uninstallListeners(JScrollPane scrollPane)
+ {
+ super.uninstallListeners(scrollPane);
+ }
+
+ /**
+ * TODO
+ *
+ * @return TODO
+ */
+ protected PropertyChangeListener createScrollBarSwapListener()
+ {
+ // FIXME: Anything else to do here?
+ return super.createPropertyChangeListener();
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java
new file mode 100644
index 000000000..8afa98c97
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java
@@ -0,0 +1,131 @@
+/* MetalSeparatorUI.java
+ Copyright (C) 2005 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.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.JComponent;
+import javax.swing.JSeparator;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicSeparatorUI;
+
+/**
+ * A UI delegate for the {@link JSeparator} component.
+ */
+public class MetalSeparatorUI
+ extends BasicSeparatorUI
+{
+
+ // FIXME: maybe replace by a Map of instances when this becomes stateful
+ /** The shared UI instance for MetalSeparatorUIs */
+ private static MetalSeparatorUI instance;
+
+ /**
+ * Constructs a new instance of <code>MetalSeparatorUI</code>.
+ */
+ public MetalSeparatorUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a shared instance of <code>MetalSeparatorUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A shared instance of <code>MetalSeparatorUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ if (instance == null)
+ instance = new MetalSeparatorUI();
+ return instance;
+ }
+
+ /**
+ * The separator is made of two lines. The top line will be
+ * the Metal theme color separatorForeground (or left line if it's vertical).
+ * The bottom or right line will be the Metal theme color
+ * separatorBackground.
+ * The two lines will
+ * be centered inside the bounds box. If the separator is horizontal,
+ * then it will be vertically centered, or if it's vertical, it will
+ * be horizontally centered.
+ *
+ * @param g The Graphics object to paint with
+ * @param c The JComponent to paint.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ Rectangle r = new Rectangle();
+ SwingUtilities.calculateInnerArea(c, r);
+ Color saved = g.getColor();
+ Color c1 = UIManager.getColor("Separator.foreground");
+ Color c2 = UIManager.getColor("Separator.background");
+ JSeparator s;
+ if (c instanceof JSeparator)
+ s = (JSeparator) c;
+ else
+ return;
+
+ if (s.getOrientation() == JSeparator.HORIZONTAL)
+ {
+ int midAB = r.height / 2;
+ g.setColor(c1);
+ g.drawLine(r.x, r.y + midAB - 1, r.x + r.width, r.y + midAB - 1);
+
+ g.setColor(c2);
+ g.fillRect(r.x, r.y + midAB, r.x + r.width, r.y + midAB);
+ }
+ else
+ {
+ int midAD = r.height / 2 + r.y;
+ g.setColor(c1);
+ g.drawLine(r.x, r.y, r.x, r.y + r.height);
+
+ g.setColor(c2);
+ g.fillRect(r.x + midAD, r.y + r.height, r.x + midAD, r.y + r.height);
+ }
+ g.setColor(saved);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java
new file mode 100644
index 000000000..e85c32462
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java
@@ -0,0 +1,475 @@
+/* MetalSliderUI.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.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.Icon;
+import javax.swing.JComponent;
+import javax.swing.JSlider;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicGraphicsUtils;
+import javax.swing.plaf.basic.BasicSliderUI;
+
+/**
+ * A UI delegate for the {@link JSlider} component.
+ */
+public class MetalSliderUI extends BasicSliderUI
+{
+ /**
+ * A property change handler that updates the rendered component in response
+ * to specific property change events. This custom handler is used to
+ * intercept the "JSlider.isFilled" property, which is only recognised by
+ * the {@link MetalLookAndFeel}.
+ */
+ protected class MetalPropertyListener
+ extends BasicSliderUI.PropertyChangeHandler
+ {
+ /**
+ * Creates a new listener.
+ */
+ protected MetalPropertyListener()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Handles property change events. Events with the name "JSlider.isFilled"
+ * are handled here, and other events are passed to the superclass.
+ *
+ * @param e the property change event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(SLIDER_FILL))
+ {
+ Boolean b = (Boolean) e.getNewValue();
+ if (b == null)
+ filledSlider = false;
+ else
+ filledSlider = b.booleanValue();
+ }
+ else
+ super.propertyChange(e);
+ }
+ }
+
+ /** The thumb color (unused, because an icon is used to draw the thumb). */
+ protected static Color thumbColor;
+
+ /**
+ * The highlight color used for drawing the track rect when the slider is
+ * enabled.
+ */
+ protected static Color highlightColor;
+
+ /**
+ * The shadow color used for drawing the track rect when the slider is
+ * enabled.
+ */
+ protected static Color darkShadowColor;
+
+ /** The track width. */
+ protected static int trackWidth = UIManager.getInt("Slider.trackWidth");
+
+ /** The length of the major tick marks. */
+ protected static int tickLength = UIManager.getInt("Slider.majorTickLength");
+
+ /** The icon used for the thumb control of horizontally oriented sliders. */
+ protected static Icon horizThumbIcon = UIManager.getIcon(
+ "Slider.horizontalThumbIcon");
+
+ /** The icon used for the thumb control of vertically oriented sliders. */
+ protected static Icon vertThumbIcon = UIManager.getIcon(
+ "Slider.verticalThumbIcon");
+
+ /** The gap between the track and the tick marks. */
+ protected final int TICK_BUFFER = 4;
+
+ /** A key to look up the filledSlider setting in the {@link UIManager}. */
+ protected final String SLIDER_FILL = "JSlider.isFilled";
+
+ /**
+ * A flag that controls whether or not the track is filled up to the value
+ * of the slider.
+ */
+ protected boolean filledSlider;
+
+ /**
+ * Constructs a new instance.
+ */
+ public MetalSliderUI()
+ {
+ super(null);
+ filledSlider = UIManager.getBoolean(SLIDER_FILL);
+ darkShadowColor = MetalLookAndFeel.getControlDarkShadow();
+ highlightColor = MetalLookAndFeel.getControlHighlight();
+ }
+
+ /**
+ * Returns a new instance of <code>MetalSliderUI</code>.
+ *
+ * @param component the component (ignored).
+ *
+ * @return A new instance of <code>MetalSliderUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalSliderUI();
+ }
+
+ /**
+ * Installs the default for this UI delegate in the supplied component.
+ *
+ * @param c the component.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ Boolean b = (Boolean) c.getClientProperty(SLIDER_FILL);
+ if (b != null)
+ filledSlider = b.booleanValue();
+ }
+
+ /**
+ * Creates a property change listener for the slider.
+ *
+ * @param slider the slider.
+ *
+ * @return A new instance of {@link MetalPropertyListener}.
+ */
+ protected PropertyChangeListener createPropertyChangeListener(JSlider slider)
+ {
+ return new MetalPropertyListener();
+ }
+
+ /**
+ * Paints the thumb icon for the slider.
+ *
+ * @param g the graphics device.
+ */
+ public void paintThumb(Graphics g)
+ {
+ Color save = g.getColor();
+ g.setColor(thumbColor);
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ horizThumbIcon.paintIcon(slider, g, thumbRect.x, thumbRect.y);
+ else
+ vertThumbIcon.paintIcon(slider, g, thumbRect.x, thumbRect.y);
+ g.setColor(save);
+ }
+
+ /**
+ * Paints the track along which the thumb control moves.
+ *
+ * @param g the graphics device.
+ */
+ public void paintTrack(Graphics g)
+ {
+ Color shadowColor = MetalLookAndFeel.getControlShadow();
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ int trackX = trackRect.x;
+ int trackY = trackRect.y + (trackRect.height - getTrackWidth()) / 2;
+ int trackW = trackRect.width;
+ int trackH = getTrackWidth();
+
+ // draw border
+ if (slider.isEnabled())
+ BasicGraphicsUtils.drawEtchedRect(g, trackX, trackY, trackW, trackH,
+ darkShadowColor, shadowColor, darkShadowColor, highlightColor);
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawRect(trackX, trackY, trackW - 2, trackH - 2);
+ }
+
+ // fill track (if required)
+ if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
+ {
+ if (slider.isEnabled())
+ {
+ int xPos = xPositionForValue(slider.getValue());
+ int x = slider.getInverted() ? xPos : trackRect.x;
+ int w = slider.getInverted() ? trackX + trackW - xPos
+ : xPos - trackRect.x;
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 1, trackY + 1, x + w - 3, trackY + 1);
+ g.setColor(UIManager.getColor("Slider.altTrackColor"));
+ g.drawLine(x + 1, trackY + 2, x + w - 3, trackY + 2);
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x + 1, trackY + 3, x + w - 3, trackY + 3);
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ g.drawLine(x + 1, trackY + 4, x + w - 3, trackY + 4);
+ }
+ }
+ else if (filledSlider)
+ {
+ int xPos = xPositionForValue(slider.getValue());
+ int x = slider.getInverted() ? xPos : trackRect.x;
+ int w = slider.getInverted() ? trackX + trackW - xPos
+ : xPos - trackRect.x;
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.fillRect(x + 1, trackY + 1, w - 3, getTrackWidth() - 3);
+ if (slider.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(x + 1, trackY + 1, x + w - 3, trackY + 1);
+ g.drawLine(x + 1, trackY + 1, x + 1,
+ trackY + getTrackWidth() - 3);
+ }
+ }
+ }
+ else
+ {
+ int trackX = trackRect.x + (trackRect.width - getTrackWidth()) / 2;
+ int trackY = trackRect.y;
+ int trackW = getTrackWidth();
+ int trackH = trackRect.height;
+ if (slider.isEnabled())
+ BasicGraphicsUtils.drawEtchedRect(g, trackX, trackY, trackW, trackH,
+ darkShadowColor, shadowColor, darkShadowColor, highlightColor);
+ else
+ {
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawRect(trackX, trackY, trackW - 2, trackH - 2);
+ }
+
+ // Fill track if necessary.
+ if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
+ {
+ if (slider.isEnabled())
+ {
+ int yPos = yPositionForValue(slider.getValue());
+ int y = slider.getInverted() ? trackY : yPos;
+ int h = slider.getInverted() ? yPos - trackY
+ : trackY + trackH - yPos;
+
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(trackX + 1, y + 1, trackX + 1, y + h - 3);
+ g.setColor(UIManager.getColor("Slider.altTrackColor"));
+ g.drawLine(trackX + 2, y + 1, trackX + 2, y + h - 3);
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(trackX + 3, y + 1, trackX + 3, y + h - 3);
+ g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
+ g.drawLine(trackX + 4, y + 1, trackX + 4, y + h - 3);
+ }
+ }
+ else if (filledSlider)
+ {
+ int yPos = yPositionForValue(slider.getValue());
+ int y = slider.getInverted() ? trackY : yPos;
+ int h = slider.getInverted() ? yPos - trackY
+ : trackY + trackH - yPos;
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.fillRect(trackX + 1, y + 1, getTrackWidth() - 3, h - 3);
+ if (slider.isEnabled())
+ {
+ g.setColor(MetalLookAndFeel.getControl());
+ g.drawLine(trackX + 1, y + 1, trackX + trackW - 3, y + 1);
+ g.drawLine(trackX + 1, y + 1, trackX + 1, y + h - 3);
+ }
+ }
+ }
+ }
+
+ /**
+ * Draws the focus rectangle for the slider. The Metal look and feel
+ * indicates that the {@link JSlider} has the focus by changing the color of
+ * the thumb control - this is handled elsewhere and so this method is empty
+ * (it overrides the method in the {@link BasicSliderUI} class to prevent
+ * a default focus highlight from being drawn).
+ *
+ * @param g the graphics device.
+ */
+ public void paintFocus(Graphics g)
+ {
+ thumbColor = getFocusColor();
+ paintThumb(g);
+ }
+
+ /**
+ * Returns the size of the thumb icon.
+ *
+ * @return The size of the thumb icon.
+ */
+ protected Dimension getThumbSize()
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ return new Dimension(horizThumbIcon.getIconWidth(),
+ horizThumbIcon.getIconHeight());
+ else
+ return new Dimension(vertThumbIcon.getIconWidth(),
+ vertThumbIcon.getIconHeight());
+ }
+
+ /**
+ * Returns the length of the major tick marks.
+ *
+ * @return The length of the major tick marks.
+ */
+ public int getTickLength()
+ {
+ int len = tickLength + TICK_BUFFER + 1;
+ if (slider.getOrientation() == JSlider.VERTICAL)
+ len += 2;
+ return len;
+ }
+
+ /**
+ * Returns the track width.
+ *
+ * @return The track width.
+ */
+ protected int getTrackWidth()
+ {
+ return trackWidth;
+ }
+
+ /**
+ * Returns the track length.
+ *
+ * @return The track length.
+ */
+ protected int getTrackLength()
+ {
+ return slider.getOrientation() == JSlider.HORIZONTAL
+ ? tickRect.width : tickRect.height;
+ }
+
+ /**
+ * Returns the thumb overhang.
+ *
+ * @return The thumb overhang.
+ */
+ protected int getThumbOverhang()
+ {
+ // FIXME: for what might this method be used?
+ return 0;
+ }
+
+ protected void scrollDueToClickInTrack(int dir)
+ {
+ // FIXME: for what might this method be overridden?
+ super.scrollDueToClickInTrack(dir);
+ }
+
+ /**
+ * Paints the minor ticks for a slider with a horizontal orientation.
+ *
+ * @param g the graphics device.
+ * @param tickBounds the tick bounds.
+ * @param x the x value for the tick.
+ */
+ protected void paintMinorTickForHorizSlider(Graphics g, Rectangle tickBounds,
+ int x)
+ {
+ // Note the incoming 'g' has a translation in place to get us to the
+ // start of the tick rect already...
+ if (slider.isEnabled())
+ g.setColor(slider.getForeground());
+ else
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength / 2);
+ }
+
+ /**
+ * Paints the major ticks for a slider with a horizontal orientation.
+ *
+ * @param g the graphics device.
+ * @param tickBounds the tick bounds.
+ * @param x the x value for the tick.
+ */
+ protected void paintMajorTickForHorizSlider(Graphics g, Rectangle tickBounds,
+ int x)
+ {
+ // Note the incoming 'g' has a translation in place to get us to the
+ // start of the tick rect already...
+ if (slider.isEnabled())
+ g.setColor(slider.getForeground());
+ else
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength - 1);
+ }
+
+ /**
+ * Paints the minor ticks for a slider with a vertical orientation.
+ *
+ * @param g the graphics device.
+ * @param tickBounds the tick bounds.
+ * @param y the y value for the tick.
+ */
+ protected void paintMinorTickForVertSlider(Graphics g, Rectangle tickBounds,
+ int y)
+ {
+ // Note the incoming 'g' has a translation in place to get us to the
+ // start of the tick rect already...
+ if (slider.isEnabled())
+ g.setColor(slider.getForeground());
+ else
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(TICK_BUFFER, y, TICK_BUFFER + tickLength / 2, y);
+ }
+
+ /**
+ * Paints the major ticks for a slider with a vertical orientation.
+ *
+ * @param g the graphics device.
+ * @param tickBounds the tick bounds.
+ * @param y the y value for the tick.
+ */
+ protected void paintMajorTickForVertSlider(Graphics g, Rectangle tickBounds,
+ int y)
+ {
+ // Note the incoming 'g' has a translation in place to get us to the
+ // start of the tick rect already...
+ if (slider.isEnabled())
+ g.setColor(slider.getForeground());
+ else
+ g.setColor(MetalLookAndFeel.getControlShadow());
+ g.drawLine(TICK_BUFFER, y, TICK_BUFFER + tickLength, y);
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java
new file mode 100644
index 000000000..051499834
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java
@@ -0,0 +1,264 @@
+/* MetalSplitPaneDivider.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.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+
+import javax.swing.JButton;
+import javax.swing.JSplitPane;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.plaf.basic.BasicSplitPaneDivider;
+
+/**
+ * The divider that is used by the {@link MetalSplitPaneUI}.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+class MetalSplitPaneDivider extends BasicSplitPaneDivider
+{
+ /**
+ * The button pixel data, as indices into the colors array below.
+ * This is the version for 'left' buttons.
+ *
+ * This is slightly different from the icon in Sun's version, it is
+ * one pixel smaller and is more consistent with BUTTON_SPRITE_R.
+ */
+ static final byte[][] BUTTON_SPRITE_L = {{ 0, 0, 0, 2, 0, 0, 0, 0 },
+ { 0, 0, 2, 1, 1, 0, 0, 0 },
+ { 0, 2, 1, 1, 1, 1, 0, 0 },
+ { 2, 1, 1, 1, 1, 1, 1, 0 },
+ { 0, 3, 3, 3, 3, 3, 3, 3 }};
+
+ /**
+ * The button pixel data, as indices into the colors array below.
+ * This is the version for 'right' buttons.
+ */
+ static final byte[][] BUTTON_SPRITE_R = {{ 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 0, 1, 1, 1, 1, 1, 1, 3 },
+ { 0, 0, 1, 1, 1, 1, 3, 0 },
+ { 0, 0, 0, 1, 1, 3, 0, 0 },
+ { 0, 0, 0, 0, 3, 0, 0, 0 }};
+
+ private class MetalOneTouchButton
+ extends JButton
+ {
+ /**
+ * Denotes a left button.
+ */
+ static final int LEFT = 0;
+
+ /**
+ * Denotes a right button.
+ */
+ static final int RIGHT = 1;
+
+ /**
+ * The colors for the button sprite.
+ */
+ private Color[] colors;
+
+ /**
+ * Either LEFT or RIGHT.
+ */
+ private int direction;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param dir either LEFT or RIGHT
+ */
+ MetalOneTouchButton(int dir)
+ {
+ direction = dir;
+ colors = new Color[4];
+ }
+
+ /**
+ * Never allow borders.
+ */
+ public void setBorder(Border b)
+ {
+ }
+
+ /**
+ * Never allow focus traversal.
+ */
+ public boolean isFocusTraversable()
+ {
+ return false;
+ }
+
+ /**
+ * Paints the one touch button.
+ */
+ public void paint(Graphics g)
+ {
+ if (splitPane != null)
+ {
+ // Update colors here to reflect dynamic changes to the theme.
+ colors[0] = getBackground();
+ colors[1] = MetalLookAndFeel.getPrimaryControlDarkShadow();
+ colors[2] = MetalLookAndFeel.getPrimaryControlInfo();
+ colors[3] = MetalLookAndFeel.getPrimaryControlHighlight();
+
+ // Fill background.
+ g.setColor(getBackground());
+ g.fillRect(0, 0, getWidth(), getHeight());
+
+ // Pressed buttons have slightly different color mapping.
+ if (getModel().isPressed())
+ colors[1] = colors[2];
+
+ byte[][] sprite;
+ if (direction == LEFT)
+ sprite = BUTTON_SPRITE_L;
+ else
+ sprite = BUTTON_SPRITE_R;
+
+ if (orientation == JSplitPane.VERTICAL_SPLIT)
+ {
+ // Draw the sprite as it is.
+ for (int y = 0; y < sprite.length; y++)
+ {
+ byte[] line = sprite[y];
+ for (int x = 0; x < line.length; x++)
+ {
+ int c = line[x];
+ if (c != 0)
+ {
+ g.setColor(colors[c]);
+ g.fillRect(x + 1, y + 1, 1, 1);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Draw the sprite with swapped X and Y axis.
+ for (int y = 0; y < sprite.length; y++)
+ {
+ byte[] line = sprite[y];
+ for (int x = 0; x < line.length; x++)
+ {
+ int c = line[x];
+ if (c != 0)
+ {
+ g.setColor(colors[c]);
+ g.fillRect(y + 1, x + 1, 1, 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /** The dark color in the pattern. */
+ Color dark;
+
+ /** The light color in the pattern. */
+ Color light;
+
+ /** The JSplitPane the divider is on. */
+ JSplitPane splitPane;
+
+ /** The split pane orientation. */
+ int orientation;
+
+ /**
+ * Creates a new instance of <code>MetalSplitPaneDivider</code>.
+ *
+ * @param ui the <code>MetalSplitPaneUI</code> that uses this divider
+ */
+ public MetalSplitPaneDivider(MetalSplitPaneUI ui, Color light, Color dark)
+ {
+ super(ui);
+ this.splitPane = super.splitPane;
+ this.orientation = super.orientation;
+ this.light = light;
+ this.dark = dark;
+ }
+
+ /**
+ * Paints the divider.
+ *
+ * @param g the <code>Graphics</code> context to use for painting
+ */
+ public void paint(Graphics g)
+ {
+ Dimension s = getSize();
+
+ if (splitPane.hasFocus())
+ {
+ g.setColor(UIManager.getColor("SplitPane.dividerFocusColor"));
+ g.fillRect(0, 0, s.width, s.height);
+ }
+
+ // Paint border if one exists.
+ Border border = getBorder();
+ if (border != null)
+ border.paintBorder(this, g, 0, 0, s.width, s.height);
+
+ Insets i = getInsets();
+ MetalUtils.fillMetalPattern(splitPane, g, i.left + 2, i.top + 2,
+ s.width - i.left - i.right - 4,
+ s.height - i.top - i.bottom - 4,
+ light, dark);
+ super.paint(g);
+ }
+
+ protected JButton createLeftOneTouchButton()
+ {
+ JButton b = new MetalOneTouchButton(MetalOneTouchButton.LEFT);
+ b.setMinimumSize(new Dimension(ONE_TOUCH_SIZE, ONE_TOUCH_SIZE));
+ b.setRequestFocusEnabled(false);
+ return b;
+ }
+
+ protected JButton createRightOneTouchButton()
+ {
+ JButton b = new MetalOneTouchButton(MetalOneTouchButton.RIGHT);
+ b.setMinimumSize(new Dimension(ONE_TOUCH_SIZE, ONE_TOUCH_SIZE));
+ b.setRequestFocusEnabled(false);
+ return b;
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java
new file mode 100644
index 000000000..5b8f2127e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java
@@ -0,0 +1,89 @@
+/* MetalSplitPaneUI.java
+ Copyright (C) 2005 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 javax.swing.JComponent;
+import javax.swing.JSplitPane;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicSplitPaneDivider;
+import javax.swing.plaf.basic.BasicSplitPaneUI;
+
+/**
+ * A UI delegate for the {@link JSplitPane} component.
+ */
+public class MetalSplitPaneUI extends BasicSplitPaneUI
+{
+ /**
+ * Constructs a new instance of <code>MetalSplitPaneUI</code>.
+ */
+ public MetalSplitPaneUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new instance of <code>MetalSplitPaneUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A new instance of <code>MetalSplitPaneUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalSplitPaneUI();
+ }
+
+ /**
+ * Returns the divider that is used by the <code>JSplitPane</code>.
+ *
+ * The divider returned by this method is a {@link BasicSplitPaneDivider}
+ * that is drawn using the Metal look.
+ *
+ * @return the default divider to use for <code>JSplitPane</code>s.
+ */
+ public BasicSplitPaneDivider createDefaultDivider()
+ {
+ Color light = UIManager.getColor("SplitPane.highlight");
+ Color dark = UIManager.getColor("SplitPane.darkShadow");
+ return new MetalSplitPaneDivider(this, light, dark);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
new file mode 100644
index 000000000..77705ba0e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java
@@ -0,0 +1,1269 @@
+/* MetalTabbedPaneUI.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.Graphics;
+import java.awt.LayoutManager;
+import java.awt.Rectangle;
+
+import javax.swing.JComponent;
+import javax.swing.JTabbedPane;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.basic.BasicTabbedPaneUI;
+
+/**
+ * A UI delegate for the {@link JTabbedPane} component.
+ */
+public class MetalTabbedPaneUI extends BasicTabbedPaneUI
+{
+
+ /**
+ * A {@link LayoutManager} responsible for placing all the tabs and the
+ * visible component inside the {@link JTabbedPane}. This class is only used
+ * for {@link JTabbedPane#WRAP_TAB_LAYOUT}.
+ *
+ * @specnote Apparently this class was intended to be protected,
+ * but was made public by a compiler bug and is now
+ * public for compatibility.
+ */
+ public class TabbedPaneLayout
+ extends BasicTabbedPaneUI.TabbedPaneLayout
+ {
+ /**
+ * Creates a new instance of the layout manager.
+ */
+ public TabbedPaneLayout()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Overridden to do nothing, because tab runs are not rotated in the
+ * {@link MetalLookAndFeel}.
+ *
+ * @param tabPlacement the tab placement (one of {@link #TOP},
+ * {@link #BOTTOM}, {@link #LEFT} or {@link #RIGHT}).
+ * @param selectedRun the index of the selected run.
+ */
+ protected void rotateTabRuns(int tabPlacement, int selectedRun)
+ {
+ // do nothing, because tab runs are not rotated in the MetalLookAndFeel
+ }
+
+ /**
+ * Overridden to do nothing, because the selected tab does not have extra
+ * padding in the {@link MetalLookAndFeel}.
+ *
+ * @param tabPlacement the tab placement (one of {@link #TOP},
+ * {@link #BOTTOM}, {@link #LEFT} or {@link #RIGHT}).
+ * @param selectedIndex the index of the selected tab.
+ */
+ protected void padSelectedTab(int tabPlacement, int selectedIndex)
+ {
+ // do nothing, because the selected tab does not have extra padding in
+ // the MetalLookAndFeel
+ }
+
+ /**
+ * Overridden because tab runs are only normalized for TOP and BOTTOM
+ * tab placement in the Metal L&F.
+ */
+ protected void normalizeTabRuns(int tabPlacement, int tabCount, int start,
+ int max)
+ {
+ if (tabPlacement == TOP || tabPlacement == BOTTOM)
+ super.normalizeTabRuns(tabPlacement, tabCount, start, max);
+ }
+ }
+
+ /**
+ * The minimum tab width.
+ */
+ protected int minTabWidth;
+
+ /**
+ * The color for the selected tab.
+ */
+ protected Color selectColor;
+
+ /**
+ * The color for a highlighted selected tab.
+ */
+ protected Color selectHighlight;
+
+ /**
+ * The background color used for the tab area.
+ */
+ protected Color tabAreaBackground;
+
+ /** The graphics to draw the highlight below the tab. */
+ private Graphics hg;
+
+ /**
+ * Indicates if the tabs are having their background filled.
+ */
+ private boolean tabsOpaque;
+
+ /**
+ * Constructs a new instance of MetalTabbedPaneUI.
+ */
+ public MetalTabbedPaneUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns an instance of MetalTabbedPaneUI.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return an instance of MetalTabbedPaneUI
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalTabbedPaneUI();
+ }
+
+ /**
+ * Creates and returns an instance of {@link TabbedPaneLayout}.
+ *
+ * @return A layout manager used by this UI delegate.
+ */
+ protected LayoutManager createLayoutManager()
+ {
+ return (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
+ ? new MetalTabbedPaneUI.TabbedPaneLayout()
+ : super.createLayoutManager();
+ }
+
+ /**
+ * Paints the border for a single tab.
+ *
+ * @param g the graphics device.
+ * @param tabPlacement the tab placement ({@link #TOP}, {@link #LEFT},
+ * {@link #BOTTOM} or {@link #RIGHT}).
+ * @param tabIndex the index of the tab to draw the border for.
+ * @param x the x-coordinate for the tab's bounding rectangle.
+ * @param y the y-coordinate for the tab's bounding rectangle.
+ * @param w the width for the tab's bounding rectangle.
+ * @param h the height for the tab's bounding rectangle.
+ * @param isSelected indicates whether or not the tab is selected.
+ */
+ protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
+ int x, int y, int w, int h, boolean isSelected)
+ {
+ int bottom = y + h - 1;
+ int right = x + w - 1;
+
+ switch (tabPlacement)
+ {
+ case LEFT:
+ paintLeftTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected);
+ break;
+ case BOTTOM:
+ paintBottomTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected);
+ break;
+ case RIGHT:
+ paintRightTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected);
+ break;
+ case TOP:
+ default:
+ paintTopTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected);
+ }
+ }
+
+ /**
+ * Paints the border for a tab assuming that the tab position is at the top
+ * ({@link #TOP}).
+ *
+ * @param tabIndex the tab index.
+ * @param g the graphics device.
+ * @param x the x-coordinate for the tab's bounding rectangle.
+ * @param y the y-coordinate for the tab's bounding rectangle.
+ * @param w the width for the tab's bounding rectangle.
+ * @param h the height for the tab's bounding rectangle.
+ * @param btm the y coordinate of the bottom border
+ * @param rght the x coordinate of the right border
+ * @param isSelected indicates whether the tab is selected.
+ */
+ protected void paintTopTabBorder(int tabIndex, Graphics g, int x, int y,
+ int w, int h, int btm, int rght, boolean isSelected)
+ {
+ int tabCount = tabPane.getTabCount();
+ int currentRun = getRunForTab(tabCount, tabIndex);
+ int right = w - 1;
+ int bottom = h - 1;
+
+ // Paint gap.
+ if (shouldFillGap(currentRun, tabIndex, x, y))
+ {
+ g.translate(x, y);
+ g.setColor(getColorForGap(currentRun, x, y + 1));
+ g.fillRect(1, 0, 5, 3);
+ g.fillRect(1, 3, 2, 2);
+ g.translate(-x, -y);
+ }
+
+ g.translate(x, y);
+
+ boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
+ Color oceanSelectedBorder =
+ UIManager.getColor("TabbedPane.borderHightlightColor");
+ if (isOcean && isSelected)
+ g.setColor(oceanSelectedBorder);
+ else
+ g.setColor(darkShadow);
+
+ // Slant
+ g.drawLine(1, 5, 6, 0);
+ // Top.
+ g.drawLine(6, 0, right, 0);
+ // Right.
+ int lastIndex = lastTabInRun(tabCount, currentRun);
+ if (tabIndex == lastIndex)
+ g.drawLine(right, 1, right, bottom);
+ // Left.
+ int selectedIndex = tabPane.getSelectedIndex();
+ if (isOcean && tabIndex - 1 == selectedIndex
+ && currentRun == getRunForTab(tabCount, selectedIndex))
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ if (tabIndex != tabRuns[runCount - 1])
+ {
+ if (isOcean && isSelected)
+ {
+ g.drawLine(0, 6, 0, bottom);
+ g.setColor(darkShadow);
+ g.drawLine(0, 0, 0, 5);
+ }
+ else
+ {
+ g.drawLine(0, 0, 0, bottom);
+ }
+ }
+ else
+ {
+ g.drawLine(0, 6, 0, bottom);
+ }
+
+ // Paint the highlight.
+ g.setColor(isSelected ? selectHighlight : highlight);
+ // Slant.
+ g.drawLine(1, 6, 6, 1);
+ // Top.
+ g.drawLine(6, 1, right, 1);
+ // Left.
+ g.drawLine(1, 6, 1, bottom);
+ int firstIndex = tabRuns[currentRun];
+ if (tabIndex == firstIndex && tabIndex != tabRuns[runCount - 1])
+ {
+ if (tabPane.getSelectedIndex() == tabRuns[currentRun + 1])
+ g.setColor(selectHighlight);
+ else
+ g.setColor(highlight);
+ g.drawLine(1, 0, 1, 4);
+ }
+
+ g.translate(-x, -y);
+ }
+
+ /**
+ * Paints the border for a tab assuming that the tab position is at the left
+ * ({@link #LEFT}).
+ *
+ * @param tabIndex the tab index.
+ * @param g the graphics device.
+ * @param x the x-coordinate for the tab's bounding rectangle.
+ * @param y the y-coordinate for the tab's bounding rectangle.
+ * @param w the width for the tab's bounding rectangle.
+ * @param h the height for the tab's bounding rectangle.
+ * @param btm ???
+ * @param rght ???
+ * @param isSelected indicates whether the tab is selected.
+ */
+ protected void paintLeftTabBorder(int tabIndex, Graphics g, int x, int y,
+ int w, int h, int btm, int rght, boolean isSelected)
+ {
+ g.translate(x, y);
+ int bottom = h - 1;
+ int right = w - 1;
+
+ int tabCount = tabPane.getTabCount();
+ int currentRun = getRunForTab(tabCount, tabIndex);
+ int firstIndex = tabRuns[currentRun];
+
+ // Paint the part of the above tab.
+ if (tabIndex != firstIndex && tabIndex > 0 && tabsOpaque)
+ {
+ Color c;
+ if (tabPane.getSelectedIndex() == tabIndex - 1)
+ c = selectColor;
+ else
+ c = getUnselectedBackground(tabIndex - 1);
+ g.setColor(c);
+ g.fillRect(2, 0, 4, 3);
+ g.drawLine(2, 3, 2, 3);
+ }
+
+ // Paint the highlight.
+ boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
+ if (isOcean)
+ {
+ g.setColor(isSelected ? selectHighlight : MetalLookAndFeel.getWhite());
+ }
+ else
+ {
+ g.setColor(isSelected ? selectHighlight : highlight);
+ }
+ // Slant.
+ g.drawLine(1, 6, 6, 1);
+ // Left.
+ g.drawLine(1, 6, 1, bottom);
+ // Top.
+ g.drawLine(6, 1, right, 1);
+ if (tabIndex != firstIndex)
+ {
+ if (isOcean)
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+ }
+ g.drawLine(1, 0, 1, 4);
+ }
+
+ // Paint border.
+ Color oceanSelectedBorder =
+ UIManager.getColor("TabbedPane.borderHightlightColor");
+ if (isOcean && isSelected)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ else
+ {
+ g.setColor(darkShadow);
+ }
+
+ // Slant.
+ g.drawLine(1, 5, 6, 0);
+ // Top.
+ g.drawLine(6, 0, right, 0);
+ // Bottom.
+ int lastIndex = lastTabInRun(tabCount, currentRun);
+ if (tabIndex == lastIndex)
+ {
+ g.drawLine(0, bottom, right, bottom);
+ }
+ // Left.
+ if (isOcean)
+ {
+ if (tabPane.getSelectedIndex() == tabIndex - 1)
+ {
+ g.drawLine(0, 6, 0, bottom);
+ if (tabIndex != firstIndex)
+ {
+ g.setColor(oceanSelectedBorder);
+ g.drawLine(0, 0, 0, 5);
+ }
+ }
+ else if (isSelected)
+ {
+ g.drawLine(0, 5, 0, bottom);
+ if (tabIndex != firstIndex)
+ {
+ g.setColor(darkShadow);
+ g.drawLine(0, 0, 0, 5);
+ }
+ }
+ else if (tabIndex != firstIndex)
+ {
+ g.drawLine(0, 0, 0, bottom);
+ }
+ else
+ {
+ g.drawLine(0, 6, 0, bottom);
+ }
+ }
+ else
+ {
+ if (tabIndex != firstIndex)
+ {
+ g.drawLine(0, 0, 0, bottom);
+ }
+ else
+ {
+ g.drawLine(0, 6, 0, bottom);
+ }
+ }
+
+ g.translate(-x, -y);
+ }
+
+ /**
+ * Paints the border for a tab assuming that the tab position is at the right
+ * ({@link #RIGHT}).
+ *
+ * @param tabIndex the tab index.
+ * @param g the graphics device.
+ * @param x the x-coordinate for the tab's bounding rectangle.
+ * @param y the y-coordinate for the tab's bounding rectangle.
+ * @param w the width for the tab's bounding rectangle.
+ * @param h the height for the tab's bounding rectangle.
+ * @param btm ???
+ * @param rght ???
+ * @param isSelected indicates whether the tab is selected.
+ */
+ protected void paintRightTabBorder(int tabIndex, Graphics g, int x, int y,
+ int w, int h, int btm, int rght, boolean isSelected)
+ {
+ g.translate(x, y);
+ int bottom = h - 1;
+ int right = w - 1;
+
+ int tabCount = tabPane.getTabCount();
+ int currentRun = getRunForTab(tabCount, tabIndex);
+ int firstIndex = tabRuns[currentRun];
+
+ // Paint part of the above tab.
+ if (tabIndex != firstIndex && tabIndex > 0 && tabsOpaque)
+ {
+ Color c;
+ if (tabPane.getSelectedIndex() == tabIndex - 1)
+ c = selectColor;
+ else
+ c = getUnselectedBackground(tabIndex - 1);
+ g.setColor(c);
+ g.fillRect(right - 5, 0, 5, 3);
+ g.fillRect(right - 2, 3, 2, 2);
+ }
+
+ // Paint highlight.
+ g.setColor(isSelected ? selectHighlight : highlight);
+
+ // Slant.
+ g.drawLine(right - 6, 1, right - 1, 6);
+ // Top.
+ g.drawLine(0, 1, right - 6, 1);
+ // Left.
+ if (! isSelected)
+ {
+ g.drawLine(0, 1, 0, bottom);
+ }
+
+ // Paint border.
+ boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
+ Color oceanSelectedBorder =
+ UIManager.getColor("TabbedPane.borderHightlightColor");
+ if (isOcean && isSelected)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ else
+ {
+ g.setColor(darkShadow);
+ }
+
+ // Bottom.
+ int lastIndex = lastTabInRun(tabCount, currentRun);
+ if (tabIndex == lastIndex)
+ {
+ g.drawLine(0, bottom, right, bottom);
+ }
+ // Slant.
+ if (isOcean && tabPane.getSelectedIndex() == tabIndex - 1)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ g.drawLine(right - 6, 0, right, 6);
+ // Top.
+ g.drawLine(0, 0, right - 6, 0);
+ // Right.
+ if (isOcean && isSelected)
+ {
+ g.drawLine(right, 6, right, bottom);
+ if (tabIndex != firstIndex)
+ {
+ g.setColor(darkShadow);
+ g.drawLine(right, 0, right, 5);
+ }
+ }
+ else if (isOcean && tabPane.getSelectedIndex() == tabIndex - 1)
+ {
+ if (tabIndex != firstIndex)
+ {
+ g.setColor(oceanSelectedBorder);
+ g.drawLine(right, 0, right, 6);
+ }
+ g.setColor(darkShadow);
+ g.drawLine(right, 7, right, bottom);
+ }
+ else if (tabIndex != firstIndex)
+ {
+ g.drawLine(right, 0, right, bottom);
+ }
+ else
+ {
+ g.drawLine(right, 6, right, bottom);
+ }
+ g.translate(-x, -y);
+ }
+
+ /**
+ * Paints the border for a tab assuming that the tab position is at the bottom
+ * ({@link #BOTTOM}).
+ *
+ * @param tabIndex the tab index.
+ * @param g the graphics device.
+ * @param x the x-coordinate for the tab's bounding rectangle.
+ * @param y the y-coordinate for the tab's bounding rectangle.
+ * @param w the width for the tab's bounding rectangle.
+ * @param h the height for the tab's bounding rectangle.
+ * @param btm ???
+ * @param rght ???
+ * @param isSelected indicates whether the tab is selected.
+ */
+ protected void paintBottomTabBorder(int tabIndex, Graphics g, int x, int y,
+ int w, int h, int btm, int rght, boolean isSelected)
+ {
+ int bottom = h - 1;
+ int right = w - 1;
+
+ int tabCount = tabPane.getTabCount();
+ int currentRun = getRunForTab(tabCount, tabIndex);
+ // Paint gap if necessary.
+ if (shouldFillGap(currentRun, tabIndex, x, y))
+ {
+ g.translate(x, y);
+ g.setColor(getColorForGap(currentRun, x, y));
+ g.fillRect(1, bottom - 4, 3, 5);
+ g.fillRect(4, bottom - 1, 2, 2);
+ g.translate(-x, -y);
+ }
+
+ g.translate(x, y);
+
+ // Paint border.
+ boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
+ Color oceanSelectedBorder =
+ UIManager.getColor("TabbedPane.borderHightlightColor");
+ if (isOcean && isSelected)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ else
+ {
+ g.setColor(darkShadow);
+ }
+ // Slant.
+ g.drawLine(1, bottom - 5, 6, bottom);
+ // Bottom.
+ g.drawLine(6, bottom, right, bottom);
+ // Right.
+ int lastIndex = lastTabInRun(tabCount, currentRun);
+ if (tabIndex == lastIndex)
+ {
+ g.drawLine(right, 0, right, bottom);
+ }
+ // Left.
+ if (isOcean && isSelected)
+ {
+ g.drawLine(0, 0, 0, bottom - 5);
+
+ // Paint a connecting line to the tab below for all
+ // but the first tab in the last run.
+ if (tabIndex != tabRuns[runCount-1])
+ {
+ g.setColor(darkShadow);
+ g.drawLine(0, bottom - 5, 0, bottom);
+ }
+ }
+ else
+ {
+ if (isOcean && tabIndex == tabPane.getSelectedIndex() + 1)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ if (tabIndex != tabRuns[runCount - 1])
+ {
+ g.drawLine(0, 0, 0, bottom);
+ }
+ else
+ {
+ g.drawLine(0, 0, 0, bottom - 6);
+ }
+ }
+
+ // Paint highlight.
+ g.setColor(isSelected ? selectHighlight : highlight);
+ // Slant.
+ g.drawLine(1, bottom - 6, 6, bottom - 1);
+ // Left.
+ g.drawLine(1, 0, 1, bottom - 6);
+
+ int firstIndex = tabRuns[currentRun];
+ if (tabIndex == firstIndex && tabIndex != tabRuns[runCount - 1])
+ {
+ if (tabPane.getSelectedIndex() == tabRuns[currentRun + 1])
+ {
+ g.setColor(selectHighlight);
+ }
+ else
+ {
+ g.setColor(highlight);
+ }
+ g.drawLine(1, bottom - 4, 1, bottom);
+ }
+
+ g.translate(-x, -y);
+ }
+
+ /**
+ * Paints the background for a tab.
+ *
+ * @param g the graphics device.
+ * @param tabPlacement the tab placement ({@link #TOP}, {@link #LEFT},
+ * {@link #BOTTOM} or {@link #RIGHT}).
+ * @param tabIndex the index of the tab to draw the border for.
+ * @param x the x-coordinate for the tab's bounding rectangle.
+ * @param y the y-coordinate for the tab's bounding rectangle.
+ * @param w the width for the tab's bounding rectangle.
+ * @param h the height for the tab's bounding rectangle.
+ * @param isSelected indicates whether or not the tab is selected.
+ */
+ protected void paintTabBackground(Graphics g, int tabPlacement,
+ int tabIndex, int x, int y, int w, int h, boolean isSelected)
+ {
+ if (isSelected)
+ g.setColor(selectColor);
+ else
+ g.setColor(getUnselectedBackground(tabIndex));
+
+ switch (tabPlacement)
+ {
+ case LEFT:
+ g.fillRect(x + 5, y + 1, w - 5, h - 1);
+ g.fillRect(x + 2, y + 4, 3, h - 4);
+ break;
+ case BOTTOM:
+ g.fillRect(x + 2, y, w - 2, h - 3);
+ g.fillRect(x + 5, y + h - 4, w - 5, 3);
+ break;
+ case RIGHT:
+ g.fillRect(x, y + 1, w - 4, h - 1);
+ g.fillRect(x + w - 4, y + 5, 3, h - 5);
+ break;
+ case TOP:
+ default:
+ g.fillRect(x + 4, y + 2, w - 4, h - 2);
+ g.fillRect(x + 2, y + 5, 2, h - 5);
+ }
+ }
+
+ /**
+ * This method paints the focus rectangle around the selected tab.
+ *
+ * @param g The Graphics object to paint with.
+ * @param tabPlacement The JTabbedPane's tab placement.
+ * @param rects The array of rectangles keeping track of size and position.
+ * @param tabIndex The tab index.
+ * @param iconRect The icon bounds.
+ * @param textRect The text bounds.
+ * @param isSelected Whether this tab is selected.
+ */
+ protected void paintFocusIndicator(Graphics g, int tabPlacement,
+ Rectangle[] rects, int tabIndex,
+ Rectangle iconRect, Rectangle textRect,
+ boolean isSelected)
+ {
+ if (tabPane.hasFocus() && isSelected)
+ {
+ Rectangle rect = rects[tabIndex];
+
+ g.setColor(focus);
+ g.translate(rect.x, rect.y);
+
+ switch (tabPlacement)
+ {
+ case LEFT:
+ // Top line
+ g.drawLine(7, 2, rect.width-2, 2);
+
+ // Right line
+ g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
+
+ // Bottom line
+ g.drawLine(rect.width-2, rect.height-2, 3, rect.height-2);
+
+ // Left line
+ g.drawLine(2, rect.height-3, 2, 7);
+
+ // Slant
+ g.drawLine(2, 6, 6, 2);
+ break;
+ case RIGHT:
+ // Top line
+ g.drawLine(1, 2, rect.width-8, 2);
+
+ // Slant
+ g.drawLine(rect.width-7, 2, rect.width-3, 6);
+
+ // Right line
+ g.drawLine(rect.width-3, 7, rect.width-3, rect.height-3);
+
+ // Bottom line
+ g.drawLine(rect.width-3, rect.height-2, 2, rect.height-2);
+
+ // Left line
+ g.drawLine(1, rect.height-2, 1, 2);
+ break;
+ case BOTTOM:
+ // Top line
+ g.drawLine(2, 1, rect.width-2, 1);
+
+ // Right line
+ g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
+
+ // Bottom line
+ g.drawLine(7, rect.height-3, rect.width-2, rect.height-3);
+
+ // Slant
+ g.drawLine(6, rect.height-3, 2, rect.height-7);
+
+ // Left line
+ g.drawLine(2, rect.height-8, 2, 2);
+
+ break;
+ case TOP:
+ default:
+ // Top line
+ g.drawLine(6, 2, rect.width-2, 2);
+
+ // Right line
+ g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
+
+ // Bottom line
+ g.drawLine(3, rect.height-3, rect.width-2, rect.height-3);
+
+ // Left line
+ g.drawLine(2, rect.height-3, 2, 7);
+
+ // Slant
+ g.drawLine(2, 6, 6, 2);
+
+ }
+
+ g.translate(-rect.x, -rect.y);
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if the tabs in the specified run should be
+ * padded to make the run fill the width/height of the {@link JTabbedPane}.
+ *
+ * @param tabPlacement the tab placement for the {@link JTabbedPane} (one of
+ * {@link #TOP}, {@link #BOTTOM}, {@link #LEFT} and {@link #RIGHT}).
+ * @param run the run index.
+ *
+ * @return A boolean.
+ */
+ protected boolean shouldPadTabRun(int tabPlacement, int run)
+ {
+ // as far as I can tell, all runs should be padded except the last run
+ // (which is drawn at the very top for tabPlacement == TOP)
+ return run < this.runCount - 1;
+ }
+
+ /**
+ * Installs the defaults for this UI. This method calls super.installDefaults
+ * and then loads the Metal specific defaults for TabbedPane.
+ */
+ protected void installDefaults()
+ {
+ super.installDefaults();
+ selectColor = UIManager.getColor("TabbedPane.selected");
+ selectHighlight = UIManager.getColor("TabbedPane.selectHighlight");
+ tabAreaBackground = UIManager.getColor("TabbedPane.tabAreaBackground");
+ tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
+ minTabWidth = 0;
+ }
+
+ /**
+ * Returns the color for the gap.
+ *
+ * @param currentRun - The current run to return the color for
+ * @param x - The x position of the current run
+ * @param y - The y position of the current run
+ *
+ * @return the color for the gap in the current run.
+ */
+ protected Color getColorForGap(int currentRun, int x, int y)
+ {
+ int index = tabForCoordinate(tabPane, x, y);
+ int selected = tabPane.getSelectedIndex();
+ if (selected == index)
+ return selectColor;
+ return tabAreaBackground;
+ }
+
+ /**
+ * Returns true if the gap should be filled in.
+ *
+ * @param currentRun - The current run
+ * @param tabIndex - The current tab
+ * @param x - The x position of the tab
+ * @param y - The y position of the tab
+ *
+ * @return true if the gap at the current run should be filled
+ */
+ protected boolean shouldFillGap(int currentRun, int tabIndex, int x, int y)
+ {
+ // As far as I can tell, the gap is never filled in.
+ return false;
+ }
+
+ /**
+ * Paints the highlight below the tab, if there is one.
+ */
+ protected void paintHighlightBelowTab()
+ {
+ int selected = tabPane.getSelectedIndex();
+ int tabPlacement = tabPane.getTabPlacement();
+ Rectangle bounds = getTabBounds(tabPane, selected);
+
+ hg.setColor(selectColor);
+ int x = bounds.x;
+ int y = bounds.y;
+ int w = bounds.width;
+ int h = bounds.height;
+
+ if (tabPlacement == TOP)
+ hg.fillRect(x, y + h - 2, w, 30);
+ else if (tabPlacement == LEFT)
+ hg.fillRect(x + w - 1, y, 20, h);
+ else if (tabPlacement == BOTTOM)
+ hg.fillRect(x, y - h + 2, w, 30);
+ else if (tabPlacement == RIGHT)
+ hg.fillRect(x - 18, y, 20, h);
+ else
+ throw new AssertionError("Unrecognised 'tabPlacement' argument.");
+ hg = null;
+ }
+
+ /**
+ * Returns true if we should rotate the tab runs.
+ *
+ * @param tabPlacement - The current tab placement.
+ * @param selectedRun - The selected run.
+ *
+ * @return true if the tab runs should be rotated.
+ */
+ protected boolean shouldRotateTabRuns(int tabPlacement,
+ int selectedRun)
+ {
+ // false because tab runs are not rotated in the MetalLookAndFeel
+ return false;
+ }
+
+ protected int calculateMaxTabHeight(int tabPlacement)
+ {
+ // FIXME: Why is this overridden?
+ return super.calculateMaxTabHeight(tabPlacement);
+ }
+
+ /**
+ * Returns the amount of overlay among the tabs. In
+ * the Metal L&F the overlay for LEFT and RIGHT placement
+ * is half of the maxTabHeight. For TOP and BOTTOM placement
+ * the tabs do not overlay.
+ *
+ * @param tabPlacement the placement
+ *
+ * @return the amount of overlay among the tabs
+ */
+ protected int getTabRunOverlay(int tabPlacement)
+ {
+ int overlay = 0;
+ if (tabPlacement == LEFT || tabPlacement == RIGHT)
+ {
+ int maxHeight = calculateMaxTabHeight(tabPlacement);
+ overlay = maxTabHeight / 2;
+ }
+ return overlay;
+ }
+
+ /**
+ * Paints the upper edge of the content border.
+ *
+ * @param g the graphics to use for painting
+ * @param tabPlacement the tab placement
+ * @param selectedIndex the index of the selected tab
+ * @param x the upper left coordinate of the content area
+ * @param y the upper left coordinate of the content area
+ * @param w the width of the content area
+ * @param h the height of the content area
+ */
+ protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
+ int selectedIndex, int x, int y,
+ int w, int h)
+ {
+ Color oceanSelectedBorder =
+ UIManager.getColor("TabbedPane.borderHightlightColor");
+ boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
+ if (isOcean)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ else
+ {
+ g.setColor(selectHighlight);
+ }
+
+ Rectangle rect = selectedIndex < 0 ? null :
+ getTabBounds(selectedIndex, calcRect);
+
+ // If tabs are not placed on TOP, or if the selected tab is not in the
+ // run directly above the content or the selected tab is not visible,
+ // then we draw an unbroken line.
+ if (tabPlacement != TOP || selectedIndex < 0
+ || rect.y + rect.height + 1 < y || rect.x < x || rect.x > x + w)
+ {
+ g.drawLine(x, y, x + w - 2, y);
+ if (isOcean && tabPlacement == TOP)
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x, y + 1, x + w - 2, y + 1);
+ }
+ }
+ else
+ {
+ boolean isLast = isLastTabInRun(selectedIndex);
+ if (isLast)
+ {
+ g.drawLine(x, y, rect.x + 1, y);
+ }
+ else
+ {
+ g.drawLine(x, y, rect.x, y);
+ }
+
+ int right = x + w - 1;
+ if (rect.x + rect.width < right - 1)
+ {
+ if (isLast)
+ {
+ g.drawLine(rect.x + rect.width - 1, y, right - 1, y);
+ }
+ else
+ {
+ g.drawLine(rect.x + rect.width, y, right - 1, y);
+ }
+ }
+ else
+ {
+ g.setColor(shadow);
+ g.drawLine(x + w - 2, y, x + w - 2, y);
+ }
+
+ // When in OceanTheme, draw another white line.
+ if (isOcean)
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+ if (isLast)
+ {
+ g.drawLine(x, y + 1, rect.x + 1, y + 1);
+ }
+ else
+ {
+ g.drawLine(x, y + 1, rect.x, y + 1);
+ }
+
+ if (rect.x + rect.width < right - 1)
+ {
+ if (isLast)
+ {
+ g.drawLine(rect.x + rect.width - 1, y + 1, right - 1,
+ y + 1);
+ }
+ else
+ {
+ g.drawLine(rect.x + rect.width, y + 1, right - 1, y + 1);
+ }
+ }
+ else
+ {
+ g.setColor(shadow);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
+ }
+ }
+ }
+ }
+
+ /**
+ * Paints the lower edge of the content border.
+ *
+ * @param g the graphics to use for painting
+ * @param tabPlacement the tab placement
+ * @param selectedIndex the index of the selected tab
+ * @param x the upper left coordinate of the content area
+ * @param y the upper left coordinate of the content area
+ * @param w the width of the content area
+ * @param h the height of the content area
+ */
+ protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement,
+ int selectedIndex, int x, int y,
+ int w, int h)
+ {
+ g.setColor(darkShadow);
+
+ // If tabs are not placed on BOTTOM, or if the selected tab is not in the
+ // run directly below the content or the selected tab is not visible,
+ // then we draw an unbroken line.
+ Rectangle rect = selectedIndex < 0 ? null :
+ getTabBounds(selectedIndex, calcRect);
+ boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
+ Color oceanSelectedBorder =
+ UIManager.getColor("TabbedPane.borderHightlightColor");
+ if (tabPlacement != BOTTOM || selectedIndex < 0 || rect.y - 1 > h
+ || rect.x < x || rect.x > x + w)
+ {
+ if (isOcean && tabPlacement == BOTTOM)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
+ }
+ else
+ {
+ boolean isLast = isLastTabInRun(selectedIndex);
+ if (isOcean)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+
+ int bottom = y + h - 1;
+ int right = x + w - 1;
+ if (isLast)
+ {
+ g.drawLine(x, bottom, rect.x, bottom);
+ }
+ else
+ {
+ g.drawLine(x, bottom, rect.x - 1, bottom);
+ }
+
+ if (rect.x + rect.width < x + w - 2)
+ {
+ if (isLast)
+ {
+ g.drawLine(rect.x + rect.width - 1, bottom, right, bottom);
+ }
+ else
+ {
+ g.drawLine(rect.x + rect.width, bottom, right, bottom);
+ }
+ }
+ }
+ }
+
+ /**
+ * Paints the left edge of the content border.
+ *
+ * @param g the graphics to use for painting
+ * @param tabPlacement the tab placement
+ * @param selectedIndex the index of the selected tab
+ * @param x the upper left coordinate of the content area
+ * @param y the upper left coordinate of the content area
+ * @param w the width of the content area
+ * @param h the height of the content area
+ */
+ protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement,
+ int selectedIndex, int x, int y,
+ int w, int h)
+ {
+ boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
+ Color oceanSelectedBorder =
+ UIManager.getColor("TabbedPane.borderHightlightColor");
+ Rectangle rect = selectedIndex < 0 ? null :
+ getTabBounds(selectedIndex, calcRect);
+
+ if (isOcean)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ else
+ {
+ g.setColor(selectHighlight);
+ }
+
+ // If tabs are not placed on LEFT, or if the selected tab is not in the
+ // run directly left to the content or the selected tab is not visible,
+ // then we draw an unbroken line.
+ if (tabPlacement != LEFT || selectedIndex < 0
+ || rect.x + rect.width + 1 < x || rect.y < y || rect.y > y + h)
+ {
+ g.drawLine(x, y + 1, x, y + h - 2);
+ if (isOcean && tabPlacement == LEFT)
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x, y + 1, x, y + h - 2);
+ }
+ }
+ else
+ {
+ g.drawLine(x, y, x, rect.y + 1);
+ if (rect.y + rect.height < y + h - 2)
+ {
+ g.drawLine(x, rect.y + rect.height + 1, x, y + h + 2);
+ }
+ if (isOcean)
+ {
+ g.setColor(MetalLookAndFeel.getWhite());
+ g.drawLine(x + 1, y + 1, x + 1, rect.y + 1);
+ if (rect.y + rect.height < y + h - 2)
+ {
+ g.drawLine(x + 1, rect.y + rect.height + 1, x + 1, y + h + 2);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Paints the right edge of the content border.
+ *
+ * @param g the graphics to use for painting
+ * @param tabPlacement the tab placement
+ * @param selectedIndex the index of the selected tab
+ * @param x the upper left coordinate of the content area
+ * @param y the upper left coordinate of the content area
+ * @param w the width of the content area
+ * @param h the height of the content area
+ */
+ protected void paintContentBorderRightEdge(Graphics g, int tabPlacement,
+ int selectedIndex, int x, int y,
+ int w, int h)
+ {
+ g.setColor(darkShadow);
+ Rectangle rect = selectedIndex < 0 ? null :
+ getTabBounds(selectedIndex, calcRect);
+ boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme;
+ Color oceanSelectedBorder =
+ UIManager.getColor("TabbedPane.borderHightlightColor");
+
+ // If tabs are not placed on RIGHT, or if the selected tab is not in the
+ // run directly right to the content or the selected tab is not visible,
+ // then we draw an unbroken line.
+ if (tabPlacement != RIGHT || selectedIndex < 0 || rect.x - 1 > w
+ || rect.y < y || rect.y > y + h)
+ {
+ if (isOcean && tabPlacement == RIGHT)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
+ }
+ else
+ {
+ if (isOcean)
+ {
+ g.setColor(oceanSelectedBorder);
+ }
+ g.drawLine(x + w - 1, y, x + w - 1, rect.y);
+
+ if (rect.y + rect.height < y + h - 2)
+ {
+ g.drawLine(x + w - 1, rect.y + rect.height, x + w - 1, y + h - 2);
+ }
+ }
+ }
+
+ /**
+ * Determines if the specified tab is the last tab in its tab run.
+ *
+ * @param tabIndex the index of the tab
+ *
+ * @return if the specified tab is the last tab in its tab run
+ */
+ private boolean isLastTabInRun(int tabIndex)
+ {
+ int count = tabPane.getTabCount();
+ int run = getRunForTab(count, tabIndex);
+ int lastIndex = lastTabInRun(count, run);
+ return tabIndex == lastIndex;
+ }
+
+ /**
+ * Returns the background for an unselected tab. This first asks the
+ * JTabbedPane for the background at the specified tab index, if this
+ * is an UIResource (that means, it is inherited from the JTabbedPane)
+ * and the TabbedPane.unselectedBackground UI property is not null,
+ * this returns the value of the TabbedPane.unselectedBackground property,
+ * otherwise the value returned by the JTabbedPane.
+ *
+ * @param tabIndex the index of the tab for which we query the background
+ *
+ * @return the background for an unselected tab
+ */
+ private Color getUnselectedBackground(int tabIndex)
+ {
+ Color bg = tabPane.getBackgroundAt(tabIndex);
+ Color unselectedBackground =
+ UIManager.getColor("TabbedPane.unselectedBackground");
+ if (bg instanceof UIResource && unselectedBackground != null)
+ bg = unselectedBackground;
+ return bg;
+ }
+
+ protected int getTabLabelShiftX(int tabPlacement,
+ int index,
+ boolean isSelected)
+ {
+ return 0;
+ }
+
+ protected int getTabLabelShiftY(int tabPlacement,
+ int index,
+ boolean isSelected)
+ {
+ return 0;
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java
new file mode 100644
index 000000000..f7b18dbd4
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java
@@ -0,0 +1,82 @@
+/* MetalTextFieldUI.java
+ Copyright (C) 2005 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.beans.PropertyChangeEvent;
+
+import javax.swing.JComponent;
+import javax.swing.JTextField;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicTextFieldUI;
+
+/**
+ * A UI delegate for the {@link JTextField} component.
+ */
+public class MetalTextFieldUI extends BasicTextFieldUI
+{
+ /**
+ * Constructs a new instance of MetalTextFieldUI.
+ */
+ public MetalTextFieldUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new instance of <code>MetalTextFieldUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A new instance of <code>MetalTextFieldUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalTextFieldUI();
+ }
+
+ /**
+ * This method gets called when a bound property is changed on the associated
+ * JTextComponent. This is a hook which UI implementations may change to
+ * reflect how the UI displays bound properties of JTextComponent subclasses.
+ */
+ public void propertyChange(PropertyChangeEvent evt)
+ {
+ super.propertyChange(evt);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java b/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java
new file mode 100644
index 000000000..209cbbe5e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java
@@ -0,0 +1,576 @@
+/* MetalTheme.java --
+ Copyright (C) 2004, 2005 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 javax.swing.UIDefaults;
+import javax.swing.plaf.ColorUIResource;
+import javax.swing.plaf.FontUIResource;
+
+/**
+ * The base class for themes used by the {@link MetalLookAndFeel}. A default
+ * theme ({@link DefaultMetalTheme}) is provided, or you can create and use
+ * your own.
+ *
+ * @see MetalLookAndFeel#setCurrentTheme(MetalTheme)
+ */
+public abstract class MetalTheme
+{
+ private ColorUIResource BLACK = new ColorUIResource(Color.BLACK);
+ private ColorUIResource WHITE = new ColorUIResource(Color.WHITE);
+
+ /**
+ * Default constructor.
+ */
+ public MetalTheme()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Returns the name of the theme.
+ *
+ * @return The name of the theme.
+ */
+ public abstract String getName();
+
+ /**
+ * Adds custom entries to the UI defaults table. This method is empty.
+ *
+ * @param table the table.
+ */
+ public void addCustomEntriesToTable(UIDefaults table)
+ {
+ // Do nothing here.
+ // This method needs to be overridden to actually do something.
+ // It is called from MetalLookAndFeel.getDefaults().
+ }
+
+ /**
+ * Returns the accelerator foreground color. The default implementation
+ * returns the color from {@link #getPrimary1()}.
+ *
+ * @return The accelerator foreground color.
+ */
+ public ColorUIResource getAcceleratorForeground()
+ {
+ return getPrimary1();
+ }
+
+ /**
+ * Returns the accelerator selected foreground color. The default
+ * implementation returns the color from {@link #getBlack()}.
+ *
+ * @return The accelerator selected foreground color.
+ */
+ public ColorUIResource getAcceleratorSelectedForeground()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the control color. The default implementation returns the color
+ * from {@link #getSecondary3()}.
+ *
+ * @return The control color.
+ */
+ public ColorUIResource getControl()
+ {
+ return getSecondary3();
+ }
+
+ /**
+ * Returns the color used for dark shadows on controls. The default
+ * implementation returns the color from {@link #getSecondary1()}.
+ *
+ * @return The color used for dark shadows on controls.
+ */
+ public ColorUIResource getControlDarkShadow()
+ {
+ return getSecondary1();
+ }
+
+ /**
+ * Returns the color used for disabled controls. The default implementation
+ * returns the color from {@link #getSecondary1()}.
+ *
+ * @return The color used for disabled controls.
+ */
+ public ColorUIResource getControlDisabled()
+ {
+ return getSecondary2();
+ }
+
+ /**
+ * Returns the color used to draw highlights for controls. The default
+ * implementation returns the color from {@link #getWhite()}.
+ *
+ * @return The color used to draw highlights for controls.
+ */
+ public ColorUIResource getControlHighlight()
+ {
+ return getWhite();
+ }
+
+ /**
+ * Returns the color used to display control info. The default
+ * implementation returns the color from {@link #getBlack()}.
+ *
+ * @return The color used to display control info.
+ */
+ public ColorUIResource getControlInfo()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the color used to draw shadows for controls. The default
+ * implementation returns the color from {@link #getSecondary2()}.
+ *
+ * @return The color used to draw shadows for controls.
+ */
+ public ColorUIResource getControlShadow()
+ {
+ return getSecondary2();
+ }
+
+ /**
+ * Returns the color used for text on controls. The default implementation
+ * returns the color from {@link #getControlInfo()}.
+ *
+ * @return The color used for text on controls.
+ */
+ public ColorUIResource getControlTextColor()
+ {
+ return getControlInfo();
+ }
+
+ /**
+ * Returns the color used for the desktop background. The default
+ * implementation returns the color from {@link #getPrimary2()}.
+ *
+ * @return The color used for the desktop background.
+ */
+ public ColorUIResource getDesktopColor()
+ {
+ return getPrimary2();
+ }
+
+ /**
+ * Returns the color used to draw focus highlights. The default
+ * implementation returns the color from {@link #getPrimary2()}.
+ *
+ * @return The color used to draw focus highlights.
+ */
+ public ColorUIResource getFocusColor()
+ {
+ return getPrimary2();
+ }
+
+ /**
+ * Returns the color used to draw highlighted text. The default
+ * implementation returns the color from {@link #getHighlightedTextColor()}.
+ *
+ * @return The color used to draw highlighted text.
+ */
+ public ColorUIResource getHighlightedTextColor()
+ {
+ return getControlTextColor();
+ }
+
+ /**
+ * Returns the color used to draw text on inactive controls. The default
+ * implementation returns the color from {@link #getControlDisabled()}.
+ *
+ * @return The color used to draw text on inactive controls.
+ */
+ public ColorUIResource getInactiveControlTextColor()
+ {
+ return getControlDisabled();
+ }
+
+ /**
+ * Returns the color used to draw inactive system text. The default
+ * implementation returns the color from {@link #getSecondary2()}.
+ *
+ * @return The color used to draw inactive system text.
+ */
+ public ColorUIResource getInactiveSystemTextColor()
+ {
+ return getSecondary2();
+ }
+
+ /**
+ * Returns the background color for menu items. The default implementation
+ * returns the color from {@link #getSecondary3()}.
+ *
+ * @return The background color for menu items.
+ *
+ * @see #getMenuSelectedBackground()
+ */
+ public ColorUIResource getMenuBackground()
+ {
+ return getSecondary3();
+ }
+
+ /**
+ * Returns the foreground color for disabled menu items. The default
+ * implementation returns the color from {@link #getSecondary2()}.
+ *
+ * @return The foreground color for disabled menu items.
+ *
+ * @see #getMenuForeground()
+ */
+ public ColorUIResource getMenuDisabledForeground()
+ {
+ return getSecondary2();
+ }
+
+ /**
+ * Returns the foreground color for menu items. The default implementation
+ * returns the color from {@link #getBlack()}.
+ *
+ * @return The foreground color for menu items.
+ *
+ * @see #getMenuDisabledForeground()
+ * @see #getMenuSelectedForeground()
+ */
+ public ColorUIResource getMenuForeground()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the background color for selected menu items. The default
+ * implementation returns the color from {@link #getPrimary2()}.
+ *
+ * @return The background color for selected menu items.
+ *
+ * @see #getMenuBackground()
+ */
+ public ColorUIResource getMenuSelectedBackground()
+ {
+ return getPrimary2();
+ }
+
+ /**
+ * Returns the foreground color for selected menu items. The default
+ * implementation returns the value from {@link #getBlack()}.
+ *
+ * @return The foreground color for selected menu items.
+ *
+ * @see #getMenuForeground()
+ */
+ public ColorUIResource getMenuSelectedForeground()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the primary color for controls. The default implementation
+ * returns the color from {@link #getPrimary3()}.
+ *
+ * @return The primary color for controls.
+ */
+ public ColorUIResource getPrimaryControl()
+ {
+ return getPrimary3();
+ }
+
+ /**
+ * Returns the primary color for the dark shadow on controls. The default
+ * implementation returns the color from {@link #getPrimary1()}.
+ *
+ * @return The primary color for the dark shadow on controls.
+ */
+ public ColorUIResource getPrimaryControlDarkShadow()
+ {
+ return getPrimary1();
+ }
+
+ /**
+ * Returns the primary color for the highlight on controls. The default
+ * implementation returns the color from {@link #getWhite()}.
+ *
+ * @return The primary color for the highlight on controls.
+ */
+ public ColorUIResource getPrimaryControlHighlight()
+ {
+ return getWhite();
+ }
+
+ /**
+ * Returns the primary color for the information on controls. The default
+ * implementation returns the color from {@link #getBlack()}.
+ *
+ * @return The primary color for the information on controls.
+ */
+ public ColorUIResource getPrimaryControlInfo()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the primary color for the shadow on controls. The default
+ * implementation returns the color from {@link #getPrimary2()}.
+ *
+ * @return The primary color for the shadow on controls.
+ */
+ public ColorUIResource getPrimaryControlShadow()
+ {
+ return getPrimary2();
+ }
+
+ /**
+ * Returns the background color for separators. The default implementation
+ * returns the color from {@link #getWhite()}.
+ *
+ * @return The background color for separators.
+ */
+ public ColorUIResource getSeparatorBackground()
+ {
+ return getWhite();
+ }
+
+ /**
+ * Returns the foreground color for separators. The default implementation
+ * returns the value from {@link #getPrimary1()}.
+ *
+ * @return The foreground color for separators.
+ */
+ public ColorUIResource getSeparatorForeground()
+ {
+ return getPrimary1();
+ }
+
+ /**
+ * Returns the color used for system text. The default implementation
+ * returns the color from {@link #getBlack()}.
+ *
+ * @return The color used for system text.
+ */
+ public ColorUIResource getSystemTextColor()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the color used to highlight text. The default implementation
+ * returns the color from {@link #getPrimary3()}.
+ *
+ * @return The color used to highlight text.
+ */
+ public ColorUIResource getTextHighlightColor()
+ {
+ return getPrimary3();
+ }
+
+ /**
+ * Returns the color used to display user text. The default implementation
+ * returns the color from {@link #getBlack()}.
+ *
+ * @return The color used to display user text.
+ */
+ public ColorUIResource getUserTextColor()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the window background color. The default implementation returns
+ * the color from {@link #getWhite()}.
+ *
+ * @return The window background color.
+ */
+ public ColorUIResource getWindowBackground()
+ {
+ return getWhite();
+ }
+
+ /**
+ * Returns the window title background color. The default implementation
+ * returns the color from {@link #getPrimary3()}.
+ *
+ * @return The window title background color.
+ */
+ public ColorUIResource getWindowTitleBackground()
+ {
+ return getPrimary3();
+ }
+
+ /**
+ * Returns the window title foreground color. The default implementation
+ * returns the color from {@link #getBlack()}.
+ *
+ * @return The window title foreground color.
+ */
+ public ColorUIResource getWindowTitleForeground()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the background color for an inactive window title. The default
+ * implementation returns the color from {@link #getSecondary3()}.
+ *
+ * @return The background color for an inactive window title.
+ */
+ public ColorUIResource getWindowTitleInactiveBackground()
+ {
+ return getSecondary3();
+ }
+
+ /**
+ * Returns the foreground color for an inactive window title. The default
+ * implementation returns the color from {@link #getBlack()}.
+ *
+ * @return The foreground color for an inactive window title.
+ */
+ public ColorUIResource getWindowTitleInactiveForeground()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the color used for black.
+ *
+ * @return The color used for black.
+ */
+ protected ColorUIResource getBlack()
+ {
+ return BLACK;
+ }
+
+ /**
+ * Returns the color used for white.
+ *
+ * @return The color used for white.
+ */
+ protected ColorUIResource getWhite()
+ {
+ return WHITE;
+ }
+
+ /**
+ * Returns the first primary color for this theme.
+ *
+ * @return The first primary color.
+ */
+ protected abstract ColorUIResource getPrimary1();
+
+ /**
+ * Returns the second primary color for this theme.
+ *
+ * @return The second primary color.
+ */
+ protected abstract ColorUIResource getPrimary2();
+
+ /**
+ * Returns the third primary color for this theme.
+ *
+ * @return The third primary color.
+ */
+ protected abstract ColorUIResource getPrimary3();
+
+ /**
+ * Returns the first secondary color for this theme.
+ *
+ * @return The first secondary color.
+ */
+ protected abstract ColorUIResource getSecondary1();
+
+ /**
+ * Returns the second secondary color for this theme.
+ *
+ * @return The second secondary color.
+ */
+ protected abstract ColorUIResource getSecondary2();
+
+ /**
+ * Returns the third secondary color for this theme.
+ *
+ * @return The third secondary color.
+ */
+ protected abstract ColorUIResource getSecondary3();
+
+ /**
+ * Returns the font used for text on controls.
+ *
+ * @return The font used for text on controls.
+ */
+ public abstract FontUIResource getControlTextFont();
+
+ /**
+ * Returns the font used for text in menus.
+ *
+ * @return The font used for text in menus.
+ */
+ public abstract FontUIResource getMenuTextFont();
+
+ /**
+ * Returns the font used for sub text.
+ *
+ * @return The font used for sub text.
+ */
+ public abstract FontUIResource getSubTextFont();
+
+ /**
+ * Returns the font used for system text.
+ *
+ * @return The font used for system text.
+ */
+ public abstract FontUIResource getSystemTextFont();
+
+ /**
+ * Returns the font used for user text.
+ *
+ * @return The font used for user text.
+ */
+ public abstract FontUIResource getUserTextFont();
+
+ /**
+ * Returns the font used for window titles.
+ *
+ * @return The font used for window titles.
+ */
+ public abstract FontUIResource getWindowTitleFont();
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java
new file mode 100644
index 000000000..2dacd7fec
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java
@@ -0,0 +1,230 @@
+/* MetalToggleButtonUI.java
+ Copyright (C) 2005 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.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.AbstractButton;
+import javax.swing.ButtonModel;
+import javax.swing.JComponent;
+import javax.swing.JToggleButton;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.basic.BasicButtonUI;
+import javax.swing.plaf.basic.BasicToggleButtonUI;
+
+/**
+ * A UI delegate for the {@link JToggleButton} component.
+ */
+public class MetalToggleButtonUI
+ extends BasicToggleButtonUI
+{
+
+ /** The color for the focus border. */
+ protected Color focusColor;
+
+ /** The color that indicates a selected button. */
+ protected Color selectColor;
+
+ /** The color for disabled button labels. */
+ protected Color disabledTextColor;
+
+ /**
+ * Returns a new instance of <code>MetalToggleButtonUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A new instance of <code>MetalToggleButtonUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalToggleButtonUI();
+ }
+
+ /**
+ * Constructs a new instance of <code>MetalToggleButtonUI</code>.
+ */
+ public MetalToggleButtonUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns the color for the focus border.
+ *
+ * @return the color for the focus border
+ */
+ protected Color getFocusColor()
+ {
+ return focusColor;
+ }
+
+ /**
+ * Returns the color that indicates a selected button.
+ *
+ * @return the color that indicates a selected button
+ */
+ protected Color getSelectColor()
+ {
+ return selectColor;
+ }
+
+ /**
+ * Returns the color for the text label of disabled buttons. The value
+ * is initialised in the {@link #installDefaults(AbstractButton)} method
+ * by reading the <code>ToggleButton.disabledText</code> item from the UI
+ * defaults.
+ *
+ * @return The color for the text label of disabled buttons.
+ */
+ protected Color getDisabledTextColor()
+ {
+ return disabledTextColor;
+ }
+
+ /**
+ * Updates the button with the defaults for this look and feel.
+ *
+ * @param b the button.
+ */
+ public void installDefaults(AbstractButton b)
+ {
+ super.installDefaults(b);
+ focusColor = UIManager.getColor(getPropertyPrefix() + "focus");
+ selectColor = UIManager.getColor(getPropertyPrefix() + "select");
+ disabledTextColor = UIManager.getColor(getPropertyPrefix() + "disabledText");
+ }
+
+ /**
+ * Paints the button background when it is pressed/selected.
+ *
+ * @param g the graphics device.
+ * @param b the button.
+ */
+ protected void paintButtonPressed(Graphics g, AbstractButton b)
+ {
+ if (b.isContentAreaFilled() && b.isOpaque())
+ {
+ Color saved = g.getColor();
+ Rectangle bounds = SwingUtilities.getLocalBounds(b);
+ g.setColor(selectColor);
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
+ g.setColor(saved);
+ }
+ }
+
+ /**
+ * Paints the text for the button.
+ *
+ * As of JDK 1.4 this method is obsolete.
+ * Use {@link BasicButtonUI#paintText(java.awt.Graphics,
+ * javax.swing.AbstractButton, java.awt.Rectangle, java.lang.String)}.
+ *
+ * @param g the graphics device.
+ * @param c the component.
+ * @param textRect the bounds for the text.
+ * @param text the text.
+ *
+ */
+ protected void paintText(Graphics g, JComponent c, Rectangle textRect,
+ String text)
+ {
+ Font savedFont = g.getFont();
+ Color savedColor = g.getColor();
+ g.setFont(c.getFont());
+ if (c.isEnabled())
+ g.setColor(c.getForeground());
+ else
+ g.setColor(disabledTextColor);
+ FontMetrics fm = g.getFontMetrics(c.getFont());
+ int ascent = fm.getAscent();
+ g.drawString(text, textRect.x, textRect.y + ascent);
+ g.setFont(savedFont);
+ g.setColor(savedColor);
+ }
+
+ /**
+ * Draws the focus highlight around the text and icon.
+ *
+ * @param g the graphics device.
+ * @param b the button.
+ */
+ protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect,
+ Rectangle textRect, Rectangle iconRect)
+ {
+ if (!b.hasFocus())
+ return;
+ Color saved = g.getColor();
+ g.setColor(focusColor);
+ Rectangle fr = iconRect.union(textRect);
+ g.drawRect(fr.x - 1, fr.y - 1, fr.width + 1, fr.height + 1);
+ g.setColor(saved);
+ }
+
+ /**
+ * If the property <code>ToggleButton.gradient</code> is set, then a gradient
+ * is painted as background, otherwise the normal superclass behaviour is
+ * called.
+ */
+ public void update(Graphics g, JComponent c)
+ {
+ AbstractButton b = (AbstractButton) c;
+ ButtonModel m = b.getModel();
+ if (b.getBackground() instanceof UIResource
+ && b.isContentAreaFilled()
+ && b.isEnabled() && ! m.isArmed() && ! m.isPressed()
+ && UIManager.get(getPropertyPrefix() + "gradient") != null)
+ {
+ MetalUtils.paintGradient(g, 0, 0, c.getWidth(), c.getHeight(),
+ SwingConstants.VERTICAL,
+ getPropertyPrefix() + "gradient");
+ paint(g, c);
+ }
+ else
+ super.update(g, c);
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java
new file mode 100644
index 000000000..64e679c67
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java
@@ -0,0 +1,298 @@
+/* MetalToolBarUI.java
+ Copyright (C) 2005 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.Graphics;
+import java.awt.Point;
+import java.awt.event.ContainerListener;
+import java.awt.event.MouseEvent;
+
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JComponent;
+import javax.swing.JToolBar;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.event.MouseInputListener;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicToolBarUI;
+
+/**
+ * A UI delegate for the {@link JToolBar} component.
+ */
+public class MetalToolBarUI extends BasicToolBarUI
+{
+
+ /**
+ * A listener (no longer used) that responds when components are added to or
+ * removed from the {@link JToolBar}. The required behaviour is now
+ * handled in the super class.
+ *
+ * @see MetalToolBarUI#createContainerListener()
+ */
+ protected class MetalContainerListener
+ extends BasicToolBarUI.ToolBarContListener
+ {
+ /**
+ * Creates a new instance.
+ */
+ protected MetalContainerListener()
+ {
+ // Nothing to do here.
+ }
+ }
+
+ /**
+ * A listener (no longer used) that responds to property change events in a
+ * {@link JToolBar} component. The required behaviour is now handled in the
+ * super class.
+ *
+ * @see MetalToolBarUI#createRolloverListener()
+ */
+ protected class MetalRolloverListener
+ extends BasicToolBarUI.PropertyListener
+ {
+ /**
+ * Creates a new instance.
+ */
+ protected MetalRolloverListener()
+ {
+ // Nothing to do here.
+ }
+ }
+
+ /**
+ * The container listener (an implementation specific field, according to the
+ * spec, and not used in GNU Classpath).
+ */
+ protected ContainerListener contListener;
+
+ /**
+ * The rollover listener (an implementation specific field, according to the
+ * spec, and not used in GNU Classpath).
+ */
+ protected PropertyChangeListener rolloverListener;
+
+ /**
+ * Creates a new instance of this UI delegate.
+ */
+ public MetalToolBarUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new instance of <code>MetalToolBarUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A new instance of <code>MetalToolBarUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalToolBarUI();
+ }
+
+ /**
+ * Returns <code>null</code> as permitted by recent versions of the API
+ * specification. Originally it seems this method returned a new instance of
+ * {@link MetalRolloverListener}, but this is now redundant.
+ *
+ * @return <code>null</code>.
+ */
+ protected PropertyChangeListener createRolloverListener()
+ {
+ return null;
+ }
+
+ /**
+ * Returns <code>null</code> as permitted by recent versions of the API
+ * specification. Originally it seems this method returned a new instance of
+ * {@link MetalContainerListener}, but this is now redundant.
+ *
+ * @return <code>null</code>.
+ */
+ protected ContainerListener createContainerListener()
+ {
+ return null;
+ }
+
+ /**
+ * Returns a border with no rollover effect for buttons in the tool bar.
+ *
+ * @return A border.
+ *
+ * @see MetalBorders#getToolbarButtonBorder()
+ */
+ protected Border createNonRolloverBorder()
+ {
+ return MetalBorders.getToolbarButtonBorder();
+ }
+
+ /**
+ * Sets the offset for the window used for dragging the toolbar.
+ * It is set as long as the window is not null (it has been installed).
+ */
+ protected void setDragOffset(Point p)
+ {
+ if (dragWindow != null)
+ dragWindow.setOffset(p);
+ }
+
+ /**
+ * Creates and returns an instance of MetalDockingListener.
+ *
+ * @return an instance of MetalDockingListener.
+ */
+ protected MouseInputListener createDockingListener()
+ {
+ return new MetalDockingListener(toolBar);
+ }
+
+ /**
+ * This is the MouseHandler class that allows the user to drag the JToolBar
+ * in and out of the parent and dock it if it can.
+ */
+ protected class MetalDockingListener extends BasicToolBarUI.DockingListener
+ {
+ /**
+ * Creates a new DockingListener object.
+ *
+ * @param t The JToolBar this DockingListener is being used for.
+ */
+ public MetalDockingListener(JToolBar t)
+ {
+ super(t);
+ }
+
+ /**
+ * This method is called when the mouse is pressed in the JToolBar. If the
+ * press doesn't occur in a place where it causes the JToolBar to be
+ * dragged, it returns. Otherwise, it starts a drag session.
+ *
+ * @param e The MouseEvent.
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ super.mousePressed(e);
+ setDragOffset(new Point(e.getX(), e.getY()));
+ }
+
+ /**
+ * This method is called when the mouse is dragged. It delegates the drag
+ * painting to the dragTo method.
+ *
+ * @param e The MouseEvent.
+ */
+ public void mouseDragged(MouseEvent e)
+ {
+ // Does not do anything differently than dragging
+ // BasicToolBarUI.DockingListener
+ super.mouseDragged(e);
+ }
+ }
+
+ /**
+ * Installs the UI on the toolbar. This calls super and sets the rollover
+ * property according to the <code>UIManager</code> property
+ * &quot;ToolBar.isRollover&quot;.
+ *
+ * @param c the component to install the UI on
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ if (c instanceof JToolBar)
+ {
+ JToolBar tb = (JToolBar) c;
+ tb.setRollover(UIManager.getBoolean("ToolBar.isRollover"));
+ }
+ }
+
+ /**
+ * Uninstalls the UI from the toolbar. This calls super and resets the
+ * rollover property.
+ *
+ * @param c the component to uninstall the UI from
+ */
+ public void uninstallUI(JComponent c)
+ {
+ if (c instanceof JToolBar)
+ {
+ JToolBar tb = (JToolBar) c;
+ tb.setRollover(false);
+ }
+ super.uninstallUI(c);
+ }
+
+ /**
+ * Paints the background of the component if necessary and then calls
+ * <code>paint(g, c)</code>.
+ *
+ * This is overridden to implement the OceanTheme gradient when an OceanTheme
+ * is installed.
+ *
+ * @param g the graphics to use
+ * @param c the component to paint.
+ *
+ * @since 1.5
+ */
+ public void update(Graphics g, JComponent c)
+ {
+ // TODO: Sun's implementation uses the MenuBar.gradient here.
+ // I would consider this a bug, but implement it like this
+ // for compatibility.
+ if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme
+ && UIManager.get("MenuBar.gradient") != null)
+ {
+ if (c.isOpaque())
+ {
+ MetalUtils.paintGradient(g, 0, 0, c.getWidth(), c.getHeight(),
+ SwingConstants.VERTICAL,
+ "MenuBar.gradient");
+ }
+ paint(g, c);
+ }
+ else
+ {
+ super.update(g, c);
+ }
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java
new file mode 100644
index 000000000..742ff2204
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java
@@ -0,0 +1,276 @@
+/* MetalToolTipUI.java
+ Copyright (C) 2005 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.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.AbstractButton;
+import javax.swing.JComponent;
+import javax.swing.JMenuItem;
+import javax.swing.JToolTip;
+import javax.swing.KeyStroke;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.UIResource;
+import javax.swing.plaf.basic.BasicToolTipUI;
+
+/**
+ * A UI delegate for the {@link JToolTip} component.
+ */
+public class MetalToolTipUI
+ extends BasicToolTipUI
+{
+ /**
+ * The amount of space between the tool tip text and the accelerator
+ * description (if visible).
+ */
+ public static final int padSpaceBetweenStrings = 12;
+
+ /** The shared UI instance. */
+ private static MetalToolTipUI instance;
+
+ /** A flag controlling the visibility of the accelerator (if there is one). */
+ private boolean isAcceleratorHidden;
+
+ /** A string representing the accelerator key for the component. */
+ private String acceleratorString;
+
+ /**
+ * The delimiter for the accelerator string.
+ */
+ private String acceleratorDelimiter;
+
+ /** The font for the accelerator string. */
+ private Font acceleratorFont;
+
+ /** The color for the accelerator string. */
+ private Color acceleratorForeground;
+
+ /** The active border. */
+ private Border activeBorder;
+
+ /** The inactive border. */
+ private Border inactiveBorder;
+
+ /**
+ * Constructs a new instance of <code>MetalToolTipUI</code>.
+ */
+ public MetalToolTipUI()
+ {
+ super();
+ activeBorder = UIManager.getBorder("ToolTip.border");
+ inactiveBorder = UIManager.getBorder("ToolTip.borderInactive");
+ isAcceleratorHidden = UIManager.getBoolean("ToolTip.hideAccelerator");
+ acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");
+ acceleratorForeground = UIManager.getColor("MenuItem.acceleratorForeground");
+ acceleratorDelimiter = UIManager.getString("MenuItem.acceleratorDelimiter");
+ }
+
+ /**
+ * Returns a shared instance of the <code>MetalToolTipUI</code> class.
+ * Although this UI delegate does maintain state information, there is never
+ * more than one tool tip visible, so it is OK to use a shared instance.
+ *
+ * @param component the component (a {@link JToolTip}).
+ *
+ * @return A shared instance of the <code>MetalToolTipUI</code> class.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ if (instance == null)
+ instance = new MetalToolTipUI();
+ return instance;
+ }
+
+ /**
+ * Returns a string representing the accelerator key (if there is one) for
+ * the component that the tool tip belongs to.
+ *
+ * @return A string representing the accelerator key.
+ */
+ public String getAcceleratorString()
+ {
+ return acceleratorString;
+ }
+
+ /**
+ * Installs the UI for the specified component (a {@link JToolTip}).
+ *
+ * @param c the {@link JToolTip} component.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ Border existingBorder = c.getBorder();
+ if (existingBorder == null || existingBorder instanceof UIResource)
+ {
+ if (c.isEnabled())
+ c.setBorder(activeBorder);
+ else
+ c.setBorder(inactiveBorder);
+ }
+ }
+
+ /**
+ * Clears the defaults set in {@link #installUI(JComponent)}.
+ *
+ * @param c the component.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ super.uninstallUI(c);
+ if (c.getBorder() instanceof UIResource)
+ c.setBorder(null);
+ }
+
+ /**
+ * Returns <code>true</code> if the accelerator string is hidden, and
+ * <code>false</code> otherwise. This setting is controlled by the
+ * <code>ToolTip.hideAccelerator</code> entry in the UI defaults table.
+ *
+ * @return A boolean.
+ */
+ protected boolean isAcceleratorHidden()
+ {
+ return isAcceleratorHidden;
+ }
+
+ /**
+ * Returns the preferred size for the {@link JToolTip} component.
+ *
+ * @param c the component (a {@link JToolTip}).
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ Dimension d = super.getPreferredSize(c);
+ String acc = getAcceleratorString();
+ if (acc != null && ! acc.equals(""))
+ {
+ FontMetrics fm = c.getFontMetrics(c.getFont());
+ d.width += fm.stringWidth(acc);
+ }
+ return d;
+ }
+
+ /**
+ * Paints the tool tip.
+ *
+ * @param g the graphics context.
+ * @param c the {@link JToolTip} component.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ super.paint(g, c);
+ // Somehow paint accelerator. Keep care for possible HTML rendering.
+ }
+
+ /**
+ * Returns a string representing the accelerator for the component, or
+ * <code>null</code> if the component has no accelerator.
+ *
+ * @param c the component.
+ *
+ * @return A string representing the accelerator (possibly
+ * <code>null</code>).
+ */
+ private String fetchAcceleratorString(JComponent c)
+ {
+ String result = null;
+ if (c instanceof JToolTip)
+ {
+ JToolTip toolTip = (JToolTip) c;
+ JComponent component = toolTip.getComponent();
+ KeyStroke ks = null;
+ int mne = 0;
+ if (component instanceof JMenuItem)
+ {
+ JMenuItem item = (JMenuItem) component;
+ ks = item.getAccelerator();
+ if (ks == null)
+ mne = item.getMnemonic();
+ }
+ else if (component instanceof AbstractButton)
+ {
+ AbstractButton button = (AbstractButton) component;
+ mne = button.getMnemonic();
+ }
+ if (mne > 0)
+ ks = KeyStroke.getKeyStroke(Character.toUpperCase((char) mne),
+ InputEvent.ALT_MASK, false);
+ if (ks != null)
+ result = acceleratorToString(ks);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a string representing an accelerator.
+ *
+ * @param accelerator the accelerator (<code>null</code> not permitted).
+ *
+ * @return A string representing an accelerator.
+ */
+ private String acceleratorToString(KeyStroke accelerator)
+ {
+ // convert keystroke into string format
+ String modifiersText = "";
+ int modifiers = accelerator.getModifiers();
+ char keyChar = accelerator.getKeyChar();
+ int keyCode = accelerator.getKeyCode();
+
+ if (modifiers != 0)
+ modifiersText = KeyEvent.getKeyModifiersText(modifiers)
+ + acceleratorDelimiter;
+
+ if (keyCode == KeyEvent.VK_UNDEFINED)
+ return modifiersText + keyChar;
+ else
+ return modifiersText + KeyEvent.getKeyText(keyCode);
+ }
+
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java
new file mode 100644
index 000000000..bdfa2d4f6
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java
@@ -0,0 +1,317 @@
+/* MetalTreeUI.java
+ Copyright (C) 2005 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.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JComponent;
+import javax.swing.JTree;
+import javax.swing.UIManager;
+import javax.swing.tree.TreePath;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicTreeUI;
+
+/**
+ * A UI delegate for the {@link JTree} component.
+ */
+public class MetalTreeUI extends BasicTreeUI
+{
+ /**
+ * Listens for property changes of the line style and updates the
+ * internal setting.
+ */
+ private class LineStyleListener
+ implements PropertyChangeListener
+ {
+
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(LINE_STYLE_PROPERTY))
+ decodeLineStyle(e.getNewValue());
+ }
+
+ }
+
+ /**
+ * The key to the lineStyle client property.
+ */
+ private static final String LINE_STYLE_PROPERTY = "JTree.lineStyle";
+
+ /**
+ * The property value indicating no line style.
+ */
+ private static final String LINE_STYLE_VALUE_NONE = "None";
+
+ /**
+ * The property value indicating angled line style.
+ */
+ private static final String LINE_STYLE_VALUE_ANGLED = "Angled";
+
+ /**
+ * The property value indicating horizontal line style.
+ */
+ private static final String LINE_STYLE_VALUE_HORIZONTAL = "Horizontal";
+
+ /**
+ * The line style for None.
+ */
+ private static final int LINE_STYLE_NONE = 0;
+
+ /**
+ * The line style for Angled.
+ */
+ private static final int LINE_STYLE_ANGLED = 1;
+
+ /**
+ * The line style for Horizontal.
+ */
+ private static final int LINE_STYLE_HORIZONTAL = 2;
+
+ /**
+ * The current line style.
+ */
+ private int lineStyle;
+
+ /**
+ * Listens for changes on the line style property and updates the
+ * internal settings.
+ */
+ private PropertyChangeListener lineStyleListener;
+
+ /**
+ * Constructs a new instance of <code>MetalTreeUI</code>.
+ */
+ public MetalTreeUI()
+ {
+ super();
+ }
+
+ /**
+ * Returns a new instance of <code>MetalTreeUI</code>.
+ *
+ * @param component the component for which we return an UI instance
+ *
+ * @return A new instance of <code>MetalTreeUI</code>.
+ */
+ public static ComponentUI createUI(JComponent component)
+ {
+ return new MetalTreeUI();
+ }
+
+ /**
+ * The horizontal element of legs between nodes starts at the right of the
+ * left-hand side of the child node by default. This method makes the
+ * leg end before that.
+ */
+ protected int getHorizontalLegBuffer()
+ {
+ return super.getHorizontalLegBuffer();
+ }
+
+ /**
+ * Configures the specified component appropriate for the look and feel.
+ * This method is invoked when the ComponentUI instance is being installed
+ * as the UI delegate on the specified component. This method should completely
+ * configure the component for the look and feel, including the following:
+ * 1. Install any default property values for color, fonts, borders, icons,
+ * opacity, etc. on the component. Whenever possible, property values
+ * initialized by the client program should not be overridden.
+ * 2. Install a LayoutManager on the component if necessary.
+ * 3. Create/add any required sub-components to the component.
+ * 4. Create/install event listeners on the component.
+ * 5. Create/install a PropertyChangeListener on the component in order
+ * to detect and respond to component property changes appropriately.
+ * 6. Install keyboard UI (mnemonics, traversal, etc.) on the component.
+ * 7. Initialize any appropriate instance data.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+
+ Object lineStyleProp = c.getClientProperty(LINE_STYLE_PROPERTY);
+ decodeLineStyle(lineStyleProp);
+ if (lineStyleListener == null)
+ lineStyleListener = new LineStyleListener();
+ c.addPropertyChangeListener(lineStyleListener);
+ }
+
+ /**
+ * Reverses configuration which was done on the specified component during
+ * installUI. This method is invoked when this UIComponent instance is being
+ * removed as the UI delegate for the specified component. This method should
+ * undo the configuration performed in installUI, being careful to leave the
+ * JComponent instance in a clean state (no extraneous listeners,
+ * look-and-feel-specific property objects, etc.). This should include
+ * the following:
+ * 1. Remove any UI-set borders from the component.
+ * 2. Remove any UI-set layout managers on the component.
+ * 3. Remove any UI-added sub-components from the component.
+ * 4. Remove any UI-added event/property listeners from the component.
+ * 5. Remove any UI-installed keyboard UI from the component.
+ * 6. Nullify any allocated instance data objects to allow for GC.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ super.uninstallUI(c);
+ if (lineStyleListener != null)
+ c.removePropertyChangeListener(lineStyleListener);
+ lineStyleListener = null;
+ }
+
+ /**
+ * This function converts between the string passed into the client
+ * property and the internal representation (currently an int).
+ *
+ * @param lineStyleFlag - String representation
+ */
+ protected void decodeLineStyle(Object lineStyleFlag)
+ {
+ if (lineStyleFlag == null || lineStyleFlag.equals(LINE_STYLE_VALUE_ANGLED))
+ lineStyle = LINE_STYLE_ANGLED;
+ else if (lineStyleFlag.equals(LINE_STYLE_VALUE_HORIZONTAL))
+ lineStyle = LINE_STYLE_HORIZONTAL;
+ else if (lineStyleFlag.equals(LINE_STYLE_VALUE_NONE))
+ lineStyle = LINE_STYLE_NONE;
+ else
+ lineStyle = LINE_STYLE_ANGLED;
+ }
+
+ /**
+ * Checks if the location is in expand control.
+ *
+ * @param row - current row
+ * @param rowLevel - current level
+ * @param mouseX - current x location of the mouse click
+ * @param mouseY - current y location of the mouse click
+ */
+ protected boolean isLocationInExpandControl(int row, int rowLevel,
+ int mouseX, int mouseY)
+ {
+ return super.isLocationInExpandControl(tree.getPathForRow(row),
+ mouseX, mouseY);
+ }
+
+ /**
+ * Paints the specified component appropriate for the look and feel.
+ * This method is invoked from the ComponentUI.update method when the
+ * specified component is being painted. Subclasses should override this
+ * method and use the specified Graphics object to render the content of
+ * the component.
+ *
+ * @param g - the current graphics configuration.
+ * @param c - the current component to draw
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ // Calls BasicTreeUI's paint since it takes care of painting all
+ // types of icons.
+ super.paint(g, c);
+
+ if (lineStyle == LINE_STYLE_HORIZONTAL)
+ paintHorizontalSeparators(g, c);
+ }
+
+ /**
+ * Paints the horizontal separators.
+ *
+ * @param g - the current graphics configuration.
+ * @param c - the current component to draw
+ */
+ protected void paintHorizontalSeparators(Graphics g, JComponent c)
+ {
+ g.setColor(UIManager.getColor("Tree.line"));
+ Rectangle clip = g.getClipBounds();
+ int row0 = getRowForPath(tree, getClosestPathForLocation(tree, 0, clip.y));
+ int row1 =
+ getRowForPath(tree, getClosestPathForLocation(tree, 0,
+ clip.y + clip.height - 1));
+ if (row0 >= 0 && row1 >= 0)
+ {
+ for (int i = row0; i <= row1; i++)
+ {
+ TreePath p = getPathForRow(tree, i);
+ if (p != null && p.getPathCount() == 2)
+ {
+ Rectangle r = getPathBounds(tree, getPathForRow(tree, i));
+ if (r != null)
+ {
+ g.drawLine(clip.x, r.y, clip.x + clip.width, r.y);
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Paints the vertical part of the leg. The receiver should NOT modify
+ * clipBounds, insets.
+ *
+ * @param g - the current graphics configuration.
+ * @param clipBounds -
+ * @param insets -
+ * @param path - the current path
+ */
+ protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,
+ Insets insets, TreePath path)
+ {
+ if (lineStyle == LINE_STYLE_ANGLED)
+ super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
+ }
+
+ /**
+ * Paints the horizontal part of the leg. The receiver should NOT \
+ * modify clipBounds, or insets.
+ * NOTE: parentRow can be -1 if the root is not visible.
+ */
+ protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
+ Insets insets, Rectangle bounds,
+ TreePath path, int row,
+ boolean isExpanded, boolean hasBeenExpanded,
+ boolean isLeaf)
+ {
+ if (lineStyle == LINE_STYLE_ANGLED)
+ super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path, row,
+ isExpanded, hasBeenExpanded, isLeaf);
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java
new file mode 100644
index 000000000..247f92265
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java
@@ -0,0 +1,597 @@
+/* MetalUtils.java
+Copyright (C) 2005 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 gnu.classpath.SystemProperties;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.GradientPaint;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.TexturePaint;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.util.List;
+
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+
+/**
+ * Some utility and helper methods for the Metal Look &amp; Feel.
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+class MetalUtils
+{
+
+ /**
+ * The typical metal pattern for use with Graphics2D.
+ */
+ static BufferedImage pattern2D;
+
+ /**
+ * The light color to draw the pattern.
+ */
+ static Color lightColor;
+
+ /**
+ * The dark color to draw to draw the pattern.
+ */
+ static Color darkColor;
+
+ /**
+ * Fills a rectangle with the typical Metal pattern.
+ *
+ * @param g the <code>Graphics</code> context to use
+ * @param x the X coordinate of the upper left corner of the rectangle to
+ * fill
+ * @param y the Y coordinate of the upper left corner of the rectangle to
+ * fill
+ * @param w the width of the rectangle to fill
+ * @param h the height of the rectangle to fill
+ * @param light the light color to use
+ * @param dark the dark color to use
+ */
+ static void fillMetalPattern(Component c, Graphics g, int x, int y, int w, int h,
+ Color light, Color dark)
+ {
+ if (g instanceof Graphics2D
+ && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") == null)
+ fillMetalPattern2D((Graphics2D) g, x, y, w, h, light, dark);
+ else
+ {
+ int xOff = 0;
+ for (int mY = y; mY < (y + h); mY++)
+ {
+ // set color alternating with every line
+ if (((mY - y) % 2) == 0)
+ g.setColor(light);
+ else
+ g.setColor(dark);
+
+ for (int mX = x + xOff; mX < (x + w); mX += 4)
+ {
+ g.fillRect(mX, mY, 1, 1);
+ }
+
+ // increase x offset
+ xOff++;
+ if (xOff > 3)
+ xOff = 0;
+ }
+ }
+ }
+
+ /**
+ * Fills a rectangle with the typical Metal pattern using Java2D.
+ *
+ * @param g2d the <code>Graphics2D</code> context to use
+ * @param x the X coordinate of the upper left corner of the rectangle to
+ * fill
+ * @param y the Y coordinate of the upper left corner of the rectangle to
+ * fill
+ * @param w the width of the rectangle to fill
+ * @param h the height of the rectangle to fill
+ */
+ static void fillMetalPattern2D(Graphics2D g2d, int x, int y, int w, int h,
+ Color light, Color dark)
+ {
+ if (pattern2D == null || !darkColor.equals(dark) || !lightColor.equals(light))
+ initializePattern(light, dark);
+
+ // Prepare the texture.
+ TexturePaint texture =
+ new TexturePaint(pattern2D, new Rectangle2D.Double(0., 0., 4., 4.));
+ g2d.setPaint(texture);
+ g2d.fillRect(x, y, w, h);
+ }
+
+ /**
+ * Initializes the pattern image.
+ */
+ static void initializePattern(Color light, Color dark)
+ {
+ pattern2D = new BufferedImage(4, 4, BufferedImage.TYPE_INT_ARGB);
+ lightColor = light;
+ darkColor = dark;
+ Graphics g = pattern2D.getGraphics();
+ g.setColor(light);
+ g.fillRect(0, 0, 1, 1);
+ g.fillRect(2, 2, 1, 1);
+ g.setColor(dark);
+ g.fillRect(1, 1, 1, 1);
+ g.fillRect(3, 3, 1, 1);
+ g.dispose();
+ }
+
+ /**
+ * Paints the typical Metal gradient. See {@link #paintGradient(Graphics,
+ * int, int, int, int, float, float, Color, Color, Color, int, int[][])}
+ * for more details.
+ *
+ * This variant paints a gradient without a mask.
+ *
+ * @param g the graphics context to use
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param dir the direction of the gradient, either
+ * @param uiProp the key of the UIManager property that has the parameters
+ */
+ static void paintGradient(Graphics g, int x, int y, int w, int h,
+ int dir, String uiProp)
+ {
+ paintGradient(g, x, y, w, h, dir, uiProp, null);
+ }
+
+ /**
+ * Paints the typical Metal gradient. See {@link #paintGradient(Graphics,
+ * int, int, int, int, float, float, Color, Color, Color, int, int[][])}
+ * for more details.
+ *
+ * The parameters are fetched from the UIManager using the key
+ * <code>uiProp</code>. The value is expected to be a {@link List} that
+ * contains 4 values: two {@link Double}s and 3 {@link Color} object that
+ * together make up the parameters passed to the painting method.
+ *
+ * @param g the graphics context to use
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param dir the direction of the gradient, either
+ * @param uiProp the key of the UIManager property that has the parameters
+ * @param mask the mask that should be used when painting the gradient as
+ * described above
+ */
+ static void paintGradient(Graphics g, int x, int y, int w, int h,
+ int dir, String uiProp, int[][] mask)
+ {
+ List params = (List) UIManager.get(uiProp);
+ float g1 = ((Float) params.get(0)).floatValue();
+ float g2 = ((Float) params.get(1)).floatValue();
+ Color c1 = (Color) params.get(2);
+ Color c2 = (Color) params.get(3);
+ Color c3 = (Color) params.get(4);
+ paintGradient(g, x, y, w, h, g1, g2, c1, c2, c3, dir, mask);
+ }
+
+ /**
+ * Paints the typical Metal gradient. The gradient is painted as follows:
+ * <pre>
+ *
+ * +-------+--------+--------+-----------------------------+
+ * | | | | |
+ * +-------+--------+--------+-----------------------------+
+ * c1 -> c2 -- c2 -> c1 --------> c3
+ * < -g1- > < -g2- > < -g1- >
+ * </pre>
+ *
+ * There are 4 distinct areas in this gradient:
+ * <ol>
+ * <li>A gradient from color 1 to color 2 with the relative width specified
+ * by <code>g1</code></li>
+ * <li>A solid area with the color 2 and the relative width specified by
+ * <code>g2</code></li>
+ * <li>A gradient from color 2 to color 1 with the relative width specified
+ * by <code>g1</code></li>
+ *
+ * The <code>mask</code> parameter is an array if int arrays, where the first
+ * index specifies the row (in the gradient direction), and the second index
+ * is the starting and end offset of that line. This way you can specify a
+ * mask that should be laid over the gradient for paintint non-rectangular
+ * gradients. The following example should demonstrate this for painting
+ * a circular shaped gradient (note that the first and last line should not
+ * be drawn at all, they are only here to show the circular shape more
+ * clearly). Everything <em>inside</code> the surrounded area is filled by
+ * the gradient:
+ *
+ * <pre>
+ * 012345678
+ * xxx
+ * 0 x x { {4, 7},
+ * 1 x x {3, 8},
+ * 2 x x {3, 8},
+ * 3 x x {3, 8},
+ * 4 x x {4, 7} }
+ * xxx
+ * </pre>
+ *
+ * The <code>mask</code> array is expected to have <code>w</code> or
+ * <code>h</code> array elements, depending on the direction.
+ *
+ * If the <code>mask</code> parameter is null, then the gradient is painted
+ * without a mask.
+ *
+ * @param g the graphics context to use
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param g1 the relative width of the c1->c2 gradients
+ * @param g2 the relative width of the c2 solid area
+ * @param c1 the color 1
+ * @param c2 the color 2
+ * @param c3 the color 3
+ * @param dir the direction of the gradient, either
+ * {@link SwingConstants#HORIZONTAL} or {@link SwingConstants#VERTICAL}
+ * @param mask the mask that should be used when painting the gradient as
+ * described above
+ */
+ static void paintGradient(Graphics g, int x, int y, int w, int h, float g1,
+ float g2, Color c1, Color c2, Color c3, int dir,
+ int[][] mask)
+ {
+ if (dir == SwingConstants.HORIZONTAL)
+ paintHorizontalGradient(g, x, y, w, h, g1, g2, c1, c2, c3, mask);
+ else
+ paintVerticalGradient(g, x, y, w, h, g1, g2, c1, c2, c3, mask);
+ }
+
+ /**
+ * Paints a horizontal gradient. See {@link #paintGradient(Graphics, int,
+ * int, int, int, float, float, Color, Color, Color, int, int[][])}
+ * for details.
+ *
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param g1 the relative width of the c1->c2 gradients
+ * @param g2 the relative width of the c2 solid area
+ * @param c1 the color 1
+ * @param c2 the color 2
+ * @param c3 the color 3
+ * @param mask the mask that should be used when painting the gradient as
+ * described above
+ */
+ static void paintHorizontalGradient(Graphics g, int x, int y, int w, int h,
+ float g1, float g2, Color c1, Color c2,
+ Color c3, int[][] mask)
+ {
+
+ if (g instanceof Graphics2D
+ && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") == null)
+ {
+ paintHorizontalGradient2D((Graphics2D) g, x, y, w, h, g1, g2, c1, c2,
+ c3, mask);
+ return;
+ }
+
+ // Calculate the coordinates.
+ int y0 = y;
+ int y1 = y + h;
+ // The size of the first gradient area (c1->2).
+ int w1 = (int) (w * g1);
+ // The size of the solid c2 area.
+ int w2 = (int) (w * g2);
+ int x0 = x;
+ int x1 = x0 + w1;
+ int x2 = x1 + w2;
+ int x3 = x2 + w1;
+ int x4 = x + w;
+
+ // Paint first gradient area (c1->c2).
+ int xc; // The current y coordinate.
+ for (xc = x0; xc < x1; xc++)
+ {
+ if (xc > x + w)
+ break;
+
+ // Perform color interpolation;
+ double factor = (xc - x0) / (double) w1;
+ int rInt = (int) ((c2.getRed() - c1.getRed()) * factor + c1.getRed());
+ int gInt = (int) ((c2.getGreen() - c1.getGreen()) * factor
+ + c1.getGreen());
+ int bInt = (int) ((c2.getBlue() - c1.getBlue()) * factor
+ + c1.getBlue());
+ Color interpolated = new Color(rInt, gInt, bInt);
+ g.setColor(interpolated);
+ if (mask != null)
+ {
+ y0 = mask[xc - x0][0] + y;
+ y1 = mask[xc - x0][1] + y;
+ }
+ g.fillRect(xc, y0, 1, y1 - y0);
+ }
+ // Paint solid c2 area.
+ g.setColor(c2);
+ if (mask == null)
+ {
+ g.fillRect(x1, y, x2 - x1, h);
+ }
+ else
+ {
+ for (xc = x1; xc < x2; xc++)
+ {
+ y0 = mask[xc - x0][0] + y;
+ y1 = mask[xc - x0][1] + y;
+ g.fillRect(xc, y0, 1, y1 - y0);
+ }
+ }
+
+ // Paint second gradient area (c2->c1).
+ for (xc = x2; xc < x3; xc++)
+ {
+ if (xc > x + w)
+ break;
+
+ // Perform color interpolation;
+ double factor = (xc - x2) / (double) w1;
+ int rInt = (int) ((c1.getRed() - c2.getRed()) * factor + c2.getRed());
+ int gInt = (int) ((c1.getGreen() - c2.getGreen()) * factor
+ + c2.getGreen());
+ int bInt = (int) ((c1.getBlue() - c2.getBlue()) * factor
+ + c2.getBlue());
+ Color interpolated = new Color(rInt, gInt, bInt);
+ g.setColor(interpolated);
+ if (mask != null)
+ {
+ y0 = mask[xc - x0][0] + y;
+ y1 = mask[xc - x0][1] + y;
+ }
+ g.fillRect(xc, y0, 1, y1 - y0);
+ }
+
+ // Paint third gradient area (c1->c3).
+ for (xc = x3; xc < x4; xc++)
+ {
+ if (xc > x + w)
+ break;
+
+ // Perform color interpolation;
+ double factor = (xc - x3) / (double) (x4 - x3);
+ int rInt = (int) ((c3.getRed() - c1.getRed()) * factor + c1.getRed());
+ int gInt = (int) ((c3.getGreen() - c1.getGreen()) * factor
+ + c1.getGreen());
+ int bInt = (int) ((c3.getBlue() - c1.getBlue()) * factor
+ + c1.getBlue());
+ Color interpolated = new Color(rInt, gInt, bInt);
+ g.setColor(interpolated);
+ if (mask != null)
+ {
+ y0 = mask[xc - x0][0] + y;
+ y1 = mask[xc - x0][1] + y;
+ }
+ g.drawLine(xc, y0, xc, y1);
+ }
+ }
+
+ /**
+ * Paints a vertical gradient. See {@link #paintGradient(Graphics, int, int,
+ * int, int, float, float, Color, Color, Color, int, int[][])} for details.
+ *
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param g1 the relative width of the c1->c2 gradients
+ * @param g2 the relative width of the c2 solid area
+ * @param c1 the color 1
+ * @param c2 the color 2
+ * @param c3 the color 3
+ * @param mask the mask that should be used when painting the gradient as
+ * described above
+ */
+ static void paintVerticalGradient(Graphics g, int x, int y, int w, int h,
+ float g1, float g2, Color c1, Color c2,
+ Color c3, int[][] mask)
+ {
+ if (g instanceof Graphics2D
+ && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") == null)
+ {
+ paintVerticalGradient2D((Graphics2D) g, x, y, w, h, g1, g2, c1, c2,
+ c3, mask);
+ return;
+ }
+
+ // Calculate the coordinates.
+ int x0 = x;
+ int x1 = x + w;
+ // The size of the first gradient area (c1->2).
+ int w1 = (int) (h * g1);
+ // The size of the solid c2 area.
+ int w2 = (int) (h * g2);
+ int y0 = y;
+ int y1 = y0 + w1;
+ int y2 = y1 + w2;
+ int y3 = y2 + w1;
+ int y4 = y + h;
+
+ // Paint first gradient area (c1->c2).
+ int yc; // The current y coordinate.
+ for (yc = y0; yc < y1; yc++)
+ {
+ if (yc > y + h)
+ break;
+
+ // Perform color interpolation;
+ double factor = (yc - y0) / (double) w1;
+ int rInt = (int) ((c2.getRed() - c1.getRed()) * factor + c1.getRed());
+ int gInt = (int) ((c2.getGreen() - c1.getGreen()) * factor
+ + c1.getGreen());
+ int bInt = (int) ((c2.getBlue() - c1.getBlue()) * factor
+ + c1.getBlue());
+ Color interpolated = new Color(rInt, gInt, bInt);
+ g.setColor(interpolated);
+ if (mask != null)
+ {
+ x0 = mask[yc - y0][0] + x;
+ x1 = mask[yc - y0][1] + x;
+ }
+ g.fillRect(x0, yc, x1 - x0, 1);
+ }
+ // Paint solid c2 area.
+ g.setColor(c2);
+ if (mask == null)
+ {
+ g.fillRect(x, y1, w, y2 - y1);
+ }
+ else
+ {
+ for (yc = y1; yc < y2; yc++)
+ {
+ x0 = mask[yc - y0][0] + x;
+ x1 = mask[yc - y0][1] + x;
+ g.fillRect(x0, yc, x1 - x0, 1);
+ }
+ }
+
+ // Paint second gradient area (c2->c1).
+ for (yc = y2; yc < y3; yc++)
+ {
+ if (yc > y + h)
+ break;
+
+ // Perform color interpolation;
+ double factor = (yc - y2) / (double) w1;
+ int rInt = (int) ((c1.getRed() - c2.getRed()) * factor + c2.getRed());
+ int gInt = (int) ((c1.getGreen() - c2.getGreen()) * factor
+ + c2.getGreen());
+ int bInt = (int) ((c1.getBlue() - c2.getBlue()) * factor
+ + c2.getBlue());
+ Color interpolated = new Color(rInt, gInt, bInt);
+ g.setColor(interpolated);
+ if (mask != null)
+ {
+ x0 = mask[yc - y0][0] + x;
+ x1 = mask[yc - y0][1] + x;
+ }
+ g.fillRect(x0, yc, x1 - x0, 1);
+ }
+
+ // Paint third gradient area (c1->c3).
+ for (yc = y3; yc < y4; yc++)
+ {
+ if (yc > y + h)
+ break;
+
+ // Perform color interpolation;
+ double factor = (yc - y3) / (double) (y4 - y3);
+ int rInt = (int) ((c3.getRed() - c1.getRed()) * factor + c1.getRed());
+ int gInt = (int) ((c3.getGreen() - c1.getGreen()) * factor
+ + c1.getGreen());
+ int bInt = (int) ((c3.getBlue() - c1.getBlue()) * factor
+ + c1.getBlue());
+ Color interpolated = new Color(rInt, gInt, bInt);
+ g.setColor(interpolated);
+ if (mask != null)
+ {
+ x0 = mask[yc - y0][0] + x;
+ x1 = mask[yc - y0][1] + x;
+ }
+ g.fillRect(x0, yc, x1 - x0, 1);
+ }
+ }
+
+ /**
+ * Paints a horizontal gradient using Graphics2D functionality.
+ *
+ * @param g the Graphics2D instance
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param g1 the relative width of the c1->c2 gradients
+ * @param g2 the relative width of the c2 solid area
+ * @param c1 the color 1
+ * @param c2 the color 2
+ * @param c3 the color 3
+ * @param mask the mask that should be used when painting the gradient as
+ * described above
+ */
+ private static void paintHorizontalGradient2D(Graphics2D g, int x, int y,
+ int w, int h, float g1,
+ float g2, Color c1,
+ Color c2, Color c3,
+ int[][] mask)
+ {
+ // FIXME: Handle the mask somehow, or do Graphics2D clipping instead.
+ GradientPaint p1 = new GradientPaint(x, y, c1, x + w * g1, y, c2);
+ g.setPaint(p1);
+ // This fills the first gradient and the solid area in one go.
+ g.fillRect(x, y, (int) (w * (g1 + g2)), h);
+
+ GradientPaint p2 = new GradientPaint(x + (w * (g1 + g2)), y, c2, x + w, y,
+ c3);
+ g.setPaint(p2);
+ g.fillRect((int) (x + (w * (g1 + g2))), y,
+ (int) (w * (1. - (g1 + g2))), h);
+ }
+
+ private static void paintVerticalGradient2D(Graphics2D g, int x, int y,
+ int w, int h, float g1,
+ float g2, Color c1,
+ Color c2, Color c3,
+ int[][] mask)
+ {
+ // FIXME: Handle the mask somehow, or do Graphics2D clipping instead.
+ GradientPaint p1 = new GradientPaint(x, y, c1, x, y + h * g1, c2);
+ g.setPaint(p1);
+ // This fills the first gradient and the solid area in one go.
+ g.fillRect(x, y, w, (int) (h * (g1 + g2)));
+
+ GradientPaint p2 = new GradientPaint(x, y + (h * (g1 + g2)), c2, x, y + h,
+ c3);
+ g.setPaint(p2);
+ g.fillRect(x, (int) (y + (h * (g1 + g2))), w,
+ (int) (h * (1. - (g1 + g2))));
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java
new file mode 100644
index 000000000..6a6a3f5aa
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java
@@ -0,0 +1,318 @@
+/* DefaultMetalTheme.java -- A modern theme for the Metal L&F
+ Copyright (C) 2005 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.Insets;
+import java.util.Arrays;
+
+import javax.swing.UIDefaults;
+import javax.swing.plaf.ColorUIResource;
+import javax.swing.plaf.BorderUIResource.LineBorderUIResource;
+
+/**
+ * A modern theme for the Metal Look &amp; Feel.
+ * @since 1.5
+ *
+ * @author Roman Kennke (roman@kennke.org)
+ */
+public class OceanTheme extends DefaultMetalTheme
+{
+ /**
+ * The OceanTheme value for black.
+ */
+ static final ColorUIResource BLACK = new ColorUIResource(51, 51, 51);
+
+ /**
+ * The OceanTheme value for primary1.
+ */
+ static final ColorUIResource PRIMARY1 = new ColorUIResource(99, 130, 191);
+
+ /**
+ * The OceanTheme value for primary1.
+ */
+ static final ColorUIResource PRIMARY2 = new ColorUIResource(163, 184, 204);
+
+ /**
+ * The OceanTheme value for primary1.
+ */
+ static final ColorUIResource PRIMARY3 = new ColorUIResource(184, 207, 229);
+
+ /**
+ * The OceanTheme value for secondary1.
+ */
+ static final ColorUIResource SECONDARY1 = new ColorUIResource(122, 138, 153);
+
+ /**
+ * The OceanTheme value for secondary2.
+ */
+ static final ColorUIResource SECONDARY2 = new ColorUIResource(184, 207, 229);
+
+ /**
+ * The OceanTheme value for secondary3.
+ */
+ static final ColorUIResource SECONDARY3 = new ColorUIResource(238, 238, 238);
+
+ /**
+ * The OceanTheme value for inactive control text.
+ */
+ static final ColorUIResource INACTIVE_CONTROL_TEXT =
+ new ColorUIResource(153, 153, 153);
+
+ /**
+ * Returns the name of this theme, &quot;Ocean&quot;
+ */
+ public String getName()
+ {
+ return "Ocean";
+ }
+
+ /**
+ * Returns the color for control text, which is the
+ * value of the theme's black value.
+ */
+ public ColorUIResource getControlTextColor()
+ {
+ return getBlack();
+ }
+
+ /**
+ * Returns the desktop color, which is the theme's white color.
+ */
+ public ColorUIResource getDesktopColor()
+ {
+ return getWhite();
+ }
+
+ /**
+ * Returns the color for inactive control text, which is the
+ * RGB value (153, 153, 153).
+ */
+ public ColorUIResource getInactiveControlTextColor()
+ {
+ return INACTIVE_CONTROL_TEXT;
+ }
+
+ /**
+ * Returns the OceanTheme's color for disabled menu foreground,
+ *
+ */
+ public ColorUIResource getMenuDisabledForeground()
+ {
+ return INACTIVE_CONTROL_TEXT;
+ }
+
+
+ /**
+ * Returns the OceanTheme's color for black, the RGB value
+ * (51, 51, 51).
+ *
+ * @return Returns the OceanTheme's value for black
+ */
+ protected ColorUIResource getBlack()
+ {
+ return BLACK;
+ }
+
+ /**
+ * Return the OceanTheme's value for primary 1, the RGB value
+ * (99, 130, 191).
+ */
+ protected ColorUIResource getPrimary1()
+ {
+ return PRIMARY1;
+ }
+
+ /**
+ * Return the OceanTheme's value for primary 2, the RGB value
+ * (163, 184, 204).
+ */
+ protected ColorUIResource getPrimary2()
+ {
+ return PRIMARY2;
+ }
+
+ /**
+ * Return the OceanTheme's value for primary 1, the RGB value
+ * (184, 207, 229).
+ */
+ protected ColorUIResource getPrimary3()
+ {
+ return PRIMARY3;
+ }
+
+ /**
+ * Return the OceanTheme's value for secondary 1, the RGB value
+ * (122, 138, 153).
+ */
+ protected ColorUIResource getSecondary1()
+ {
+ return SECONDARY1;
+ }
+
+ /**
+ * Return the OceanTheme's value for secondary 2, the RGB value
+ * (184, 207, 229).
+ */
+ protected ColorUIResource getSecondary2()
+ {
+ return SECONDARY2;
+ }
+ /**
+ * Return the OceanTheme's value for secondary 3, the RGB value
+ * (238, 238, 238).
+ */
+ protected ColorUIResource getSecondary3()
+ {
+ return SECONDARY3;
+ }
+
+ /**
+ * Adds customized entries to the UIDefaults table.
+ *
+ * @param defaults the UI defaults table
+ */
+ public void addCustomEntriesToTable(UIDefaults defaults)
+ {
+ // Gradients.
+ defaults.put("Button.gradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("CheckBox.gradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("CheckBoxMenuItem.gradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("MenuBar.gradient", Arrays.asList(new Object[]
+ {new Float(1.0), new Float(0.0), new ColorUIResource(Color.WHITE),
+ new ColorUIResource(218, 218, 218), new ColorUIResource(218, 218, 218)}));
+ defaults.put("RadioButton.gradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("RadioButtonMenuItem.gradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("ScrollBar.gradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("Slider.gradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.2), new ColorUIResource(200, 221, 242),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("Slider.focusGradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.2), new ColorUIResource(200, 221, 242),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("ToggleButton.gradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+ defaults.put("InternalFrame.activeTitleGradient", Arrays.asList(new Object[]
+ {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243),
+ new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)}));
+
+ // Colors.
+ ColorUIResource c1 = new ColorUIResource(200, 221, 242);
+ ColorUIResource c2 = new ColorUIResource(153, 153, 153);
+ ColorUIResource c3 = new ColorUIResource(204, 204, 204);
+ ColorUIResource c4 = new ColorUIResource(210, 226, 239);
+ ColorUIResource c5 = new ColorUIResource(218, 218, 218);
+ defaults.put("Button.disabledToolBarBorderBackground", c3);
+ defaults.put("Button.toolBarBorderBackground", c2);
+ defaults.put("Label.disabledForeground", c2);
+ defaults.put("MenuBar.borderColor", c3);
+ defaults.put("Slider.altTrackColor", c4);
+ defaults.put("SplitPane.dividerFocusColor", c1);
+ defaults.put("TabbedPane.contentAreaColor", c1);
+ defaults.put("TabbedPane.borderHightlightColor", PRIMARY1);
+ defaults.put("TabbedPane.selected", c1);
+ defaults.put("TabbedPane.tabAreaBackground", c5);
+ defaults.put("TabbedPane.unselectedBackground", SECONDARY3);
+ defaults.put("Table.gridColor", SECONDARY1);
+ defaults.put("ToolBar.borderColor", c3);
+ defaults.put("Tree.selectionBorderColor", PRIMARY1);
+
+ // Borders.
+ defaults.put("List.focusCellHighlightBorder",
+ new LineBorderUIResource(getPrimary1()));
+ defaults.put("Table.focusCellHighlightBorder",
+ new LineBorderUIResource(getPrimary1()));
+
+ // Insets.
+ defaults.put("TabbedPane.contentBorderInsets", new Insets(4, 2, 3, 3));
+ defaults.put("TabbedPane.tabAreaInsets", new Insets(2, 2, 0, 6));
+
+ // Flags.
+ defaults.put("SplitPane.oneTouchButtonsOpaque", Boolean.FALSE);
+ defaults.put("Menu.opaque", Boolean.FALSE);
+ defaults.put("ToolBar.isRollover", Boolean.TRUE);
+ defaults.put("RadioButton.rollover", Boolean.TRUE);
+ defaults.put("CheckBox.rollover", Boolean.TRUE);
+ defaults.put("Button.rollover", Boolean.TRUE);
+
+ // Icons.
+ // FIXME: Add OceanTheme icons.
+// defaults.put("Tree.leafIcon", XXX);
+// defaults.put("Tree.expandedIcon", XXX);
+// defaults.put("Tree.openIcon", XXX);
+// defaults.put("Tree.closedIcon", XXX);
+// defaults.put("Tree.collapsedIcon", XXX);
+// defaults.put("FileChooser.newFolderIcon", XXX);
+// defaults.put("FileChooser.homeFolderIcon", XXX);
+// defaults.put("FileChooser.upFolderIcon", XXX);
+// defaults.put("FileView.hardDriveIcon", XXX);
+// defaults.put("FileView.floppyDriveIcon", XXX);
+// defaults.put("FileView.fileIcon", XXX);
+// defaults.put("FileView.computerIcon", XXX);
+// defaults.put("FileView.directoryIcon", XXX);
+// defaults.put("OptionPane.questionIcon", XXX);
+// defaults.put("OptionPane.errorIcon", XXX);
+// defaults.put("OptionPane.warningIcon", XXX);
+// defaults.put("OptionPane.informationIcon", XXX);
+// defaults.put("InternalFrame.icon", XXX);
+// defaults.put("InternalFrame.closeIcon", XXX);
+// defaults.put("InternalFrame.iconifyIcon", XXX);
+// defaults.put("InternalFrame.minimizeIcon", XXX);
+// defaults.put("InternalFrame.maximizeIcon", XXX);
+// defaults.put("InternalFrame.paletteCloseIcon", XXX);
+
+ // UI classes.
+ defaults.put("MenuBarUI", "javax.swing.plaf.metal.MetalMenuBarUI");
+
+ // Others.
+ defaults.put("Button.rolloverIconType", "ocean");
+ }
+}
diff --git a/libjava/classpath/javax/swing/plaf/metal/package.html b/libjava/classpath/javax/swing/plaf/metal/package.html
new file mode 100644
index 000000000..8675493b6
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/metal/package.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in javax.swing.plaf.metal package.
+ Copyright (C) 2002, 2005 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. -->
+
+<html>
+<head><title>GNU Classpath - javax.swing.plaf.metal</title></head>
+
+<body>
+<p>Provides a cross-platform look and feel known as "Metal". To install this
+look and feel, add the following code (or something similar)
+near the start of your application:</p>
+<pre>try
+ {
+&nbsp;&nbsp;UIManager.setLookAndFeel(new MetalLookAndFeel());
+ }
+catch (UnsupportedLookAndFeelException e)
+ {
+&nbsp;&nbsp;e.printStackTrace();
+ }</pre>
+</body>
+</html>