diff options
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/metal')
36 files changed, 6324 insertions, 780 deletions
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java index f55510684c6..4fa3b364056 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java @@ -45,21 +45,29 @@ 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.UIDefaults; +import javax.swing.UIManager; import javax.swing.border.AbstractBorder; import javax.swing.border.Border; import javax.swing.plaf.BorderUIResource; import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicBorders; +import javax.swing.text.JTextComponent; /** - * This factory class creates borders for the different Swing components - * UI. + * A factory class that creates borders for the different Swing components. * * @author Roman Kennke (roman@kennke.org) */ @@ -69,12 +77,24 @@ 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 @@ -83,20 +103,19 @@ public class MetalBorders private static BasicBorders.MarginBorder marginBorder; /** - * The border that is drawn around Swing buttons. + * A border used for {@link JButton} components. */ - public static class ButtonBorder - extends AbstractBorder - implements UIResource + 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 ButtonBorder. + * Creates a new instance of <code>ButtonBorder</code>. */ public ButtonBorder() { + // Nothing to do here. } /** @@ -122,46 +141,55 @@ public class MetalBorders Color light = MetalLookAndFeel.getWhite(); Color middle = MetalLookAndFeel.getControl(); - // draw dark border - g.setColor(darkShadow); - g.drawRect(x, y, w - 2, h - 2); - - if (!bmodel.isPressed()) - { - // draw light border - g.setColor(light); - g.drawRect(x + 1, y + 1, w - 2, h - 2); + if (c.isEnabled()) + { + // draw dark border + g.setColor(darkShadow); + g.drawRect(x, y, w - 2, h - 2); - // draw crossing pixels of both borders - g.setColor(middle); - g.drawRect(x + 1, y + h - 2, 0, 0); - g.drawRect(x + w - 2, y + 1, 0, 0); - } - 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); + if (!bmodel.isPressed()) + { + // draw light border + g.setColor(light); + g.drawRect(x + 1, y + 1, w - 2, h - 2); - // 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(middle); + g.drawRect(x + 1, y + h - 2, 0, 0); + g.drawRect(x + w - 2, y + 1, 0, 0); + } + 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 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); + // 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); } } /** - * Returns the insets of the ButtonBorder. + * Returns the insets of the <code>ButtonBorder</code>. * * @param c the component for which the border is used * - * @return the insets of the ButtonBorder + * @return The insets of the ButtonBorder */ public Insets getBorderInsets(Component c) { @@ -169,19 +197,20 @@ public class MetalBorders } /** - * Returns the insets of the ButtonBorder in the specified Insets object. + * 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 - * @param newInsets the insets object where to put the values + * @param newInsets the insets object where to put the values (if + * <code>null</code>, a new instance is created). * - * @return the insets of the ButtonBorder + * @return The insets. */ public Insets getBorderInsets(Component c, Insets newInsets) { if (newInsets == null) newInsets = new Insets(0, 0, 0, 0); - AbstractButton b = (AbstractButton) c; newInsets.bottom = borderInsets.bottom; newInsets.left = borderInsets.left; newInsets.right = borderInsets.right; @@ -191,6 +220,71 @@ public class MetalBorders } /** + * 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 @@ -201,6 +295,7 @@ public class MetalBorders */ public Flush3DBorder() { + // Nothing to do here. } /** @@ -262,6 +357,88 @@ public class MetalBorders } /** + * 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 + { + /** + * 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 getBorderInsets(c, null); + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * @param newInsets the insets object that, if non-<code>null</code>, will + * be populated with the result from this method. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + if (newInsets == null) + newInsets = new Insets(1, 1, 1, 1); + else + { + newInsets.top = 1; + newInsets.left = 1; + newInsets.bottom = 1; + newInsets.right = 1; + } + 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 @@ -272,6 +449,7 @@ public class MetalBorders */ public TextFieldBorder() { + // Nothing to do here. } /** @@ -286,8 +464,17 @@ public class MetalBorders */ public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) - { - if (c.isEnabled()) + { + 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 { @@ -301,7 +488,7 @@ public class MetalBorders } /** - * A border used when painting {@link JInternalFrame} instances. + * A border used for the {@link JInternalFrame} component. */ public static class InternalFrameBorder extends AbstractBorder implements UIResource @@ -311,6 +498,7 @@ public class MetalBorders */ public InternalFrameBorder() { + // Nothing to do here. } /** @@ -386,7 +574,10 @@ public class MetalBorders g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15); // draw the line highlights - g.setColor(MetalLookAndFeel.getControl()); + 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); @@ -396,24 +587,129 @@ public class MetalBorders } /** + * 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(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + if (type == JOptionPane.QUESTION_MESSAGE) + { + Color bc = defaults.getColor( + "OptionPane.questionDialog.border.background"); + if (bc != null) + g.setColor(bc); + } + if (type == JOptionPane.WARNING_MESSAGE) + { + Color bc = defaults.getColor( + "OptionPane.warningDialog.border.background"); + if (bc != null) + g.setColor(bc); + } + else if (type == JOptionPane.ERROR_MESSAGE) + { + Color bc = defaults.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 + public static class MenuItemBorder extends AbstractBorder + implements UIResource { /** The border insets. */ - protected static Insets borderInsets = new Insets(2, 2, 2, 2); - - // TODO: find where the real colors come from - private static Color borderColorDark = new Color(102, 102, 153); - private static Color borderColorLight = new Color(255, 255, 255); + protected static Insets borderInsets = new Insets(1, 1, 1, 1); /** * Creates a new border instance. */ public MenuItemBorder() { + // Nothing to do here. } /** @@ -430,15 +726,17 @@ public class MetalBorders 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(borderColorDark); + 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(borderColorLight); + g.setColor(light); g.drawLine(x + w - 1, y + 1, x + w - 1, y + h); } } @@ -446,12 +744,18 @@ public class MetalBorders { JMenuItem item = (JMenuItem) c; if (item.isArmed()) - { - g.setColor(borderColorDark); - g.drawLine(x, y, x + w, y); - g.setColor(borderColorLight); - g.drawLine(x, y + h - 1, x + w, y + h - 1); - } + { + 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); + } } } @@ -505,6 +809,7 @@ public class MetalBorders */ public MenuBarBorder() { + // Nothing to do here. } /** @@ -558,7 +863,7 @@ public class MetalBorders } /** - * A border for JScrollPanes. + * A border for {@link JScrollPane} components. */ public static class ScrollPaneBorder extends AbstractBorder @@ -572,6 +877,7 @@ public class MetalBorders */ public ScrollPaneBorder() { + // Nothing to do here. } /** @@ -634,6 +940,45 @@ public class MetalBorders } /** + * 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) + { + boolean mouseIsOver = false; + if (c instanceof AbstractButton) + { + ButtonModel bmodel = ((AbstractButton) c).getModel(); + mouseIsOver = bmodel.isRollover(); + } + if (mouseIsOver) + super.paintBorder(c, g, x, y, w, h); + } + } + + /** * This border is used in Toolbar buttons as inner border. */ static class RolloverMarginBorder extends AbstractBorder @@ -646,6 +991,7 @@ public class MetalBorders */ public RolloverMarginBorder() { + // Nothing to do here. } /** @@ -693,13 +1039,14 @@ public class MetalBorders { /** The border's insets. */ - protected static Insets borderInsets = new Insets(2, 2, 1, 1); + protected static Insets borderInsets = new Insets(3, 1, 2, 1); /** * Constructs a new PopupMenuBorder. */ public PopupMenuBorder() { + // Nothing to do here. } /** @@ -763,13 +1110,258 @@ public class MetalBorders // draw highlighted inner border (only top and left) g.setColor(light); - g.drawLine(x + 1, y + 1, x + 1, y + h - 2); 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 & Feel. * * @return a border for Swing buttons in the Metal Look & Feel @@ -785,6 +1377,40 @@ public class MetalBorders } 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. @@ -796,11 +1422,36 @@ public class MetalBorders public static Border getTextFieldBorder() { if (textFieldBorder == null) - textFieldBorder = new TextFieldBorder(); + { + 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 & Feel. * * @return a border for Toolbar buttons in the Metal Look & Feel @@ -828,4 +1479,22 @@ public class MetalBorders 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 00000000000..e6fb22e929f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java @@ -0,0 +1,86 @@ +/* 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.UIResource; +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); + if (e.getPropertyName().equals( + AbstractButton.ROLLOVER_ENABLED_CHANGED_PROPERTY)) + { + AbstractButton b = (AbstractButton) e.getSource(); + if (b.getBorder() instanceof UIResource) + { + if (Boolean.TRUE.equals(e.getNewValue())) + b.setBorder(MetalBorders.getRolloverBorder()); + else if (Boolean.FALSE.equals(e.getNewValue())) + b.setBorder(MetalBorders.getButtonBorder()); + } + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java index 0dac5ec3953..02c39c1499e 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java @@ -39,18 +39,23 @@ 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.JButton; import javax.swing.JComponent; -import javax.swing.JToolBar; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicButtonListener; import javax.swing.plaf.basic.BasicButtonUI; /** - * The Metal Look & Feel implementation for - * {@link javax.swing.AbstractButton}s. + * A UI delegate for the {@link JButton} component. * * @author Roman Kennke (roman@kennke.org) */ @@ -58,27 +63,25 @@ public class MetalButtonUI extends BasicButtonUI { - /** The cached MetalButtonUI instance. */ - private static MetalButtonUI instance = null; - - /** The color for the focus border. */ + /** The color used to draw the focus rectangle around the text and/or icon. */ protected Color focusColor; - - /** The color that indicates a selected button. */ + + /** The background color for the button when it is pressed. */ protected Color selectColor; /** The color for disabled button labels. */ protected Color disabledTextColor; /** - * Creates a new instance of MetalButtonUI. + * Creates a new instance. */ public MetalButtonUI() { super(); - focusColor = getFocusColor(); - selectColor = getSelectColor(); - disabledTextColor = getDisabledTextColor(); + UIDefaults def = UIManager.getLookAndFeelDefaults(); + focusColor = def.getColor(getPropertyPrefix() + "focus"); + selectColor = def.getColor(getPropertyPrefix() + "select"); + disabledTextColor = def.getColor(getPropertyPrefix() + "disabledText"); } /** @@ -88,8 +91,7 @@ public class MetalButtonUI */ protected Color getFocusColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".focus"); + return focusColor; } /** @@ -99,8 +101,7 @@ public class MetalButtonUI */ protected Color getSelectColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".select"); + return selectColor; } /** @@ -110,36 +111,123 @@ public class MetalButtonUI */ protected Color getDisabledTextColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".disabledText"); + return disabledTextColor; } /** - * Returns an instance of MetalButtonUI. - * - * @param component a button for which a UI instance should be returned + * 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 component) - { - if (instance == null) - instance = new MetalButtonUI(); - return instance; + public static ComponentUI createUI(JComponent c) { + return new MetalButtonUI(); } /** - * Install the Look & Feel defaults for Buttons. - * - * @param button the button for which to install the Look & Feel + * Installs the default settings for the specified button. + * + * @param button the button. + * + * @see #uninstallDefaults(AbstractButton) */ public void installDefaults(AbstractButton button) { super.installDefaults(button); + if (button.isRolloverEnabled()) + { + if (button.getBorder() instanceof UIResource) + button.setBorder(MetalBorders.getRolloverBorder()); + } + } + + /** + * Removes the defaults added by {@link #installDefaults(AbstractButton)}. + */ + public void uninstallDefaults(AbstractButton button) + { + super.uninstallDefaults(button); + if (button.getBorder() instanceof UIResource) + button.setBorder(null); + } - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - button.setFont(defaults.getFont("Button.font")); + /** + * Returns a button listener for the specified button. + * + * @param button the button. + * + * @return A button listener. + */ + protected BasicButtonListener createButtonListener(AbstractButton button) + { + return new MetalButtonListener(button); + } - if (button.getParent() instanceof JToolBar) - button.setBorder(MetalBorders.getToolbarButtonBorder()); + /** + * 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()) + { + Rectangle area = b.getVisibleRect(); + g.setColor(selectColor); + g.fillRect(area.x, area.y, area.width, area.height); + } + } + + /** + * 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()); + } } - } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java index 3f3c9ce58b3..6b9f31b85b6 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java @@ -38,10 +38,8 @@ 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; @@ -49,8 +47,7 @@ import javax.swing.JCheckBox; import javax.swing.plaf.UIResource; /** - * An {@link Icon} implementation for {@link JCheckBox}es in the - * Metal Look & Feel. + * An {@link Icon} used by the {@link MetalCheckBoxUI} class. * * @author Roman Kennke (roman@kennke.org) */ @@ -79,7 +76,10 @@ public class MetalCheckBoxIcon */ protected void drawCheck(Component c, Graphics g, int x, int y) { - g.setColor(Color.BLACK); + 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); diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java index c46cb5f2fb1..b4f6f0a56cd 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java @@ -44,8 +44,7 @@ import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; /** - * A UI delegate for the {@link JCheckBox} component under the - * {@link MetalLookAndFeel}. + * A UI delegate for the {@link JCheckBox} component. */ public class MetalCheckBoxUI extends MetalRadioButtonUI @@ -64,11 +63,11 @@ public class MetalCheckBoxUI } /** - * Returns an instance of MetalCheckBoxUI. + * Returns a shared instance of <code>MetalCheckBoxUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalCheckBoxUI + * @return A shared instance of <code>MetalCheckBoxUI</code>. */ public static ComponentUI createUI(JComponent component) { 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 00000000000..6993e18e9b9 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java @@ -0,0 +1,241 @@ +/* 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.Component; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; + +import javax.swing.CellRendererPane; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JList; +import javax.swing.SwingUtilities; + +/** + * 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; + + /** ??? */ + 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. + * @parma 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; + } + + /** + * 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); + // TODO: figure out what this might need to be used for + // perhaps it has something to do with the button's icon and/or border? + } + + /** + * Paints the component. + * + * @param g the graphics device. + */ + public void paintComponent(Graphics g) + { + super.paintComponent(g); + if (iconOnly) + { + Rectangle bounds = getBounds(); + int x = (bounds.width - comboIcon.getIconWidth()) / 2; + int y = (bounds.height - comboIcon.getIconHeight()) / 2; + comboIcon.paintIcon(comboBox, g, x, y); + } + else + { + Object selected = comboBox.getModel().getSelectedItem(); + if (selected == null) + selected = ""; + Rectangle bounds = comboBox.getBounds(); + Rectangle innerArea = SwingUtilities.calculateInnerArea(this, null); + Insets insets = comboBox.getInsets(); + Rectangle renderArea = new Rectangle(innerArea.x, innerArea.y, + innerArea.width - comboIcon.getIconWidth() - 4, innerArea.height); + Component cellRenderer + = comboBox.getRenderer().getListCellRendererComponent(this.listBox, + selected, comboBox.getSelectedIndex(), false, false); + cellRenderer.setBackground(comboBox.getBackground()); + cellRenderer.setEnabled(comboBox.isEnabled()); + rendererPane.paintComponent(g, cellRenderer, this, renderArea); + if (comboBox.hasFocus()) + { + g.setColor(MetalLookAndFeel.getFocusColor()); + g.drawRect(innerArea.x, innerArea.y - 1, innerArea.width - 1, + innerArea.height); + } + int iconX = bounds.width - insets.right - comboIcon.getIconWidth() - 7; + int iconY = insets.top + + (bounds.height - comboIcon.getIconHeight()) / 2; + comboIcon.paintIcon(comboBox, g, iconX, iconY); + } + } +} 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 00000000000..a531079cb1d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java @@ -0,0 +1,143 @@ +/* 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.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + +import javax.swing.JTextField; +import javax.swing.plaf.basic.BasicComboBoxEditor; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.MetalBorders.Flush3DBorder; + +/** + * 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 Flush3DBorder + { + /** + * 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) + { + Color savedColor = g.getColor(); + if (c.isEnabled()) + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(x, y, x + w - 1, y); + g.drawLine(x, y, x, y + h - 2); + g.drawLine(x + 2, y + h - 2, x + w - 1, y + h - 2); + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); + g.setColor(MetalLookAndFeel.getWhite()); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + g.setColor(savedColor); + } + + /** + * 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. + } + } + + /** The editor's border insets. */ + protected static Insets editorBorderInsets = new Insets(4, 2, 4, 0); + + /** + * Creates a new editor. + */ + public MetalComboBoxEditor() + { + super(); + editor.setBorder(new MetalComboBoxEditorBorder()); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java index ce4fa7d32ce..f21c5af6136 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java @@ -1,4 +1,4 @@ -/* MetalComboBoxButton.java +/* MetalComboBoxIcon.java Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -88,10 +88,11 @@ public class MetalComboBoxIcon implements Icon, Serializable { */ public void paintIcon(Component c, Graphics g, int x, int y) { - // TODO: work out whether/how the icon changes with different component - // states (and also different metal themes) Color savedColor = g.getColor(); - g.setColor(Color.black); + 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 index 28c279d8ed6..a43ee3cb04f 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java @@ -38,20 +38,134 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.util.HashMap; +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.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.CellRendererPane; +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; -public class MetalComboBoxUI - extends BasicComboBoxUI -{ - /** The UI instances for JComboBoxes. */ - private static HashMap instances = null; +/** + * 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) + { + JComboBox cb = (JComboBox) parent; + if (!cb.isEditable()) + { + Rectangle bounds = parent.getBounds(); + arrowButton.setBounds(0, 0, bounds.width, bounds.height); + } + else + superLayout(parent); + } + + /** + * 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) + { + if (e.getPropertyName().equals("editable")) + editablePropertyChanged(e); + super.propertyChange(e); + } + } /** + * 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() @@ -68,19 +182,135 @@ public class MetalComboBoxUI */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); - - Object o = instances.get(component); - MetalComboBoxUI instance; - if (o == null) + 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 new MetalComboPopup(comboBox); + } + + /** + * Creates a new button for use in rendering the JComboBox. + * + * @return A button. + */ + protected JButton createArrowButton() + { + JButton button = new MetalComboBoxButton(comboBox, new MetalComboBoxIcon(), + new CellRendererPane(), 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()); + } + if (comboBox.isEditable()) { - instance = new MetalComboBoxUI(); - instances.put(component, instance); + arrowButton.setText(null); + if (editor != null) + editor.setVisible(true); } else - instance = (MetalComboBoxUI) o; - - return instance; + { + String text = ""; + Object selected = comboBox.getSelectedItem(); + if (selected != null) + text = selected.toString(); + arrowButton.setText(text); + if (editor != null) + editor.setVisible(true); + } + } + + /** + * 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) + { + Dimension d = getDisplaySize(); + MetalComboBoxButton b = (MetalComboBoxButton) arrowButton; + Insets insets = b.getInsets(); + int insetsH = insets.top + insets.bottom; + int insetsW = insets.left + insets.right; + if (!comboBox.isEditable()) + { + Icon icon = b.getComboIcon(); + int iconWidth = icon.getIconWidth() + 6; + return new Dimension(d.width + insetsW + iconWidth, d.height + insetsH); + } + else + // FIXME: the following dimensions pass most of the Mauve tests, but + // I don't yet understand the logic behind this...it is probably wrong + return new Dimension(d.width + insetsW + (d.height + insetsH) - 4, + d.height + insetsH + 1); } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java index 00870545bc6..ecbb76e6e7a 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java @@ -39,9 +39,13 @@ 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 { @@ -51,7 +55,7 @@ public class MetalDesktopIconUI private static MetalDesktopIconUI instance = null; /** - * Constructs a new instance of MetalDesktopIconUI. + * Constructs a new instance of <code>MetalDesktopIconUI</code>. */ public MetalDesktopIconUI() { @@ -59,11 +63,11 @@ public class MetalDesktopIconUI } /** - * Returns an instance of MetalDesktopIconUI. + * Returns a shared instance of <code>MetalDesktopIconUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalDesktopIconUI + * @return A shared instance of <code>MetalDesktopIconUI</code>. */ public static ComponentUI createUI(JComponent component) { 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 00000000000..3a2e1c13508 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java @@ -0,0 +1,430 @@ +/* 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.Component; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.AbstractListModel; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JList; +import javax.swing.UIManager; +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; + + +/** + * 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 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 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; + setText(v.getName(f)); + setIcon(v.getIcon(f)); + 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 int selectedIndex; + + /** + * Creates a new model. + */ + protected FilterComboBoxModel() + { + filters = new FileFilter[1]; + filters[0] = getAcceptAllFileFilter(getFileChooser()); + selectedIndex = 0; + } + + /** + * Handles property changes. + * + * @param e the property change event. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) + { + selectedIndex = -1; + FileFilter selected = (FileFilter) e.getNewValue(); + for (int i = 0; i < filters.length; i++) + if (filters[i].equals(selected)) + selectedIndex = i; + 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. + */ + public void setSelectedItem(Object filter) + { + // change the filter in the file chooser and let the property change + // event trigger the change to the selected item + getFileChooser().setFileFilter((FileFilter) filter); + } + + /** + * Returns the selected file filter. + * + * @return The selected file filter. + */ + public Object getSelectedItem() + { + if (selectedIndex >= 0) + return filters[selectedIndex]; + return null; + } + + /** + * 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 A component. + */ + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) + { + FileFilter filter = (FileFilter) value; + return super.getListCellRendererComponent(list, filter.getDescription(), + index, isSelected, cellHasFocus); + } + } + + /** The model for the directory combo box. */ + DirectoryComboBoxModel directoryModel; + + /** + * 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); + } + + /** + * 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 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(); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java index d8c77432653..6f4feccfc37 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java @@ -43,9 +43,11 @@ 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; @@ -75,6 +77,7 @@ public class MetalIconFactory implements Serializable */ public CheckBoxMenuItemIcon() { + // Nothing to do here. } /** @@ -137,6 +140,385 @@ public class MetalIconFactory implements Serializable } /** + * 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, 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, 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, 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, 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 + implements Icon, Serializable + { + /** + * 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). */ @@ -153,13 +535,15 @@ public class MetalIconFactory implements Serializable } /** - * Returns the height of the icon, in pixels. + * 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; + return 16 + getAdditionalHeight(); } /** @@ -192,9 +576,11 @@ public class MetalIconFactory implements Serializable } /** - * Returns the additional height (???). + * 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. + * @return The additional height (<code>0</code> unless overridden). */ public int getAdditionalHeight() { @@ -228,13 +614,15 @@ public class MetalIconFactory implements Serializable } /** - * Returns the height of the icon, in pixels. + * 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; + return 16 + getAdditionalHeight(); } /** @@ -265,9 +653,11 @@ public class MetalIconFactory implements Serializable } /** - * Returns the additional height (???). + * 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. + * @return The additional height (<code>0</code> unless overridden). */ public int getAdditionalHeight() { @@ -285,29 +675,77 @@ public class MetalIconFactory implements Serializable } } - + /** - * An {@link Icon} implementation for {@link JCheckBox}es in the - * Metal Look & Feel. - * - * @author Roman Kennke (roman@kennke.org) + * An icon used by the {@link MetalInternalFrameUI} class when the frame + * is displayed as a palette. + * + * @since 1.3 */ - static class RadioButtonIcon - implements Icon, UIResource, Serializable + public static class PaletteCloseIcon + implements Icon, Serializable, UIResource { /** - * Draws the check in the RadioButton. - * - * @param c the component to draw on - * @param g the Graphics context to draw with + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. */ - protected void drawCheck(Component c, Graphics g) + public int getIconWidth() { - g.setColor(MetalLookAndFeel.getBlack()); - g.fillRect(4, 3, 4, 6); - g.drawLine(3, 4, 3, 7); - g.drawLine(8, 4, 8, 7); + 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 & Feel. + * + * @author Roman Kennke (roman@kennke.org) + */ + static class RadioButtonIcon implements Icon, UIResource, Serializable + { /** * Returns the width of the icon in pixels. @@ -330,70 +768,104 @@ public class MetalIconFactory implements Serializable } /** - * Paints the icon. This first paints the border of the RadioButton and - * if the CheckBox is selected it calls {@link #drawCheck} to draw - * the check. + * Paints the icon, taking into account whether or not the component is + * enabled, selected and/or armed. * - * @param c the Component to draw on (gets casted to JCheckBox) + * @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) - { - Color dark = MetalLookAndFeel.getControlDarkShadow(); - Color light = MetalLookAndFeel.getWhite(); - g.translate(x, y); - - // The light 'circle' - g.setColor(light); - g.drawLine(4, 1, 10, 1); - g.drawLine(2, 2, 3, 2); - g.drawLine(8, 2, 11, 2); - g.drawLine(2, 3, 2, 3); - g.drawLine(11, 2, 11, 9); - g.drawLine(1, 4, 1, 7); - g.drawLine(12, 4, 12, 7); - g.drawLine(2, 8, 2, 11); - g.drawLine(11, 8, 11, 9); - g.drawLine(10, 10, 10, 10); - g.drawLine(2, 11, 9, 11); - g.drawLine(4, 12, 7, 12); - - // The dark 'circle' - g.setColor(dark); - g.drawLine(4, 0, 7, 0); - g.drawLine(2, 1, 3, 1); - g.drawLine(8, 1, 9, 1); - g.drawLine(1, 2, 1, 3); - g.drawLine(10, 2, 10, 3); - g.drawLine(0, 4, 0, 7); - g.drawLine(11, 4, 11, 7); - g.drawLine(1, 8, 1, 9); - g.drawLine(10, 8, 10, 9); - g.drawLine(2, 10, 3, 10); - g.drawLine(8, 10, 9, 10); - g.drawLine(4, 11, 7, 11); - - JRadioButton rb = (JRadioButton) c; - if (rb.isSelected()) - drawCheck(c, g); - - g.translate(-x, -y); - } + public void paintIcon(Component c, Graphics g, int x, int y) + { + 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, Serializable + private static class RadioButtonMenuItemIcon implements Icon, Serializable { /** * Creates a new icon instance. */ public RadioButtonMenuItemIcon() - { + { + // Nothing to do here. } /** @@ -463,8 +935,7 @@ public class MetalIconFactory implements Serializable * The icon used to display the thumb control on a horizontally oriented * {@link JSlider} component. */ - private static class HorizontalSliderThumbIcon - implements Icon, Serializable + private static class HorizontalSliderThumbIcon implements Icon, Serializable { /** @@ -472,6 +943,7 @@ public class MetalIconFactory implements Serializable */ public HorizontalSliderThumbIcon() { + // Nothing to do here. } /** @@ -505,13 +977,19 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { + boolean enabled = false; boolean focus = false; - if (c != null) - focus = c.hasFocus(); - // TODO: pick up the colors from the look and feel + if (c != null) + { + enabled = c.isEnabled(); + focus = c.hasFocus(); + } // draw the outline - g.setColor(Color.black); + 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); @@ -519,8 +997,11 @@ public class MetalIconFactory implements Serializable g.drawLine(x, y + 7, x, y + 1); // fill the icon - g.setColor(focus ? new Color(153, 153, 204) : new Color(204, 204, 204)); // medium - g.fillRect(x + 2, y + 2, 12, 7); + 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); @@ -528,33 +1009,42 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 6, y + 13, x + 8, y + 13); g.drawLine(x + 7, y + 14, x + 7, y + 14); - // draw highlights - g.setColor(focus ? new Color(204, 204, 255) : new Color(255, 255, 255)); // light - 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); + // if the slider is enabled, draw dots and highlights + if (c.isEnabled()) + { + 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 + 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); + g.drawLine(x + 5, y + 5, x + 5, y + 5); + g.drawLine(x + 9, y + 5, x + 9, y + 5); - // draw dots - g.setColor(focus ? new Color(102, 102, 153) : Color.black); // dark - 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 + 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); - g.drawLine(x + 5, y + 5, x + 5, y + 5); - g.drawLine(x + 9, y + 5, x + 9, y + 5); + // 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 + 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); + 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); + } } } @@ -563,7 +1053,7 @@ public class MetalIconFactory implements Serializable * An icon used for the 'close' button in the title frame of a * {@link JInternalFrame}. */ - private static class InternalFrameCloseIcon implements Icon, Serializable + private static class InternalFrameCloseIcon implements Icon, Serializable { /** The icon size in pixels. */ private int size; @@ -601,25 +1091,53 @@ public class MetalIconFactory implements Serializable /** * Paints the icon. * - * @param c the component. + * @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) { - // draw the gray areas first - g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + 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 + 4, y + 9, 2, 2); - g.fillRect(x + 9, y + 4, 2, 2); - g.fillRect(x + 9, y + 9, 2, 2); - g.fillRect(x + 5, y + 5, 5, 5); + 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); @@ -635,20 +1153,24 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 1, y + 14, x + 14, y + 14); g.drawLine(x + 14, y + 1, x + 14, y + 14); - 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); + 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, Serializable + private static class InternalFrameDefaultMenuIcon + implements Icon, Serializable { /** @@ -656,6 +1178,7 @@ public class MetalIconFactory implements Serializable */ public InternalFrameDefaultMenuIcon() { + // Nothing to do here. } /** @@ -718,8 +1241,8 @@ public class MetalIconFactory implements Serializable * maximise an internal frame, this icon will replace the 'maximise' icon to * provide a 'restore' option. */ - private static class InternalFrameAltMaximizeIcon - implements Icon, Serializable + private static class InternalFrameAltMaximizeIcon + implements Icon, Serializable { /** The icon size in pixels. */ private int size; @@ -764,14 +1287,23 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { - Color color = MetalLookAndFeel.getControlDarkShadow(); - if (c instanceof JInternalFrame) - { - JInternalFrame f = (JInternalFrame) c; - if (f.isSelected()) - color = MetalLookAndFeel.getPrimaryControlShadow(); - } - g.setColor(color); + 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); @@ -803,10 +1335,16 @@ public class MetalIconFactory implements Serializable 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 + 2, y + 6, x + 6, y + 6); - g.drawLine(x + 2, y + 6, x + 2, y + 11); 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); } } @@ -814,8 +1352,7 @@ public class MetalIconFactory implements Serializable * An icon used for the 'maximize' button in the title frame of a * {@link JInternalFrame}. */ - private static class InternalFrameMaximizeIcon - implements Icon, Serializable + private static class InternalFrameMaximizeIcon implements Icon, Serializable { /** @@ -823,6 +1360,7 @@ public class MetalIconFactory implements Serializable */ public InternalFrameMaximizeIcon() { + // Nothing to do here. } /** @@ -855,14 +1393,22 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { - Color color = MetalLookAndFeel.getControlDarkShadow(); - if (c instanceof JInternalFrame) - { - JInternalFrame f = (JInternalFrame) c; - if (f.isSelected()) - color = MetalLookAndFeel.getPrimaryControlShadow(); - } - g.setColor(color); + 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); @@ -897,9 +1443,12 @@ public class MetalIconFactory implements Serializable // draw white g.setColor(MetalLookAndFeel.getWhite()); - 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); + 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); @@ -908,14 +1457,14 @@ public class MetalIconFactory implements Serializable 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, Serializable + private static class InternalFrameMinimizeIcon implements Icon, Serializable { /** @@ -923,6 +1472,7 @@ public class MetalIconFactory implements Serializable */ public InternalFrameMinimizeIcon() { + // Nothing to do here. } /** @@ -955,14 +1505,17 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { - Color color = MetalLookAndFeel.getControlDarkShadow(); - if (c instanceof JInternalFrame) - { - JInternalFrame f = (JInternalFrame) c; - if (f.isSelected()) - color = MetalLookAndFeel.getPrimaryControlShadow(); - } - g.setColor(color); + 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); @@ -993,10 +1546,21 @@ public class MetalIconFactory implements Serializable 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 + 2, y + 9, x + 4, y + 9); - g.drawLine(x + 2, y + 10, x + 2, y + 11); 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); } } @@ -1004,13 +1568,14 @@ public class MetalIconFactory implements Serializable * The icon used to display the thumb control on a horizontally oriented * {@link JSlider} component. */ - private static class VerticalSliderThumbIcon implements Icon, Serializable + private static class VerticalSliderThumbIcon implements Icon, Serializable { /** * Creates a new instance. */ public VerticalSliderThumbIcon() { + // Nothing to do here. } /** @@ -1045,13 +1610,19 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { + boolean enabled = false; boolean focus = false; - if (c != null) - focus = c.hasFocus(); - // TODO: pick up the colors from the look and feel + if (c != null) + { + enabled = c.isEnabled(); + focus = c.hasFocus(); + } // draw the outline - g.setColor(Color.black); + 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); @@ -1059,8 +1630,11 @@ public class MetalIconFactory implements Serializable g.drawLine(x, y + 13, x, y + 1); // fill the icon - g.setColor(focus ? new Color(153, 153, 204) : new Color(204, 204, 204)); // medium - g.fillRect(x + 2, y + 2, 7, 12); + 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); @@ -1068,41 +1642,51 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 13, y + 6, x + 13, y + 8); g.drawLine(x + 14, y + 7, x + 14, y + 7); - // draw highlights - g.setColor(focus ? new Color(204, 204, 255) : new Color(255, 255, 255)); // light - 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); + // if the slider is enabled, draw dots and highlights + if (enabled) + { + 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 + 4, y + 4, x + 4, y + 4); - g.drawLine(x + 4, y + 8, x + 4, y + 8); + g.drawLine(x + 5, y + 5, x + 5, y + 5); + g.drawLine(x + 5, y + 9, x + 5, y + 9); - 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); + 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 dots - g.setColor(focus ? new Color(102, 102, 153) : Color.black); // dark - 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); + // 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 + 5, y + 5, x + 5, y + 5); - g.drawLine(x + 5, y + 9, x + 5, y + 9); + g.drawLine(x + 4, y + 4, x + 4, y + 4); + g.drawLine(x + 4, y + 8, x + 4, y + 8); - 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); + 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 + public static class TreeControlIcon implements Icon, Serializable { /** ???. */ @@ -1235,19 +1819,21 @@ public class MetalIconFactory implements Serializable /** * A tree folder icon. */ - public static class TreeFolderIcon extends FolderIcon16 + public static class TreeFolderIcon extends FolderIcon16 { /** * Creates a new instance. */ public TreeFolderIcon() - { + { + // Nothing to do here. } /** - * Returns the additional height (???). + * Returns the additional height for this icon, in this case <code>2</code> + * pixels. * - * @return The additional height. + * @return <code>2</code>. */ public int getAdditionalHeight() { @@ -1268,19 +1854,21 @@ public class MetalIconFactory implements Serializable /** * A tree leaf icon. */ - public static class TreeLeafIcon extends FileIcon16 + public static class TreeLeafIcon extends FileIcon16 { /** * Creates a new instance. */ public TreeLeafIcon() { + // Nothing to do here. } /** - * Returns the additional height (???). + * Returns the additional height for this icon, in this case <code>4</code> + * pixels. * - * @return The additional height. + * @return <code>4</code>. */ public int getAdditionalHeight() { @@ -1297,16 +1885,310 @@ public class MetalIconFactory implements Serializable return 2; } } + + /** + * An icon representing a hard disk. + * + * @see MetalIconFactory#getTreeHardDriveIcon() + */ + private static class TreeHardDriveIcon implements Icon, 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, 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, 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; + /** * Creates a new instance. All the methods are static, so creating an * instance isn't necessary. */ public MetalIconFactory() - { + { + // Nothing to do here. } /** @@ -1318,7 +2200,9 @@ public class MetalIconFactory implements Serializable */ public static Icon getCheckBoxIcon() { - return new MetalCheckBoxIcon(); + if (checkBoxIcon == null) + checkBoxIcon = new MetalCheckBoxIcon(); + return checkBoxIcon; } /** @@ -1329,7 +2213,69 @@ public class MetalIconFactory implements Serializable */ public static Icon getCheckBoxMenuItemIcon() { - return new CheckBoxMenuItemIcon(); + 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; } /** @@ -1351,7 +2297,9 @@ public class MetalIconFactory implements Serializable */ public static Icon getRadioButtonMenuItemIcon() { - return new RadioButtonMenuItemIcon(); + if (radioButtonMenuItemIcon == null) + radioButtonMenuItemIcon = new RadioButtonMenuItemIcon(); + return radioButtonMenuItemIcon; } /** @@ -1386,7 +2334,9 @@ public class MetalIconFactory implements Serializable */ public static Icon getInternalFrameDefaultMenuIcon() { - return new InternalFrameDefaultMenuIcon(); + if (internalFrameDefaultMenuIcon == null) + internalFrameDefaultMenuIcon = new InternalFrameDefaultMenuIcon(); + return internalFrameDefaultMenuIcon; } /** @@ -1475,4 +2425,40 @@ public class MetalIconFactory implements Serializable 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; + } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java index 20526eba8cd..33eb3491ad0 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java @@ -38,30 +38,208 @@ 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.UIDefaults; +import javax.swing.UIManager; import javax.swing.plaf.basic.BasicInternalFrameTitlePane; + /** - * The title pane for a {@link JInternalFrame}. + * 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 (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; - protected Icon paletteCloseIcon = MetalIconFactory.getInternalFrameCloseIcon(16); + /** + * 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; - protected int paletteTitleHeight = 12; - /** - * Creates a new title pane. + * Creates a new title pane for the specified frame. * * @param f the internal frame. */ @@ -81,6 +259,15 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane selectedTitleColor = MetalLookAndFeel.getWindowTitleBackground(); notSelectedTextColor = MetalLookAndFeel.getInactiveControlTextColor(); notSelectedTitleColor = MetalLookAndFeel.getWindowTitleInactiveBackground(); + + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + paletteTitleHeight = defaults.getInt("InternalFrame.paletteTitleHeight"); + paletteCloseIcon = defaults.getIcon("InternalFrame.paletteCloseIcon"); + minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16); + + title = new JLabel(frame.getTitle(), + MetalIconFactory.getInternalFrameDefaultMenuIcon(), + SwingConstants.LEFT); } /** @@ -93,6 +280,9 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane selectedTitleColor = null; notSelectedTextColor = null; notSelectedTitleColor = null; + paletteCloseIcon = null; + minIcon = null; + title = null; } /** @@ -128,44 +318,123 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane } /** - * Creates a layout manager for the components in the title pane. + * 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 {@link MetalTitlePaneLayout}. * - * @return A layout manager. - */ + * @return A new instance of {@link MetalTitlePaneLayout}. + */ protected LayoutManager createLayout() { - return new TitlePaneLayout() - { - public Dimension preferredLayoutSize(Container c) - { - return new Dimension(24, 24); - } - }; + return new MetalTitlePaneLayout(); } + /** + * Draws the title pane in the palette style. + * + * @param g the graphics device. + * + * @see #paintComponent(Graphics) + */ public void paintPalette(Graphics g) { - // FIXME: needs implementing - // most likely this is equivalent to paintComponent(g) when the isPalette - // flag is true + Color savedColor = g.getColor(); + Rectangle b = SwingUtilities.getLocalBounds(this); + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.fillRect(b.x, b.y, b.width, b.height); + 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) { - // probably need to check the isPalette flag here, if true pass over to - // paintPalette(Graphics) - super.paintComponent(g); - Dimension d = getSize(); - if (frame.isSelected()) - g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + Color savedColor = g.getColor(); + if (isPalette) + paintPalette(g); else - g.setColor(MetalLookAndFeel.getControlDarkShadow()); - g.drawLine(0, d.height - 1, d.width - 1, d.height - 1); + { + 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 + 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; + 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 index 7c7cb92e549..6be573f4bac 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java @@ -38,24 +38,31 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.util.HashMap; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JInternalFrame; -import javax.swing.border.EmptyBorder; 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 instances of MetalInternalFrameUI*/ - private static HashMap instances; + /** + * 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 MetalInternalFrameUI. + * Constructs a new instance of <code>MetalInternalFrameUI</code>. + * + * @param frame the frame. */ public MetalInternalFrameUI(JInternalFrame frame) { @@ -63,37 +70,96 @@ public class MetalInternalFrameUI } /** - * Returns an instance of MetalInternalFrameUI. + * Returns an instance of <code>MetalInternalFrameUI</code>. * - * @param component the component for which we return an UI instance + * @param component the internal frame. * - * @return an instance of MetalInternalFrameUI + * @return an instance of <code>MetalInternalFrameUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); - - - Object o = instances.get(component); - MetalInternalFrameUI instance; - if (o == null) - { - instance = new MetalInternalFrameUI((JInternalFrame) component); - instances.put(component, instance); - } - else - instance = (MetalInternalFrameUI) o; - - return instance; + 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); - titlePane.setBorder(new EmptyBorder(2, 2, 2, 2)); 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; + } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java index fe8a9e4e4ea..e4eaa71724d 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java @@ -50,17 +50,17 @@ import javax.swing.plaf.basic.BasicGraphicsUtils; import javax.swing.plaf.basic.BasicLabelUI; /** - * A UI delegate used for {@link JLabel}s in the {@link MetalLookAndFeel}. + * A UI delegate for the {@link JLabel} component. */ public class MetalLabelUI extends BasicLabelUI { - /** The shared UI instance for JLabels. */ + /** The shared instance of the UI delegate. */ protected static MetalLabelUI metalLabelUI; /** - * Constructs a new instance of MetalLabelUI. + * Constructs a new instance of <code>MetalLabelUI</code>. */ public MetalLabelUI() { @@ -68,11 +68,11 @@ public class MetalLabelUI } /** - * Returns an instance of MetalLabelUI. + * Returns a shared instance of <code>MetalLabelUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalLabelUI + * @return A shared instance of <code>MetalLabelUI</code>. */ public static ComponentUI createUI(JComponent component) { diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java index d9cf7c6220c..ec8014b17b3 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -42,11 +42,14 @@ import java.awt.Color; import java.awt.Font; import java.awt.Insets; +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; @@ -69,7 +72,8 @@ public class MetalLookAndFeel extends BasicLookAndFeel */ public MetalLookAndFeel() { - createDefaultTheme(); + if (theme == null) + createDefaultTheme(); } /** @@ -601,12 +605,21 @@ public class MetalLookAndFeel extends BasicLookAndFeel } /** - * Sets the current theme for the look and feel. + * 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. + * @param theme the theme (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>theme</code> is <code>null</code>. */ public static void setCurrentTheme(MetalTheme theme) { + if (theme == null) + throw new NullPointerException("Null 'theme' not permitted."); MetalLookAndFeel.theme = theme; } @@ -759,62 +772,206 @@ public class MetalLookAndFeel extends BasicLookAndFeel { super.initComponentDefaults(defaults); Object[] myDefaults = new Object[] { - "Button.background", new ColorUIResource(getControl()), + "Button.background", getControl(), "Button.border", MetalBorders.getButtonBorder(), - "Button.darkShadow", new ColorUIResource(getControlDarkShadow()), - "Button.disabledText", new ColorUIResource(getControlDisabled()), - "Button.focus", new ColorUIResource(getFocusColor()), + "Button.darkShadow", getControlDarkShadow(), + "Button.disabledText", getInactiveControlTextColor(), + "Button.focus", getFocusColor(), "Button.font", getControlTextFont(), - "Button.foreground", new ColorUIResource(getSystemTextColor()), - "Button.highlight", new ColorUIResource(getControlHighlight()), - "Button.light", new ColorUIResource(getControlHighlight()), - "Button.margin", new Insets(2, 14, 2, 14), - "Button.select", new ColorUIResource(getPrimaryControlShadow()), - "Button.shadow", new ColorUIResource(getPrimaryControlShadow()), - "CheckBox.background", new ColorUIResource(getControl()), + "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", new FontUIResource("Dialog", Font.BOLD, 12), + "CheckBox.foreground", getControlTextColor(), "CheckBox.icon", new UIDefaults.ProxyLazyValue ("javax.swing.plaf.metal.MetalCheckBoxIcon"), "CheckBox.checkIcon", new UIDefaults.ProxyLazyValue ("javax.swing.plaf.metal.MetalCheckBoxIcon"), - "CheckBoxMenuItem.background", new ColorUIResource(getControl()), + "Checkbox.select", getControlShadow(), + + "CheckBoxMenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10), + "CheckBoxMenuItem.acceleratorForeground", getAcceleratorForeground(), + "CheckBoxMenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(), + "CheckBoxMenuItem.background", getMenuBackground(), + "CheckBoxMenuItem.borderPainted", new Boolean(true), + "CheckBoxMenuItem.commandSound", "sounds/MenuItemCommand.wav", "CheckBoxMenuItem.checkIcon", MetalIconFactory.getCheckBoxMenuItemIcon(), - "ToolBar.background", new ColorUIResource(getControl()), - "Panel.background", new ColorUIResource(getControl()), - "Slider.background", new ColorUIResource(getControl()), - "OptionPane.background", new ColorUIResource(getControl()), - "ProgressBar.background", new ColorUIResource(getControl()), - "ScrollPane.border", new MetalBorders.ScrollPaneBorder(), - "TabbedPane.background", new ColorUIResource(getControl()), + "CheckBoxMenuItem.disabledForeground", getMenuDisabledForeground(), + "CheckBoxMenuItem.font", new FontUIResource("Dialog", Font.BOLD, 12), + "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", new FontUIResource("Dialog", Font.BOLD, 12), + "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(), + + "EditorPane.background", getWindowBackground(), + "EditorPane.caretForeground", getUserTextColor(), + "EditorPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "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(), + + "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.inactiveTitleBackground", getWindowTitleInactiveBackground(), + "InternalFrame.inactiveTitleForeground", getWindowTitleInactiveForeground(), "InternalFrame.maximizeIcon", MetalIconFactory.getInternalFrameMaximizeIcon(16), "InternalFrame.iconifyIcon", MetalIconFactory.getInternalFrameMinimizeIcon(16), - "Label.background", new ColorUIResource(getControl()), + "InternalFrame.paletteBorder", new MetalBorders.PaletteBorder(), + "InternalFrame.paletteCloseIcon", new MetalIconFactory.PaletteCloseIcon(), + "InternalFrame.paletteTitleHeight", new Integer(11), + + "Label.background", getControl(), + "Label.disabledForeground", getInactiveSystemTextColor(), + "Label.disabledShadow", getControlShadow(), "Label.font", getControlTextFont(), - "Label.disabledForeground", new ColorUIResource(getInactiveControlTextColor()), - "Label.foreground", new ColorUIResource(getControlTextColor()), - "Menu.background", new ColorUIResource(getControl()), + "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.background", getMenuBackground(), "Menu.border", new MetalBorders.MenuItemBorder(), "Menu.borderPainted", Boolean.TRUE, + "Menu.disabledForeground", getMenuDisabledForeground(), "Menu.font", getControlTextFont(), + "Menu.foreground", getMenuForeground(), "Menu.selectionBackground", getMenuSelectedBackground(), "Menu.selectionForeground", getMenuSelectedForeground(), - "MenuBar.background", new ColorUIResource(getControl()), + + "MenuBar.background", getMenuBackground(), "MenuBar.border", new MetalBorders.MenuBarBorder(), "MenuBar.font", getControlTextFont(), - "MenuItem.background", new ColorUIResource(getControl()), + "MenuBar.foreground", getMenuForeground(), + "MenuBar.highlight", getControlHighlight(), + "MenuBar.shadow", getControlShadow(), + + "MenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10), + "MenuItem.acceleratorForeground", getAcceleratorForeground(), + "MenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(), + "MenuItem.background", getMenuBackground(), "MenuItem.border", new MetalBorders.MenuItemBorder(), + "MenuItem.disabledForeground", getMenuDisabledForeground(), "MenuItem.font", getControlTextFont(), + "MenuItem.foreground", getMenuForeground(), "MenuItem.selectionBackground", getMenuSelectedBackground(), "MenuItem.selectionForeground", getMenuSelectedForeground(), - "Panel.background", new ColorUIResource(getControl()), + + "OptionPane.background", getControl(), + "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.inactiveBackground", getControl(), + "PasswordField.inactiveForeground", getInactiveSystemTextColor(), + "PasswordField.selectionBackground", getTextHighlightColor(), + "PasswordField.selectionForeground", getHighlightedTextColor(), + + "PopupMenu.background", getMenuBackground(), + "PopupMenu.border", new MetalBorders.PopupMenuBorder(), + "PopupMenu.font", new FontUIResource("Dialog", Font.BOLD, 12), + "PopupMenu.foreground", getMenuForeground(), + + "ProgressBar.background", getControl(), + "ProgressBar.border", new BorderUIResource.LineBorderUIResource(getControlDarkShadow(), 1), + "ProgressBar.font", new FontUIResource("Dialog", Font.BOLD, 12), + "ProgressBar.foreground", getPrimaryControlShadow(), + "ProgressBar.selectionBackground", getPrimaryControlDarkShadow(), + "ProgressBar.selectionForeground", getControl(), + + "RadioButton.background", getControl(), + "RadioButton.darkShadow", getControlDarkShadow(), + "RadioButton.disabledText", getInactiveControlTextColor(), "RadioButton.icon", new UIDefaults.LazyValue() { @@ -823,80 +980,199 @@ public class MetalLookAndFeel extends BasicLookAndFeel 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.disabledForeground", getMenuDisabledForeground(), "RadioButtonMenuItem.font", MetalLookAndFeel.getControlTextFont(), + "RadioButtonMenuItem.foreground", getMenuForeground(), "RadioButtonMenuItem.margin", new InsetsUIResource(2, 2, 2, 2), "RadioButtonMenuItem.selectionBackground", MetalLookAndFeel.getMenuSelectedBackground(), "RadioButtonMenuItem.selectionForeground", MetalLookAndFeel.getMenuSelectedForeground(), - "ScrollBar.background", new ColorUIResource(getControl()), - "ScrollBar.shadow", new ColorUIResource(getControlShadow()), - "ScrollBar.thumb", new ColorUIResource(getPrimaryControlShadow()), - "ScrollBar.thumbDarkShadow", - new ColorUIResource(getPrimaryControlDarkShadow()), - "ScrollBar.thumbHighlight", - new ColorUIResource(getPrimaryControl()), + "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(), - "SplitPane.darkShadow", - new ColorUIResource(getControlDarkShadow()), - "SplitPane.highlight", - new ColorUIResource(getControlHighlight()), + "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(), - "Slider.trackWidth", new Integer(7), - "Slider.majorTickLength", new Integer(6), - + + "Spinner.background", getControl(), + "Spinner.font", new FontUIResource("Dialog", Font.BOLD, 12), + "Spinner.foreground", getControl(), + + "SplitPane.background", getControl(), + "SplitPane.darkShadow", getControlDarkShadow(), + "SplitPane.dividerFocusColor", getPrimaryControl(), + "SplitPane.highlight", getControlHighlight(), + "SplitPane.shadow", getControlShadow(), + + "SplitPaneDivider.draggingColor", Color.DARK_GRAY, + + "TabbedPane.background", getControlShadow(), + "TabbedPane.darkShadow", getControlDarkShadow(), + "TabbedPane.focus", getPrimaryControlDarkShadow(), "TabbedPane.font", new FontUIResource("Dialog", Font.BOLD, 12), - "TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9), + "TabbedPane.foreground", getControlTextColor(), + "TabbedPane.highlight", getControlHighlight(), + "TabbedPane.light", getControl(), + "TabbedPane.selected", getControl(), + "TabbedPane.selectHighlight", getControlHighlight(), "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 2, 1), + "TabbedPane.shadow", getControlShadow(), + "TabbedPane.tabAreaBackground", getControl(), "TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6), - - "ToggleButton.background", new ColorUIResource(getControl()), - "ToggleButton.border", MetalBorders.getButtonBorder(), - "ToggleButton.darkShadow", new ColorUIResource(getControlDarkShadow()), - "ToggleButton.disabledText", new ColorUIResource(getControlDisabled()), - "ToggleButton.focus", new ColorUIResource(getFocusColor()), + "TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9), + + "Table.background", getWindowBackground(), + "Table.focusCellBackground", getWindowBackground(), + "Table.focusCellForeground", getControlTextColor(), + "Table.foreground", getControlTextColor(), + "Table.focusCellHighlightBorder", + new BorderUIResource.LineBorderUIResource(getControlShadow()), + "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.font", new FontUIResource("Dialog", Font.BOLD, 12), + "TitledBorder.titleColor", getSystemTextColor(), + + "ToggleButton.background", getControl(), + "ToggleButton.border", MetalBorders.getToggleButtonBorder(), + "ToggleButton.darkShadow", getControlDarkShadow(), + "ToggleButton.disabledText", getInactiveControlTextColor(), + "ToggleButton.focus", getFocusColor(), "ToggleButton.font", getControlTextFont(), - "ToggleButton.foreground", new ColorUIResource(getSystemTextColor()), - "ToggleButton.highlight", new ColorUIResource(getControlHighlight()), - "ToggleButton.light", new ColorUIResource(getControlHighlight()), - "ToggleButton.margin", new Insets(2, 14, 2, 14), - "ToggleButton.select", new ColorUIResource(getPrimaryControlShadow()), - "ToggleButton.shadow", new ColorUIResource(getPrimaryControlShadow()), - - "Tree.openIcon", MetalIconFactory.getTreeFolderIcon(), + "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", new FontUIResource("Dialog", Font.BOLD, 12), + "ToolBar.foreground", getMenuForeground(), + "ToolBar.highlight", getControlHighlight(), + "ToolBar.light", getControlHighlight(), + "ToolBar.shadow", getControlShadow(), + "ToolBar.border", new MetalBorders.ToolBarBorder(), + + "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(), + + "Tree.background", getWindowBackground(), "Tree.closedIcon", MetalIconFactory.getTreeFolderIcon(), - "Tree.leafIcon", MetalIconFactory.getTreeLeafIcon(), "Tree.collapsedIcon", MetalIconFactory.getTreeControlIcon(true), "Tree.expandedIcon", MetalIconFactory.getTreeControlIcon(false), - "Tree.font", new FontUIResource(new Font("Helvetica", Font.PLAIN, 12)), - "Tree.background", new ColorUIResource(Color.white), - "Tree.foreground", new ColorUIResource(new Color(204, 204, 255)), - "Tree.hash", new ColorUIResource(new Color(204, 204, 255)), + "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(20), "Tree.scrollsOnExpand", Boolean.TRUE, - "Tree.selectionBackground", new ColorUIResource(new Color(204, 204, 255)), - "Tree.nonSelectionBackground", new ColorUIResource(Color.white), - "Tree.selectionBorderColor", new ColorUIResource(new Color(102, 102, 153)), + "Tree.selectionBackground", getTextHighlightColor(), "Tree.selectionBorder", new BorderUIResource.LineBorderUIResource(new Color(102, 102, 153)), - "Tree.nonSelectionBorder", new BorderUIResource.LineBorderUIResource(Color.white), - "Tree.selectionForeground", new ColorUIResource(Color.black), - "Tree.textBackground", new ColorUIResource(new Color(204, 204, 255)), - "Tree.textForeground", new ColorUIResource(Color.black), - "Tree.selectionForeground", new ColorUIResource(Color.black), - "PopupMenu.border", new MetalBorders.PopupMenuBorder() + "Tree.selectionBorderColor", getFocusColor(), + "Tree.selectionForeground", getHighlightedTextColor(), + "Tree.textBackground", getWindowBackground(), + "Tree.textForeground", getUserTextColor(), + + "Viewport.background", getControl(), + "Viewport.foreground", getUserTextColor() }; defaults.putDefaults(myDefaults); } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java index ec9bf2b5586..44a2d3bcd6a 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java @@ -39,8 +39,12 @@ 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 { @@ -50,7 +54,7 @@ public class MetalPopupMenuSeparatorUI private static MetalPopupMenuSeparatorUI instance = null; /** - * Constructs a new instance of MetalPopupMenuSeparatorUI. + * Constructs a new instance of <code>MetalPopupMenuSeparatorUI</code>. */ public MetalPopupMenuSeparatorUI() { @@ -58,11 +62,11 @@ public class MetalPopupMenuSeparatorUI } /** - * Returns an instance of MetalPopupMenuSeparatorUI. + * Returns a shared instance of <code>MetalPopupMenuSeparatorUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalPopupMenuSeparatorUI + * @return A shared instance of <code>MetalPopupMenuSeparatorUI</code>. */ public static ComponentUI createUI(JComponent component) { diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java index 96d1988fd3d..0f28818b96c 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java @@ -38,20 +38,22 @@ 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; -public class MetalProgressBarUI - extends BasicProgressBarUI -{ - - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for MetalProgressBarUIs */ - private static MetalProgressBarUI instance = null; - +/** + * A UI delegate for the {@link JProgressBar} component. + */ +public class MetalProgressBarUI extends BasicProgressBarUI +{ /** - * Constructs a new instance of MetalProgressBarUI. + * Constructs a new instance of <code>MetalProgressBarUI</code>. */ public MetalProgressBarUI() { @@ -59,16 +61,87 @@ public class MetalProgressBarUI } /** - * Returns an instance of MetalProgressBarUI. + * Returns a new instance of <code>MetalProgressBarUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalProgressBarUI + * @return A new instance of <code>MetalProgressBarUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalProgressBarUI(); - return instance; + 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 index a668f914e43..f37626e630f 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java @@ -38,20 +38,38 @@ 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.UIDefaults; +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 { - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for JRadioButtons. */ - private static MetalRadioButtonUI instance = null; - + /** 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 MetalRadioButtonUI. + * Constructs a new instance of <code>MetalRadioButtonUI</code>. */ public MetalRadioButtonUI() { @@ -59,16 +77,108 @@ public class MetalRadioButtonUI } /** - * Returns an instance of MetalRadioButtonUI. + * Returns a new instance of <code>MetalRadioButtonUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalRadioButtonUI + * @return A new instance of <code>MetalRadioButtonUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalRadioButtonUI(); - return instance; + return new MetalRadioButtonUI(); + } + + /** + * Sets the default values for the specified button. + * + * @param b the button. + */ + public void installDefaults(AbstractButton b) + { + super.installDefaults(b); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + disabledTextColor = defaults.getColor("RadioButton.disabledText"); + focusColor = defaults.getColor("RadioButton.focus"); + selectColor = defaults.getColor("RadioButton.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 UIDefaults} 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 UIDefaults} 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 UIDefaults} 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 + 2, t.width + 2, t.height - 4); } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java index 4196a4e477c..faed80382d0 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java @@ -39,9 +39,16 @@ exception statement from your version. */ package javax.swing.plaf.metal; import javax.swing.JComponent; +import javax.swing.JRootPane; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicRootPaneUI; +/** + * A UI delegate for the {@link JRootPane} component. This class is not fully + * implemented. + * + * @since 1.4 + */ public class MetalRootPaneUI extends BasicRootPaneUI { @@ -51,7 +58,7 @@ public class MetalRootPaneUI private static MetalRootPaneUI instance = null; /** - * Constructs a new instance of MetalRootPaneUI. + * Constructs a shared instance of <code>MetalRootPaneUI</code>. */ public MetalRootPaneUI() { @@ -59,11 +66,11 @@ public class MetalRootPaneUI } /** - * Returns an instance of MetalRootPaneUI. + * Returns a shared instance of <code>MetalRootPaneUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalRootPaneUI + * @return A shared instance of <code>MetalRootPaneUI</code>. */ public static ComponentUI createUI(JComponent component) { diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java index 526dfb50ae2..9602ade9947 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java @@ -38,30 +38,106 @@ 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.util.HashMap; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JButton; import javax.swing.JComponent; +import javax.swing.JScrollBar; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicScrollBarUI; -public class MetalScrollBarUI - extends 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 */ - private static final Dimension MIN_THUMB_SIZE = new Dimension(18, 18); - - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for JScrollBars. */ - private static HashMap instances = null; + /** 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 MetalScrollBarUI. + * Constructs a new instance of <code>MetalScrollBarUI</code>, with no + * specific initialisation. */ public MetalScrollBarUI() { @@ -69,28 +145,192 @@ public class MetalScrollBarUI } /** - * Returns an instance of MetalScrollBarUI. + * Returns a new instance of <code>MetalScrollBarUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalScrollBarUI + * @return An instance of MetalScrollBarUI */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); + 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"); + 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}. + * + * @param orientation the orientation of the button ({@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} or {@link #WEST}). + * + * @return The button. + */ + protected JButton createDecreaseButton(int orientation) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + scrollBarWidth = defaults.getInt("ScrollBar.width"); + decreaseButton = new MetalScrollButton(orientation, scrollBarWidth, + isFreeStanding); + return decreaseButton; + } - Object o = instances.get(component); - MetalScrollBarUI instance; - if (o == null) + /** + * Creates a new button to use as the control at the upper end of the + * {@link JScrollBar}. + * + * @param orientation the orientation of the button ({@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} or {@link #WEST}). + * + * @return The button. + */ + protected JButton createIncreaseButton(int orientation) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + scrollBarWidth = defaults.getInt("ScrollBar.width"); + 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()) { - instance = new MetalScrollBarUI(); - instances.put(component, instance); + 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 - instance = (MetalScrollBarUI) o; - - return instance; + { + 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); + } + } } /** @@ -102,45 +342,139 @@ public class MetalScrollBarUI */ protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - // first we fill the background - g.setColor(thumbColor); - g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, - thumbBounds.height); + // 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 outer dark line - g.setColor(thumbDarkShadowColor); - g.drawRect(thumbBounds.x, thumbBounds.y, thumbBounds.width - 1, - thumbBounds.height - 1); + // draw the pattern + MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3, + thumbBounds.width - 6, thumbBounds.height - 6, + thumbHighlightColor, thumbLightShadowColor); + } - // draw the inner light line + /** + * 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 + 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); - g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1, - thumbBounds.x + thumbBounds.width - 2, - thumbBounds.y + 1); - g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1, - thumbBounds.x + 1, - thumbBounds.y + thumbBounds.height - 2); - + 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 UIDefaults def = UIManager.getLookAndFeelDefaults(); g.setColor(def.getColor("ScrollBar.shadow")); - g.drawLine(thumbBounds.x + 1, thumbBounds.y + thumbBounds.height, - thumbBounds.x + thumbBounds.width, - thumbBounds.y + thumbBounds.height); + g.drawLine(x + w, y + 1, x + w, y + h - 1); - // draw the pattern - MetalUtils.fillMetalPattern(g, thumbBounds.x + 3, thumbBounds.y + 3, - thumbBounds.width - 6, thumbBounds.height - 6, - thumbHighlightColor, thumbDarkShadowColor); } - + /** - * This method returns the minimum thumb size. + * 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 + 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 + UIDefaults def = UIManager.getLookAndFeelDefaults(); + g.setColor(def.getColor("ScrollBar.shadow")); + g.drawLine(x + 1, y + h, x + w - 2, y + h); + } + + /** + * 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() { - return MIN_THUMB_SIZE; + if (isFreeStanding) + return MIN_THUMB_SIZE_FREE_STANDING; + else + return MIN_THUMB_SIZE; } + } + 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 00000000000..84f9cfe494e --- /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.Color; +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; + } + + /** + * 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 index 3e1198b398d..d5bf175f92d 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java @@ -39,19 +39,18 @@ exception statement from your version. */ package javax.swing.plaf.metal; import javax.swing.JComponent; +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 { - - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for JScrollPanes. */ - private static MetalScrollPaneUI instance = null; - /** - * Constructs a new instance of MetalScrollPaneUI. + * Constructs a new instance of <code>MetalScrollPaneUI</code>. */ public MetalScrollPaneUI() { @@ -59,16 +58,14 @@ public class MetalScrollPaneUI } /** - * Returns an instance of MetalScrollPaneUI. + * Returns a shared instance of <code>MetalScrollPaneUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalScrollPaneUI + * @return A shared instance of <code>MetalScrollPaneUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalScrollPaneUI(); - return instance; + return new MetalScrollPaneUI(); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java index 6e78ccb7071..1d48e9be2b0 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java @@ -38,10 +38,20 @@ 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 { @@ -51,7 +61,7 @@ public class MetalSeparatorUI private static MetalSeparatorUI instance = null; /** - * Constructs a new instance of MetalSeparatorUI. + * Constructs a new instance of <code>MetalSeparatorUI</code>. */ public MetalSeparatorUI() { @@ -59,11 +69,11 @@ public class MetalSeparatorUI } /** - * Returns an instance of MetalSeparatorUI. + * Returns a shared instance of <code>MetalSeparatorUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalSeparatorUI + * @return A shared instance of <code>MetalSeparatorUI</code>. */ public static ComponentUI createUI(JComponent component) { @@ -71,4 +81,51 @@ public class MetalSeparatorUI 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 index 4b52c4b0041..08fb99d216c 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java @@ -42,8 +42,8 @@ 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 java.util.HashMap; import javax.swing.Icon; import javax.swing.JComponent; @@ -56,16 +56,59 @@ import javax.swing.plaf.basic.BasicSliderUI; /** * A UI delegate for the {@link JSlider} component. */ -public class MetalSliderUI - extends BasicSliderUI +public class MetalSliderUI extends BasicSliderUI { - // TODO: find a use for this + /** + * 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; - // TODO: find a use for this + /** + * The highlight color used for drawing the track rect when the slider is + * enabled. + */ protected static Color highlightColor; - // TODO: find a use for this + /** + * The shadow color used for drawing the track rect when the slider is + * enabled. + */ protected static Color darkShadowColor; /** The track width. */ @@ -85,17 +128,14 @@ public class MetalSliderUI /** 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; - - /** A key to look up the filledSlider setting in the {@link UIManager}. */ - protected final String SLIDER_FILL = "JSlider.isFilled"; - - /** The UI instances for MetalSliderUIs */ - private static HashMap instances; /** * Constructs a new instance. @@ -104,33 +144,27 @@ public class MetalSliderUI { super(null); filledSlider = UIManager.getBoolean(SLIDER_FILL); + darkShadowColor = MetalLookAndFeel.getControlDarkShadow(); + highlightColor = MetalLookAndFeel.getControlHighlight(); } /** - * Returns an instance of MetalSliderUI. + * Returns a new instance of <code>MetalSliderUI</code>. * - * @param component the component for which we return an UI instance + * @param component the component (ignored). * - * @return an instance of MetalSliderUI + * @return A new instance of <code>MetalSliderUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); - - Object o = instances.get(component); - MetalSliderUI instance; - if (o == null) - { - instance = new MetalSliderUI(); - instances.put(component, instance); - } - else - instance = (MetalSliderUI) o; - - return instance; + 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); @@ -140,6 +174,18 @@ public class MetalSliderUI } /** + * 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. @@ -153,46 +199,79 @@ public class MetalSliderUI } /** - * Creates a property change listener for the slider. - * - * @param slider the slider. - */ - protected PropertyChangeListener createPropertyChangeListener(JSlider slider) - { - // TODO: try to figure out why it might be necessary to override this - // method as is done in Sun's implementation - return super.createPropertyChangeListener(slider); - } - - /** * 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) - { - if (filledSlider) { - // TODO: fill the track + int trackX = trackRect.x; + int trackY = trackRect.y + (trackRect.height - getTrackWidth()) / 2; + int trackW = trackRect.width - 1; + 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 (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); + } + } } - BasicGraphicsUtils.drawEtchedRect(g, trackRect.x, trackRect.y - + (trackRect.height - getTrackWidth()) / 2, trackRect.width - 1, - getTrackWidth(), Color.darkGray, Color.gray, Color.darkGray, - Color.white); - } else - { - if (filledSlider) { - // TODO: fill the track + int trackX = trackRect.x + (trackRect.width - getTrackWidth()) / 2; + int trackY = trackRect.y; + int trackW = getTrackWidth(); + int trackH = trackRect.height - 1; + 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); + } + + 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); + } + } } - BasicGraphicsUtils.drawEtchedRect(g, trackRect.x + (trackRect.width - - getTrackWidth()) / 2, trackRect.y, getTrackWidth(), - trackRect.height - 1, Color.darkGray, Color.gray, Color.darkGray, - Color.white); - } } /** @@ -262,12 +341,13 @@ public class MetalSliderUI */ protected int getThumbOverhang() { - // TODO: figure out what this is used for + // 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); } @@ -283,8 +363,10 @@ public class MetalSliderUI { // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... - // TODO: get color from UIManager... - g.setColor(new Color(153, 153, 204)); + if (slider.isEnabled()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength / 2); } @@ -300,8 +382,10 @@ public class MetalSliderUI { // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... - // TODO: get color from UIManager... - g.setColor(new Color(153, 153, 204)); + if (slider.isEnabled()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength); } @@ -317,8 +401,10 @@ public class MetalSliderUI { // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... - // TODO: get color from UIManager... - g.setColor(new Color(153, 153, 204)); + if (slider.isEnabled()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(TICK_BUFFER - 1, y, TICK_BUFFER - 1 + tickLength / 2, y); } @@ -334,8 +420,10 @@ public class MetalSliderUI { // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... - // TODO: get color from UIManager... - g.setColor(new Color(153, 153, 204)); + if (slider.isEnabled()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(TICK_BUFFER - 1, y, TICK_BUFFER - 1 + tickLength, y); } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java index 60e9c055952..016e09557d6 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java @@ -78,7 +78,7 @@ class MetalSplitPaneDivider extends BasicSplitPaneDivider { //super.paint(g); Dimension s = getSize(); - MetalUtils.fillMetalPattern(g, 2, 2, s.width - 4, s.height - 4, + MetalUtils.fillMetalPattern(splitPane, g, 2, 2, s.width - 4, s.height - 4, light, dark); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java index b7ea8984b43..b39fb23366e 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java @@ -39,24 +39,22 @@ exception statement from your version. */ package javax.swing.plaf.metal; import java.awt.Color; -import java.util.HashMap; import javax.swing.JComponent; +import javax.swing.JSplitPane; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSplitPaneUI; import javax.swing.plaf.basic.BasicSplitPaneDivider; +import javax.swing.plaf.basic.BasicSplitPaneUI; -public class MetalSplitPaneUI - extends BasicSplitPaneUI +/** + * A UI delegate for the {@link JSplitPane} component. + */ +public class MetalSplitPaneUI extends BasicSplitPaneUI { - - /** The UI instances for MetalSplitPaneUIs */ - private static HashMap instances; - /** - * Constructs a new instance of MetalSplitPaneUI. + * Constructs a new instance of <code>MetalSplitPaneUI</code>. */ public MetalSplitPaneUI() { @@ -64,28 +62,15 @@ public class MetalSplitPaneUI } /** - * Returns an instance of MetalSplitPaneUI. + * Returns a new instance of <code>MetalSplitPaneUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalSplitPaneUI + * @return A new instance of <code>MetalSplitPaneUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); - - Object o = instances.get(component); - MetalSplitPaneUI instance; - if (o == null) - { - instance = new MetalSplitPaneUI(); - instances.put(component, instance); - } - else - instance = (MetalSplitPaneUI) o; - - return instance; + return new MetalSplitPaneUI(); } /** diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java index 1b5fe144f6c..b1e02c7a6b0 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java @@ -40,7 +40,6 @@ package javax.swing.plaf.metal; import java.awt.Graphics; import java.awt.LayoutManager; -import java.util.HashMap; import javax.swing.JComponent; import javax.swing.JTabbedPane; @@ -48,11 +47,9 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicTabbedPaneUI; /** - * A UI delegate used for the {@link JTabbedPane} component in the - * {@link MetalLookAndFeel}. + * A UI delegate for the {@link JTabbedPane} component. */ -public class MetalTabbedPaneUI - extends BasicTabbedPaneUI +public class MetalTabbedPaneUI extends BasicTabbedPaneUI { /** @@ -65,13 +62,14 @@ public class MetalTabbedPaneUI * public for compatibility. */ public class TabbedPaneLayout - extends BasicTabbedPaneUI.TabbedPaneLayout + extends BasicTabbedPaneUI.TabbedPaneLayout { /** * Creates a new instance of the layout manager. */ public TabbedPaneLayout() { + // Nothing to do here. } /** @@ -102,9 +100,6 @@ public class MetalTabbedPaneUI } } - /** The shared UI instance for JTabbedPanes. */ - private static HashMap instances = null; - /** * Constructs a new instance of MetalTabbedPaneUI. */ @@ -122,20 +117,7 @@ public class MetalTabbedPaneUI */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); - - Object o = instances.get(component); - MetalTabbedPaneUI instance; - if (o == null) - { - instance = new MetalTabbedPaneUI(); - instances.put(component, instance); - } - else - instance = (MetalTabbedPaneUI) o; - - return instance; + return new MetalTabbedPaneUI(); } /** @@ -145,7 +127,7 @@ public class MetalTabbedPaneUI */ protected LayoutManager createLayoutManager() { - return new TabbedPaneLayout(); + return super.createLayoutManager(); } /** diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java index d6e50e12239..6984daeccbe 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java @@ -38,19 +38,16 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.util.HashMap; - import javax.swing.JComponent; +import javax.swing.JTextField; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicTextFieldUI; -public class MetalTextFieldUI - extends BasicTextFieldUI +/** + * A UI delegate for the {@link JTextField} component. + */ +public class MetalTextFieldUI extends BasicTextFieldUI { - - /** The UI instances for MetalTextFieldUIs */ - private static HashMap instances = null; - /** * Constructs a new instance of MetalTextFieldUI. */ @@ -60,27 +57,14 @@ public class MetalTextFieldUI } /** - * Returns an instance of MetalTextFieldUI. + * Returns a new instance of <code>MetalTextFieldUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalTextFieldUI + * @return A new instance of <code>MetalTextFieldUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); - - Object o = instances.get(component); - MetalTextFieldUI instance; - if (o == null) - { - instance = new MetalTextFieldUI(); - instances.put(component, instance); - } - else - instance = (MetalTextFieldUI) o; - - return instance; + return new MetalTextFieldUI(); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java index be6d0c39ec8..46a19bdbe9e 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java @@ -39,13 +39,24 @@ 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.JComponent; +import javax.swing.JToggleButton; +import javax.swing.SwingUtilities; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +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 { @@ -59,21 +70,26 @@ public class MetalToggleButtonUI /** The color for disabled button labels. */ protected Color disabledTextColor; - /** The shared UI instance for MetalToggleButtonUIs */ - private static MetalToggleButtonUI instance = null; + /** + * 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 MetalToggleButtonUI. + * Constructs a new instance of <code>MetalToggleButtonUI</code>. */ public MetalToggleButtonUI() { super(); - focusColor = getFocusColor(); - selectColor = getSelectColor(); - disabledTextColor = getDisabledTextColor(); } - /** * Returns the color for the focus border. * @@ -81,8 +97,7 @@ public class MetalToggleButtonUI */ protected Color getFocusColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".focus"); + return focusColor; } /** @@ -92,32 +107,98 @@ public class MetalToggleButtonUI */ protected Color getSelectColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".select"); + return selectColor; } /** - * Returns the color for the text label of disabled buttons. + * 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 + * @return The color for the text label of disabled buttons. */ protected Color getDisabledTextColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".disabledText"); + return disabledTextColor; } /** - * Returns an instance of MetalToggleButtonUI. - * - * @param component the component for which we return an UI instance - * - * @return an instance of MetalToggleButtonUI + * Updates the button with the defaults for this look and feel. + * + * @param b the button. */ - public static ComponentUI createUI(JComponent component) + public void installDefaults(AbstractButton b) + { + super.installDefaults(b); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + focusColor = defaults.getColor(getPropertyPrefix() + "focus"); + selectColor = defaults.getColor(getPropertyPrefix() + "select"); + disabledTextColor = defaults.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. + * + * @param g the graphics device. + * @param c the component. + * @param textRect the bounds for the text. + * @param text the text. + * + * @deprecated 1.4 Use {@link BasicButtonUI#paintText(java.awt.Graphics, + * javax.swing.AbstractButton, java.awt.Rectangle, java.lang.String)}. + */ + 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 (instance == null) - instance = new MetalToggleButtonUI(); - return instance; + 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); } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java index 39af0011ae6..c5ca91399ab 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java @@ -38,20 +38,73 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.event.ContainerListener; +import java.beans.PropertyChangeListener; + import javax.swing.JComponent; +import javax.swing.JToolBar; +import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicToolBarUI; -public class MetalToolBarUI - extends 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. + } + } - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for MetalToolBarUIs */ - private static MetalToolBarUI instance = null; + /** + * 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; /** - * Constructs a new instance of MetalToolBarUI. + * Creates a new instance of this UI delegate. */ public MetalToolBarUI() { @@ -59,16 +112,51 @@ public class MetalToolBarUI } /** - * Returns an instance of MetalToolBarUI. + * Returns a new instance of <code>MetalToolBarUI</code>. * - * @param component the component for which we return an UI instance + * @param component the component for which we return an UI instance * - * @return an instance of MetalToolBarUI + * @return A new instance of <code>MetalToolBarUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalToolBarUI(); - return instance; + 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(); } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java index c88b6534ab7..5085d170ac2 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java @@ -38,32 +38,92 @@ 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.Insets; +import java.awt.Rectangle; +import java.awt.Toolkit; +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.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +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; - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for MetalToolTipUIs */ + /** The shared UI instance. */ private static MetalToolTipUI instance = null; - + + /** 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 MetalToolTipUI. + * Constructs a new instance of <code>MetalToolTipUI</code>. */ public MetalToolTipUI() { super(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + activeBorder = defaults.getBorder("ToolTip.border"); + inactiveBorder = defaults.getBorder("ToolTip.borderInactive"); + isAcceleratorHidden = defaults.getBoolean("ToolTip.hideAccelerator"); + acceleratorFont = defaults.getFont("MenuItem.acceleratorFont"); + acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground"); + acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter"); } /** - * Returns an instance of MetalToolTipUI. + * 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 for which we return an UI instance + * @param component the component (a {@link JToolTip}). * - * @return an instance of MetalToolTipUI + * @return A shared instance of the <code>MetalToolTipUI</code> class. */ public static ComponentUI createUI(JComponent component) { @@ -71,4 +131,202 @@ public class MetalToolTipUI 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) + { + if (isAcceleratorHidden()) + return super.getPreferredSize(c); + else + { + Insets insets = c.getInsets(); + JToolTip tt = (JToolTip) c; + String tipText = tt.getTipText(); + if (tipText != null) + { + FontMetrics fm = c.getFontMetrics(c.getFont()); + int prefH = fm.getHeight() + insets.top + insets.bottom; + int prefW = fm.stringWidth(tipText) + insets.left + insets.right; + + // this seems to be the first opportunity we have to get the + // accelerator string from the component (if it has one) + acceleratorString = fetchAcceleratorString(c); + if (acceleratorString != null) + { + prefW += padSpaceBetweenStrings; + fm = c.getFontMetrics(acceleratorFont); + prefW += fm.stringWidth(acceleratorString); + } + return new Dimension(prefW, prefH); + } + else return new Dimension(0, 0); + } + } + + /** + * Paints the tool tip. + * + * @param g the graphics context. + * @param c the {@link JToolTip} component. + */ + public void paint(Graphics g, JComponent c) + { + JToolTip tip = (JToolTip) c; + + String text = tip.getTipText(); + Toolkit t = tip.getToolkit(); + if (text == null) + return; + + Rectangle vr = new Rectangle(); + vr = SwingUtilities.calculateInnerArea(tip, vr); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + FontMetrics fm = t.getFontMetrics(tip.getFont()); + int ascent = fm.getAscent(); + SwingUtilities.layoutCompoundLabel(tip, fm, text, null, + SwingConstants.CENTER, SwingConstants.LEFT, + SwingConstants.CENTER, SwingConstants.CENTER, vr, ir, tr, 0); + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawString(text, vr.x, vr.y + ascent); + + // paint accelerator + if (acceleratorString != null) + { + g.setFont(acceleratorFont); + g.setColor(acceleratorForeground); + fm = t.getFontMetrics(acceleratorFont); + int width = fm.stringWidth(acceleratorString); + g.drawString(acceleratorString, vr.x + vr.width - width - padSpaceBetweenStrings/2, + vr.y + vr.height - fm.getDescent()); + } + + g.setColor(saved); + } + + /** + * 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 index 8d16f7463fe..0ffa0d17470 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java @@ -38,21 +38,50 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.util.HashMap; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ComponentListener; +import java.awt.event.FocusListener; +import java.awt.event.KeyListener; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeListener; +import java.util.Hashtable; import javax.swing.JComponent; +import javax.swing.JTree; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import javax.swing.event.CellEditorListener; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicTreeUI; -public class MetalTreeUI - extends BasicTreeUI +/** + * A UI delegate for the {@link JTree} component. + */ +public class MetalTreeUI extends BasicTreeUI { - /** The UI instances for MetalTreeUIs */ - private static HashMap instances = null; - + /** Listeners */ + private PropertyChangeListener propertyChangeListener; + private FocusListener focusListener; + private TreeSelectionListener treeSelectionListener; + private MouseListener mouseListener; + private KeyListener keyListener; + private PropertyChangeListener selectionModelPropertyChangeListener; + private ComponentListener componentListener; + private CellEditorListener cellEditorListener; + private TreeExpansionListener treeExpansionListener; + private TreeModelListener treeModelListener; + /** - * Constructs a new instance of MetalTreeUI. + * Constructs a new instance of <code>MetalTreeUI</code>. */ public MetalTreeUI() { @@ -60,27 +89,238 @@ public class MetalTreeUI } /** - * Returns an instance of MetalTreeUI. + * Returns a new instance of <code>MetalTreeUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalTreeUI + * @return A new instance of <code>MetalTreeUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); + 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) + { + tree = (JTree) c; + configureLayoutCache(); + + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + tree.setFont(defaults.getFont("Tree.font")); + tree.setForeground(defaults.getColor("Tree.foreground")); + tree.setBackground(defaults.getColor("Tree.background")); + tree.setOpaque(true); + tree.setScrollsOnExpand(defaults.getBoolean("Tree.scrollsOnExpand")); + rightChildIndent = defaults.getInt("Tree.rightChildIndent"); + leftChildIndent = defaults.getInt("Tree.leftChildIndent"); + setRowHeight(defaults.getInt("Tree.rowHeight")); + tree.setRowHeight(defaults.getInt("Tree.rowHeight")); + tree.requestFocusInWindow(false); + + setExpandedIcon(defaults.getIcon("Tree.expandedIcon")); + setCollapsedIcon(defaults.getIcon("Tree.collapsedIcon")); + + currentCellRenderer = createDefaultCellRenderer(); + rendererPane = createCellRendererPane(); + createdRenderer = true; + setCellEditor(createDefaultCellEditor()); + createdCellEditor = true; + TreeModel mod = tree.getModel(); + setModel(mod); + + treeSelectionModel = tree.getSelectionModel(); + drawingCache = new Hashtable(); + nodeDimensions = createNodeDimensions(); + + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + treeSelectionListener = createTreeSelectionListener(); + mouseListener = createMouseListener(); + keyListener = createKeyListener(); + selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener(); + componentListener = createComponentListener(); + cellEditorListener = createCellEditorListener(); + treeExpansionListener = createTreeExpansionListener(); + treeModelListener = createTreeModelListener(); - Object o = instances.get(component); - MetalTreeUI instance; - if (o == null) + editingRow = -1; + lastSelectedRow = -1; + + installKeyboardActions(); + + tree.addPropertyChangeListener(propertyChangeListener); + tree.addFocusListener(focusListener); + tree.addTreeSelectionListener(treeSelectionListener); + tree.addMouseListener(mouseListener); + tree.addKeyListener(keyListener); + tree.addPropertyChangeListener(selectionModelPropertyChangeListener); + tree.addComponentListener(componentListener); + tree.addTreeExpansionListener(treeExpansionListener); + if (treeModel != null) + treeModel.addTreeModelListener(treeModelListener); + + if (mod != null) { - instance = new MetalTreeUI(); - instances.put(component, instance); + TreePath path = new TreePath(mod.getRoot()); + if (!tree.isExpanded(path)) + toggleExpandState(path); } - else - instance = (MetalTreeUI) o; + + completeUIInstall(); + } + + /** + * 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) + { + tree.setFont(null); + tree.setForeground(null); + tree.setBackground(null); + + uninstallKeyboardActions(); + + tree.removePropertyChangeListener(propertyChangeListener); + tree.removeFocusListener(focusListener); + tree.removeTreeSelectionListener(treeSelectionListener); + tree.removeMouseListener(mouseListener); + tree.removeKeyListener(keyListener); + tree.removePropertyChangeListener(selectionModelPropertyChangeListener); + tree.removeComponentListener(componentListener); + tree.removeTreeExpansionListener(treeExpansionListener); + + TreeCellEditor tce = tree.getCellEditor(); + if (tce != null) + tce.removeCellEditorListener(cellEditorListener); + TreeModel tm = tree.getModel(); + if (tm != null) + tm.removeTreeModelListener(treeModelListener); + + tree = null; + uninstallComponents(); + completeUIUninstall(); + } + + /** + * 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) + { + // FIXME: not implemented + } - return instance; + /** + * 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); + } + + /** + * Paints the horizontal separators. + * + * @param g - the current graphics configuration. + * @param c - the current component to draw + */ + protected void paintHorizontalSeparators(Graphics g, JComponent c) + { + // FIXME: not implemented + } + + + /** + * 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) + { + 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) + { + 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 index a342ee02bd3..c0b4e657676 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java @@ -1,4 +1,4 @@ -/* Metaltils.java +/* MetalUtils.java Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,7 +38,12 @@ 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.Graphics2D; +import java.awt.TexturePaint; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; /** * Some utility and helper methods for the Metal Look & Feel. @@ -49,6 +54,21 @@ 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 @@ -57,31 +77,78 @@ class MetalUtils * @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 w the height 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(Graphics g, int x, int y, int w, int h, + static void fillMetalPattern(Component c, Graphics g, int x, int y, int w, int h, Color light, Color dark) { - int xOff = 0; - for (int mY = y; mY < (y + h); mY++) + if (g instanceof Graphics2D) + fillMetalPattern2D((Graphics2D) g, x, y, w, h, light, dark); + else { - // set color alternating with every line - if ((mY % 2) == 0) - g.setColor(light); - else - g.setColor(dark); - - for (int mX = x + (xOff); mX < (x + w); mX += 4) + int xOff = 0; + for (int mY = y; mY < (y + h); mY++) { - g.drawLine(mX, mY, mX, 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.drawLine(mX, mY, mX, mY); + } + + // 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); + } - // increase x offset - xOff++; - if (xOff > 3) - xOff = 0; - } + /** + * 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(); } } 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 00000000000..85a8cb1ff86 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java @@ -0,0 +1,209 @@ +/* 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 javax.swing.UIDefaults; +import javax.swing.plaf.ColorUIResource; + +/** + * A modern theme for the Metal Look & 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, "Ocean" + */ + 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) + { + defaults.put("Button.rollover", Boolean.TRUE); + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/package.html b/libjava/classpath/javax/swing/plaf/metal/package.html index 2ea787bb5e2..8675493b68c 100644 --- a/libjava/classpath/javax/swing/plaf/metal/package.html +++ b/libjava/classpath/javax/swing/plaf/metal/package.html @@ -40,7 +40,16 @@ exception statement from your version. --> <head><title>GNU Classpath - javax.swing.plaf.metal</title></head> <body> -<p>Provides a cross-platform look and feel known as "Metal".</p> - +<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 + { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + } +catch (UnsupportedLookAndFeelException e) + { + e.printStackTrace(); + }</pre> </body> </html> |