diff options
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/metal')
19 files changed, 1749 insertions, 426 deletions
diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java index 99c90acdbee..98a00ee0a0e 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java @@ -59,6 +59,7 @@ import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.border.AbstractBorder; import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; import javax.swing.plaf.BorderUIResource; import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicBorders; @@ -138,24 +139,59 @@ public class MetalBorders if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme) paintOceanButtonBorder(c, g, x, y, w, h); else - { - ButtonModel bmodel = null; - - if (c instanceof AbstractButton) - bmodel = ((AbstractButton) c).getModel(); + paintDefaultButtonBorder(c, g, x, y, w, h); + } - Color darkShadow = MetalLookAndFeel.getControlDarkShadow(); - Color shadow = MetalLookAndFeel.getControlShadow(); - Color light = MetalLookAndFeel.getControlHighlight(); - Color middle = MetalLookAndFeel.getControl(); + /** + * Paints the button border for the DefaultMetalTheme. + * + * @param c the component (button) + * @param g the graphics object to use + * @param x the upper left corner of the component, X coordinate + * @param y the upper left corner of the component, Y coordinate + * @param w the width of the component + * @param h the height of the component + */ + private void paintDefaultButtonBorder(Component c, Graphics g, int x, + int y, int w, int h) + { + ButtonModel bmodel = null; - if (c.isEnabled()) - { - // draw dark border - g.setColor(darkShadow); - g.drawRect(x, y, w - 2, h - 2); + if (c instanceof AbstractButton) + bmodel = ((AbstractButton) c).getModel(); + + Color darkShadow = MetalLookAndFeel.getControlDarkShadow(); + Color shadow = MetalLookAndFeel.getControlShadow(); + Color light = MetalLookAndFeel.getControlHighlight(); + Color middle = MetalLookAndFeel.getControl(); + + if (c.isEnabled()) + { + // draw dark border + g.setColor(darkShadow); + g.drawRect(x, y, w - 2, h - 2); - if (!bmodel.isPressed()) + // If the button is the default button, we paint a special border, + // regardless of the pressed state. + if (c instanceof JButton && ((JButton) c).isDefaultButton()) + { + g.drawRect(x + 1, y + 1, w - 4, h - 4); + // Draw white highlight. + g.setColor(light); + g.drawLine(x + 2, y + 2, x + w - 4, y + 2); + g.drawLine(x + 2, y + 2, x + 2, y + h - 4); + g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1); + g.drawLine(x + w - 1, y + 2, x + w - 1, y + h - 1); + // Draw crossing pixels. + g.setColor(middle); + g.fillRect(x + w - 2, y + 2, 1, 1); + g.fillRect(x + 2, y + h - 2, 1, 1); + } + else + { + // The normal border. This is used when the button is not + // pressed or the button is not armed. + if (! (bmodel.isPressed() && bmodel.isArmed()) ) { // draw light border g.setColor(light); @@ -166,6 +202,8 @@ public class MetalBorders g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1); } + // The pressed border. This border is painted only when + // the button is both pressed and armed. else { // draw light border @@ -184,12 +222,12 @@ public class MetalBorders 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); - } + } + else + { + // draw disabled border + g.setColor(MetalLookAndFeel.getInactiveControlTextColor()); + g.drawRect(x, y, w - 2, h - 2); } } @@ -218,11 +256,16 @@ public class MetalBorders if (c.isEnabled()) { - if (bmodel.isPressed()) + // Paint the pressed border if the button is pressed, or if + // the button is the default button. In the OceanTheme, the default + // button has the same border as a pressed button. + if (bmodel.isPressed() || ((c instanceof JButton) + && ((JButton) c).isDefaultButton())) { - // draw fat border - g.drawLine(x + 1, y + 1, x + w - 2, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - 2); + // Draw fat border. + g.setColor(darkShadow); + g.drawRect(x, y, w - 1, h - 1); + g.drawRect(x + 1, y + 1, w - 3, h - 3); } else if (bmodel.isRollover()) { @@ -1025,14 +1068,10 @@ public class MetalBorders 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); + // TODO: What should be done here? Obviously the ButtonBorder already + // handles the rollover state in Sun's impl. Maybe this is only there + // for backwards compatibility. + super.paintBorder(c, g, x, y, w, h); } } @@ -1520,8 +1559,7 @@ public class MetalBorders { Border outer = new ButtonBorder(); Border inner = new RolloverMarginBorder(); - toolbarButtonBorder = new BorderUIResource.CompoundBorderUIResource - (outer, inner); + toolbarButtonBorder = new CompoundBorder(outer, inner); } return toolbarButtonBorder; } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java index e6fb22e929f..f2f778f95a7 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java @@ -41,7 +41,6 @@ package javax.swing.plaf.metal; import java.beans.PropertyChangeEvent; import javax.swing.AbstractButton; -import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicButtonListener; /** @@ -70,17 +69,6 @@ class MetalButtonListener extends BasicButtonListener 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()); - } - } + // TODO: What should be done here? } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java index 10e51117329..83cd3366215 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java @@ -45,6 +45,7 @@ import java.awt.Graphics; import java.awt.Rectangle; import javax.swing.AbstractButton; +import javax.swing.ButtonModel; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.SwingConstants; @@ -160,8 +161,8 @@ public class MetalButtonUI } /** - * Paints the background of the button to indicate that it is in the "pressed" - * state. + * Paints the background of the button to indicate that it is in the + * "pressed" state. * * @param g the graphics context. * @param b the button. @@ -234,8 +235,12 @@ public class MetalButtonUI public void update(Graphics g, JComponent c) { AbstractButton b = (AbstractButton) c; - if (b.isOpaque() && UIManager.get(getPropertyPrefix() + "gradient") != null - && !b.getModel().isPressed() && b.isEnabled()) + ButtonModel m = b.getModel(); + if (b.isContentAreaFilled() + && (UIManager.get(getPropertyPrefix() + "gradient") != null) + && ! m.isPressed() && ! m.isArmed() + && b.isEnabled() + && (b.getBackground() instanceof UIResource)) { MetalUtils.paintGradient(g, 0, 0, c.getWidth(), c.getHeight(), SwingConstants.VERTICAL, diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java index 6993e18e9b9..3787a98c3a9 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java @@ -38,22 +38,25 @@ 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 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; +import javax.swing.ListCellRenderer; +import javax.swing.UIManager; /** * A button used by the {@link MetalComboBoxUI} class. */ -public class MetalComboBoxButton extends JButton { +public class MetalComboBoxButton + extends JButton +{ /** A reference to the JComboBox that the button belongs to. */ protected JComboBox comboBox; @@ -61,7 +64,9 @@ public class MetalComboBoxButton extends JButton { /** A reference to the JList. */ protected JList listBox; - /** ??? */ + /** + * Used for rendering the selected item. + */ protected CellRendererPane rendererPane; /** The button icon. */ @@ -91,7 +96,7 @@ public class MetalComboBoxButton extends JButton { * @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 + * @param onlyIcon a flag that specifies whether the button displays only an * icon, or text as well. * @param pane the rendering pane. * @param list the list. @@ -107,6 +112,9 @@ public class MetalComboBoxButton extends JButton { iconOnly = onlyIcon; listBox = list; rendererPane = pane; + setRolloverEnabled(false); + setEnabled(comboBox.isEnabled()); + setFocusable(comboBox.isEnabled()); } /** @@ -191,8 +199,16 @@ public class MetalComboBoxButton extends JButton { 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? + if (enabled) + { + setBackground(comboBox.getBackground()); + setForeground(comboBox.getForeground()); + } + else + { + setBackground(UIManager.getColor("ComboBox.disabledBackground")); + setForeground(UIManager.getColor("ComboBox.disabledForeground")); + } } /** @@ -203,39 +219,75 @@ public class MetalComboBoxButton extends JButton { 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 + Insets insets = this.getInsets(); + int w = getWidth() - (insets.left + insets.right); + int h = getHeight() - (insets.top + insets.bottom); + if (h > 0 && w > 0) { - 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()) + int x1 = insets.left; + int y1 = insets.top; + int x2 = x1 + (w - 1); + int y2 = y1 + (h - 1); + int iconWidth = 0; + int iconX = x2; + if (comboIcon != null) + { + iconWidth = comboIcon.getIconWidth(); + int iconHeight = comboIcon.getIconHeight(); + int iconY; + if (iconOnly) + { + iconX = getWidth() / 2 - iconWidth / 2; + iconY = getHeight() / 2 - iconHeight / 2; + } + else + { + iconX = x1 + (w - 1) - iconWidth; + iconY = y1 + (y2 - y1) / 2 - iconHeight / 2; + } + comboIcon.paintIcon(this, g, iconX, iconY); + if (this.hasFocus()) + { + g.setColor(MetalLookAndFeel.getFocusColor()); + g.drawRect(x1 - 1, y1 - 1, w + 3, h + 1); + } + } + if (! iconOnly && comboBox != null) { - g.setColor(MetalLookAndFeel.getFocusColor()); - g.drawRect(innerArea.x, innerArea.y - 1, innerArea.width - 1, - innerArea.height); + ListCellRenderer renderer = comboBox.getRenderer(); + boolean pressed = this.getModel().isPressed(); + Component comp= renderer.getListCellRendererComponent(listBox, + comboBox.getSelectedItem(), + -1, false, false); + comp.setFont(rendererPane.getFont()); + if (model.isArmed() && model.isPressed()) + { + if (isOpaque()) + { + comp.setBackground(UIManager.getColor("Button.select")); + comp.setForeground(comboBox.getForeground()); + } + } + else if (! comboBox.isEnabled()) + { + if (this.isOpaque()) + { + Color dbg = + UIManager.getColor("ComboBox.disabledBackground"); + comp.setBackground(dbg); + Color dfg = + UIManager.getColor("ComboBox.disabledForeground"); + comp.setForeground(dfg); + } + } + else + { + comp.setForeground(comboBox.getForeground()); + comp.setBackground(comboBox.getBackground()); + } + int wr = w - (insets.right + iconWidth); + rendererPane.paintComponent(g, comp, this, x1, y1, wr, h); } - 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 index a531079cb1d..11e41510377 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java @@ -38,15 +38,15 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; import javax.swing.JTextField; +import javax.swing.border.AbstractBorder; import javax.swing.plaf.basic.BasicComboBoxEditor; import javax.swing.plaf.metal.MetalLookAndFeel; -import javax.swing.plaf.metal.MetalBorders.Flush3DBorder; /** * An editor used by the {@link MetalComboBoxUI} class. @@ -56,7 +56,7 @@ public class MetalComboBoxEditor extends BasicComboBoxEditor /** * A border used for the {@link JTextField} component. */ - static class MetalComboBoxEditorBorder extends Flush3DBorder + static class MetalComboBoxEditorBorder extends AbstractBorder { /** * Creates a new border instance. @@ -78,20 +78,34 @@ public class MetalComboBoxEditor extends BasicComboBoxEditor */ 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()); + { + g.translate(x, y); + if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, w - 1, 0); + g.drawLine(0, 0, 0, h - 1); + g.drawLine(0, h - 1, w - 1, h - 1); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(1, 1, w - 2, 1); + g.drawLine(1, 1, 1, h - 2); + g.drawLine(1, h - 2, w - 1, h - 2); + g.drawLine(w - 1, 1, w - 1, h - 2); + } else - g.setColor(MetalLookAndFeel.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); + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, w - 1, 0); + g.drawLine(0, 0, 0, h - 2); + g.drawLine(0, h - 2, w - 1, h - 2); + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(1, 1, w - 1, 1); + g.drawLine(1, 1, 1, h - 1); + g.drawLine(1, h - 1, w - 1, h - 1); + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(1, h - 2, 1, h - 2); + } + g.translate(-x, -y); } /** @@ -127,16 +141,49 @@ public class MetalComboBoxEditor extends BasicComboBoxEditor // Nothing to do here. } } - + + /** + * A special textfield implementation for the MetalComboBoxEditor. + */ + private class EditorTextField extends JTextField + { + EditorTextField(String s, int columns) + { + super(s, columns); + } + + /** + * Tests seem to show that the textfield in MetalComboBoxEditors have + * a height + 4. + */ + public Dimension getPreferredSize() + { + Dimension size = super.getPreferredSize(); + size.height += 4; + return size; + } + + /** + * Tests seem to show that the textfield in MetalComboBoxEditors have + * a height + 4. + */ + public Dimension getMinimumSize() + { + Dimension size = super.getMinimumSize(); + size.height += 4; + return size; + } + } + /** The editor's border insets. */ - protected static Insets editorBorderInsets = new Insets(4, 2, 4, 0); + protected static Insets editorBorderInsets = new Insets(2, 2, 2, 0); /** * Creates a new editor. */ public MetalComboBoxEditor() { - super(); + editor = new EditorTextField("", 9); editor.setBorder(new MetalComboBoxEditorBorder()); } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java index 0006b78fee3..c24c0850560 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java @@ -38,12 +38,12 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; import java.awt.LayoutManager; -import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -88,14 +88,7 @@ public class MetalComboBoxUI extends BasicComboBoxUI */ 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); + layoutComboBox(parent, this); } /** @@ -134,9 +127,31 @@ public class MetalComboBoxUI extends BasicComboBoxUI */ public void propertyChange(PropertyChangeEvent e) { - if (e.getPropertyName().equals("editable")) - editablePropertyChanged(e); super.propertyChange(e); + String name = e.getPropertyName(); + if (name.equals("editable")) + editablePropertyChanged(e); + else if (name.equals("enabled")) + { + if (arrowButton instanceof MetalComboBoxButton) + { + arrowButton.setFocusable(!comboBox.isEditable() + && comboBox.isEnabled()); + comboBox.repaint(); + } + } + else if (name.equals("background")) + { + Color c = (Color) e.getNewValue(); + arrowButton.setBackground(c); + listBox.setBackground(c); + } + else if (name.equals("foreground")) + { + Color c = (Color) e.getNewValue(); + arrowButton.setForeground(c); + listBox.setForeground(c); + } } } @@ -247,22 +262,8 @@ public class MetalComboBoxUI extends BasicComboBoxUI { MetalComboBoxButton b = (MetalComboBoxButton) arrowButton; b.setIconOnly(comboBox.isEditable()); - } - if (comboBox.isEditable()) - { - arrowButton.setText(null); - if (editor != null) - editor.setVisible(true); - } - else - { - String text = ""; - Object selected = comboBox.getSelectedItem(); - if (selected != null) - text = selected.toString(); - arrowButton.setText(text); - if (editor != null) - editor.setVisible(true); + b.setFocusable(!comboBox.isEditable() && comboBox.isEnabled()); + comboBox.repaint(); } } @@ -295,22 +296,39 @@ public class MetalComboBoxUI extends BasicComboBoxUI */ 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()) + if (!isMinimumSizeDirty) + return new Dimension(cachedMinimumSize); + + Dimension d; + if (!comboBox.isEditable() && arrowButton != null + && arrowButton instanceof MetalComboBoxButton) { + MetalComboBoxButton b = (MetalComboBoxButton) arrowButton; + d = getDisplaySize(); + Insets insets = b.getInsets(); + Insets arrowInsets = b.getInsets(); + Insets comboInsets = comboBox.getInsets(); Icon icon = b.getComboIcon(); - int iconWidth = icon.getIconWidth() + 6; - return new Dimension(d.width + insetsW + iconWidth, d.height + insetsH); + d.width += comboInsets.left + comboInsets.right; + d.width += arrowInsets.left + arrowInsets.right; + d.width += arrowInsets.right + icon.getIconWidth(); + d.height += comboInsets.top + comboInsets.bottom; + d.height += arrowInsets.top + arrowInsets.bottom; + } + else if (comboBox.isEditable() && arrowButton != null && editor != null) + { + d = super.getMinimumSize(c); + Insets arrowMargin = arrowButton.getMargin(); + d.height += arrowMargin.top + arrowMargin.bottom; + d.width += arrowMargin.left + arrowMargin.right; } else - // 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); + { + d = super.getMinimumSize(c); + } + cachedMinimumSize.setSize(d.width, d.height); + isMinimumSizeDirty = false; + return new Dimension(cachedMinimumSize); } /** @@ -318,27 +336,21 @@ public class MetalComboBoxUI extends BasicComboBoxUI */ public void configureEditor() { - ComboBoxEditor cbe = comboBox.getEditor(); - if (cbe != null) - { - cbe.getEditorComponent().setFont(comboBox.getFont()); - cbe.setItem(comboBox.getSelectedItem()); - cbe.addActionListener(comboBox); - } + super.configureEditor(); + if (popupKeyListener != null) + editor.removeKeyListener(popupKeyListener); + if (focusListener != null) + editor.addFocusListener(focusListener); } - + /** * Unconfigures the editor for this combo box. */ public void unconfigureEditor() { - ComboBoxEditor cbe = comboBox.getEditor(); - if (cbe != null) - { - cbe.getEditorComponent().setFont(null); - cbe.setItem(null); - cbe.removeActionListener(comboBox); - } + super.unconfigureEditor(); + if (focusListener != null) + editor.removeFocusListener(focusListener); } /** @@ -347,6 +359,16 @@ public class MetalComboBoxUI extends BasicComboBoxUI public void layoutComboBox(Container parent, MetalComboBoxUI.MetalComboBoxLayoutManager manager) { - manager.layoutContainer(parent); + if (comboBox.isEditable()) + manager.superLayout(parent); + else if (arrowButton != null) + { + Insets comboInsets = comboBox.getInsets(); + int width = comboBox.getWidth(); + int height = comboBox.getHeight(); + arrowButton.setBounds(comboInsets.left, comboInsets.top, + width - (comboInsets.left + comboInsets.right), + height - (comboInsets.top + comboInsets.bottom)); + } } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java index ecbb76e6e7a..0c1163a8e29 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java @@ -1,5 +1,5 @@ /* MetalDesktopIconUI.java - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -50,10 +50,6 @@ public class MetalDesktopIconUI extends BasicDesktopIconUI { - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for MetalDesktopIcons */ - private static MetalDesktopIconUI instance = null; - /** * Constructs a new instance of <code>MetalDesktopIconUI</code>. */ @@ -63,16 +59,14 @@ public class MetalDesktopIconUI } /** - * Returns a shared instance of <code>MetalDesktopIconUI</code>. + * Returns a new <code>MetalDesktopIconUI</code> instance. * - * @param component the component for which we return an UI instance + * @param component the component (ignored). * - * @return A shared instance of <code>MetalDesktopIconUI</code>. + * @return A new <code>MetalDesktopIconUI</code> instance. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalDesktopIconUI(); - return instance; + return new MetalDesktopIconUI(); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java index 0b644f30037..d24a0526232 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java @@ -756,6 +756,17 @@ public class MetalIconFactory implements Serializable { /** + * This is used as a mask when painting the gradient. See + * {@link MetalUtils#paintGradient(java.awt.Graphics, int, int, int, int, + * float, float, java.awt.Color, java.awt.Color, java.awt.Color, int, + * int[][])} for details. + */ + private static int[][] gradientMask = new int[][] {{3, 7}, {1, 9}, {1, 9}, + {0, 10}, {0, 10}, {0, 10}, + {0, 10}, {1, 9}, {1, 9}, + {3, 7}}; + + /** * Returns the width of the icon in pixels. * * @return the width of the icon in pixels @@ -788,12 +799,13 @@ public class MetalIconFactory implements Serializable public void paintIcon(Component c, Graphics g, int x, int y) { if (UIManager.get("RadioButton.gradient") != null) - MetalUtils.paintGradient(g, x, y, getIconWidth(), getIconHeight(), - SwingConstants.VERTICAL, "RadioButton.gradient"); + MetalUtils.paintGradient(g, x + 2, y + 2, 8, 8, + SwingConstants.VERTICAL, "RadioButton.gradient", + gradientMask); Color savedColor = g.getColor(); JRadioButton b = (JRadioButton) c; - + // draw outer circle if (b.isEnabled()) g.setColor(MetalLookAndFeel.getControlDarkShadow()); @@ -951,6 +963,14 @@ public class MetalIconFactory implements Serializable { /** + * This mask is used to paint the gradient in the shape of the thumb. + */ + int[][] gradientMask = new int[][] { {0, 12}, {0, 12}, {0, 12}, {0, 12}, + {0, 12}, {0, 12}, {0, 12}, {1, 12}, + {2, 10}, {3, 9}, {4, 8}, {5, 7}, + {6, 6}}; + + /** * Creates a new instance. */ public HorizontalSliderThumbIcon() @@ -1008,21 +1028,37 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 6, y + 14, x, y + 8); g.drawLine(x, y + 7, x, y + 1); - // fill the icon - if (focus) - g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + // Fill the icon. + if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme + && enabled) + { + String gradient; + if (focus) + gradient = "Slider.focusGradient"; + else + gradient = "Slider.gradient"; + MetalUtils.paintGradient(g, x + 1, y + 2, 12, 13, + SwingConstants.VERTICAL, gradient, + gradientMask); + } else - g.setColor(MetalLookAndFeel.getControl()); - g.fillRect(x + 1, y + 2, 13, 7); - g.drawLine(x + 2, y + 9, x + 12, y + 9); - g.drawLine(x + 3, y + 10, x + 11, y + 10); - g.drawLine(x + 4, y + 11, x + 10, y + 11); - g.drawLine(x + 5, y + 12, x + 9, y + 12); - g.drawLine(x + 6, y + 13, x + 8, y + 13); - g.drawLine(x + 7, y + 14, x + 7, y + 14); - - // if the slider is enabled, draw dots and highlights - if (c.isEnabled()) + { + if (focus) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(x + 1, y + 2, 13, 7); + g.drawLine(x + 2, y + 9, x + 12, y + 9); + g.drawLine(x + 3, y + 10, x + 11, y + 10); + g.drawLine(x + 4, y + 11, x + 10, y + 11); + g.drawLine(x + 5, y + 12, x + 9, y + 12); + g.drawLine(x + 6, y + 13, x + 8, y + 13); + g.drawLine(x + 7, y + 14, x + 7, y + 14); + } + + // If the slider is enabled, draw dots and highlights. + if (c.isEnabled() + && !(MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)) { if (focus) g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); @@ -1039,7 +1075,7 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 7, y + 7, x + 7, y + 7); g.drawLine(x + 11, y + 7, x + 11, y + 7); - // draw highlights + // Draw highlights if (focus) g.setColor(MetalLookAndFeel.getPrimaryControl()); else @@ -1583,6 +1619,14 @@ public class MetalIconFactory implements Serializable private static class VerticalSliderThumbIcon implements Icon, Serializable { /** + * This mask is used to paint the gradient in the shape of the thumb. + */ + int[][] gradientMask = new int[][] { {0, 12}, {0, 12}, {0, 12}, {0, 12}, + {0, 12}, {0, 12}, {0, 12}, {1, 12}, + {2, 10}, {3, 9}, {4, 8}, {5, 7}, + {6, 6}}; + + /** * Creates a new instance. */ public VerticalSliderThumbIcon() @@ -1641,21 +1685,37 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 8, y + 14, x + 1, y + 14); g.drawLine(x, y + 13, x, y + 1); - // fill the icon - if (focus) - g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + // Fill the icon. + if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme + && enabled) + { + String gradient; + if (focus) + gradient = "Slider.focusGradient"; + else + gradient = "Slider.gradient"; + MetalUtils.paintGradient(g, x + 2, y + 1, 13, 12, + SwingConstants.HORIZONTAL, gradient, + gradientMask); + } else - g.setColor(MetalLookAndFeel.getControl()); - g.fillRect(x + 2, y + 1, 7, 13); - g.drawLine(x + 9, y + 2, x + 9, y + 12); - g.drawLine(x + 10, y + 3, x + 10, y + 11); - g.drawLine(x + 11, y + 4, x + 11, y + 10); - g.drawLine(x + 12, y + 5, x + 12, y + 9); - g.drawLine(x + 13, y + 6, x + 13, y + 8); - g.drawLine(x + 14, y + 7, x + 14, y + 7); - + { + if (focus) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(x + 2, y + 1, 7, 13); + g.drawLine(x + 9, y + 2, x + 9, y + 12); + g.drawLine(x + 10, y + 3, x + 10, y + 11); + g.drawLine(x + 11, y + 4, x + 11, y + 10); + g.drawLine(x + 12, y + 5, x + 12, y + 9); + g.drawLine(x + 13, y + 6, x + 13, y + 8); + g.drawLine(x + 14, y + 7, x + 14, y + 7); + } + // if the slider is enabled, draw dots and highlights - if (enabled) + if (enabled + && ! (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)) { if (focus) g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java index 2cf5f67d55d..f74828e566e 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java @@ -93,7 +93,11 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane public void propertyChange(PropertyChangeEvent e) { String propName = e.getPropertyName(); - if (propName.equals("JInternalFrame.isPalette")) + if (e.getPropertyName().equals(JInternalFrame.FRAME_ICON_PROPERTY)) + { + title.setIcon( frame.getFrameIcon() ); + } + else if (propName.equals("JInternalFrame.isPalette")) { if (e.getNewValue().equals(Boolean.TRUE)) setPalette(true); @@ -262,7 +266,7 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane paletteTitleHeight = UIManager.getInt("InternalFrame.paletteTitleHeight"); paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon"); minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16); - + title = new JLabel(frame.getTitle(), MetalIconFactory.getInternalFrameDefaultMenuIcon(), SwingConstants.LEFT); @@ -329,9 +333,10 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane } /** - * Creates a new instance of {@link MetalTitlePaneLayout}. + * Creates a new instance of <code>MetalTitlePaneLayout</code> (not part of + * the public API). * - * @return A new instance of {@link MetalTitlePaneLayout}. + * @return A new instance of <code>MetalTitlePaneLayout</code>. */ protected LayoutManager createLayout() { @@ -382,8 +387,8 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane paintPalette(g); else { - paintTitleBackground(g); - paintChildren(g); + paintTitleBackground(g); + paintChildren(g); Dimension d = getSize(); if (frame.isSelected()) g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java index e84644615ce..7a973d46eef 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -1,5 +1,5 @@ /* MetalLookAndFeel.java - Copyright (C) 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -90,7 +90,7 @@ public class MetalLookAndFeel extends BasicLookAndFeel protected void createDefaultTheme() { if (theme == null) - setCurrentTheme(new DefaultMetalTheme()); + setCurrentTheme(new OceanTheme()); } /** @@ -899,7 +899,7 @@ public class MetalLookAndFeel extends BasicLookAndFeel "CheckBoxMenuItem.acceleratorForeground", getAcceleratorForeground(), "CheckBoxMenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(), "CheckBoxMenuItem.background", getMenuBackground(), - "CheckBoxMenuItem.borderPainted", new Boolean(true), + "CheckBoxMenuItem.borderPainted", Boolean.TRUE, "CheckBoxMenuItem.commandSound", "sounds/MenuItemCommand.wav", "CheckBoxMenuItem.checkIcon", MetalIconFactory.getCheckBoxMenuItemIcon(), "CheckBoxMenuItem.disabledForeground", getMenuDisabledForeground(), @@ -1204,7 +1204,7 @@ public class MetalLookAndFeel extends BasicLookAndFeel "Table.focusCellForeground", getControlTextColor(), "Table.foreground", getControlTextColor(), "Table.focusCellHighlightBorder", - new BorderUIResource.LineBorderUIResource(getControlShadow()), + new BorderUIResource.LineBorderUIResource(getFocusColor()), "Table.focusCellBackground", getWindowBackground(), "Table.gridColor", getControlDarkShadow(), "Table.selectionBackground", new ColorUIResource(204, 204, 255), diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java index 23051e9bcea..6cabc7e8691 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java @@ -47,11 +47,11 @@ import java.awt.Graphics; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.LayoutManager2; +import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; import java.awt.event.ActionEvent; -import java.awt.event.WindowEvent; -import java.awt.event.WindowFocusListener; +import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import javax.swing.AbstractAction; @@ -70,6 +70,7 @@ import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.AbstractBorder; +import javax.swing.event.MouseInputAdapter; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicRootPaneUI; @@ -191,6 +192,50 @@ public class MetalRootPaneUI */ private static class MetalTitlePane extends JComponent { + + /** + * Handles dragging of the title pane and moves the window accordingly. + */ + private class MouseHandler + extends MouseInputAdapter + { + /** + * The point where the dragging started. + */ + Point lastDragLocation; + + /** + * Receives notification when the mouse gets pressed on the title pane. + * This updates the lastDragLocation. + * + * @param ev the mouse event + */ + public void mousePressed(MouseEvent ev) + { + lastDragLocation = ev.getPoint(); + } + + /** + * Receives notification when the mouse is dragged on the title pane. + * This will move the nearest window accordingly. + * + * @param ev the mouse event + */ + public void mouseDragged(MouseEvent ev) + { + Point dragLocation = ev.getPoint(); + int deltaX = dragLocation.x - lastDragLocation.x; + int deltaY = dragLocation.y - lastDragLocation.y; + Window window = SwingUtilities.getWindowAncestor(rootPane); + Point loc = window.getLocation(); + window.setLocation(loc.x + deltaX, loc.y + deltaY); + // Note that we do not update the lastDragLocation. This is because + // we move the underlying window while dragging the component, which + // results in having the same lastDragLocation under the mouse while + // dragging. + } + } + /** * The Action responsible for closing the JInternalFrame. */ @@ -255,6 +300,45 @@ public class MetalRootPaneUI } /** + * This action is performed when the iconify button is pressed. + */ + private class IconifyAction + extends AbstractAction + { + + public void actionPerformed(ActionEvent event) + { + Window w = SwingUtilities.getWindowAncestor(rootPane); + if (w instanceof Frame) + { + Frame f = (Frame) w; + int state = f.getExtendedState(); + f.setExtendedState(Frame.ICONIFIED); + } + } + + } + + /** + * This action is performed when the maximize button is pressed. + */ + private class MaximizeAction + extends AbstractAction + { + + public void actionPerformed(ActionEvent event) + { + Window w = SwingUtilities.getWindowAncestor(rootPane); + if (w instanceof Frame) + { + Frame f = (Frame) w; + int state = f.getExtendedState(); + f.setExtendedState(Frame.MAXIMIZED_BOTH); + } + } + } + + /** * This helper class is used to create the minimize, maximize and close * buttons in the top right corner of the Title Pane. These buttons are * special since they cannot be given focus and have no border. @@ -499,23 +583,16 @@ public class MetalRootPaneUI private void installListeners() { - Window window = SwingUtilities.getWindowAncestor(rootPane); - window.addWindowFocusListener(new WindowFocusListener() - { - public void windowGainedFocus(WindowEvent ev) - { - repaint(); - } - public void windowLostFocus(WindowEvent ev) - { - repaint(); - } - }); + MouseInputAdapter mouseHandler = new MouseHandler(); + addMouseListener(mouseHandler); + addMouseMotionListener(mouseHandler); } private void createActions() { closeAction = new CloseAction(); + iconifyAction = new IconifyAction(); + maximizeAction = new MaximizeAction(); } private void assembleSystemMenu() @@ -699,6 +776,21 @@ public class MetalRootPaneUI */ private Dimension prefSize; + /** + * The title pane for l&f decorated frames. + */ + private MetalTitlePane titlePane; + + /** + * Creates a new MetalRootLayout. + * + * @param tp the title pane + */ + MetalRootLayout(MetalTitlePane tp) + { + titlePane = tp; + } + public void addLayoutComponent(Component component, Object constraints) { // Nothing to do here. @@ -747,12 +839,8 @@ public class MetalRootPaneUI { JRootPane rp = (JRootPane) parent; JLayeredPane layeredPane = rp.getLayeredPane(); - Component contentPane = layeredPane.getComponent(0); - Component titlePane = layeredPane.getComponent(1); - Component menuBar = null; - if (layeredPane.getComponentCount() > 2 - && layeredPane.getComponent(2) instanceof JMenuBar) - menuBar = layeredPane.getComponent(2); + Component contentPane = rp.getContentPane(); + Component menuBar = rp.getJMenuBar(); // We must synchronize here, otherwise we cannot guarantee that the // prefSize is still non-null when returning. @@ -789,12 +877,8 @@ public class MetalRootPaneUI { JRootPane rp = (JRootPane) parent; JLayeredPane layeredPane = rp.getLayeredPane(); - Component contentPane = layeredPane.getComponent(0); - Component titlePane = layeredPane.getComponent(1); - Component menuBar = null; - if (layeredPane.getComponentCount() > 2 - && layeredPane.getComponent(2) instanceof JMenuBar) - menuBar = layeredPane.getComponent(2); + Component contentPane = rp.getContentPane(); + Component menuBar = rp.getJMenuBar(); Component glassPane = rp.getGlassPane(); if (glassPaneBounds == null || layeredPaneBounds == null @@ -937,6 +1021,7 @@ public class MetalRootPaneUI */ public void propertyChange(PropertyChangeEvent ev) { + super.propertyChange(ev); String propertyName = ev.getPropertyName(); if (propertyName.equals("windowDecorationStyle")) { @@ -958,12 +1043,14 @@ public class MetalRootPaneUI private void installWindowDecorations(JRootPane rp) { rp.setBorder(new MetalFrameBorder()); - rp.setLayout(new MetalRootLayout()); + MetalTitlePane titlePane = new MetalTitlePane(rp); + rp.setLayout(new MetalRootLayout(titlePane)); // We should have a contentPane already. - assert rp.getLayeredPane().getComponentCount() == 1 + assert rp.getLayeredPane().getComponentCount() > 0 : "We should have a contentPane already"; - rp.getLayeredPane().add(new MetalTitlePane(rp), - JLayeredPane.FRAME_CONTENT_LAYER); + + rp.getLayeredPane().add(titlePane, + JLayeredPane.FRAME_CONTENT_LAYER, 1); } /** @@ -975,6 +1062,14 @@ public class MetalRootPaneUI private void uninstallWindowDecorations(JRootPane rp) { rp.setBorder(null); - rp.getLayeredPane().remove(1); + JLayeredPane lp = rp.getLayeredPane(); + for (int i = lp.getComponentCount() - 1; i >= 0; --i) + { + if (lp.getComponent(i) instanceof MetalTitlePane) + { + lp.remove(i); + break; + } + } } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java index 155bb814689..c7dfd11e48c 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java @@ -349,10 +349,15 @@ public class MetalScrollBarUI extends BasicScrollBarUI else paintThumbVertical(g, c, thumbBounds); - // draw the pattern - MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3, - thumbBounds.width - 6, thumbBounds.height - 6, - thumbHighlightColor, thumbLightShadowColor); + // Draw the pattern when the theme is not Ocean. + if (! (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)) + { + MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3, + thumbBounds.width - 6, + thumbBounds.height - 6, + thumbHighlightColor, + thumbLightShadowColor); + } } /** @@ -370,13 +375,24 @@ public class MetalScrollBarUI extends BasicScrollBarUI 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); + // First we fill the background. + MetalTheme theme = MetalLookAndFeel.getCurrentTheme(); + if (theme instanceof OceanTheme + && UIManager.get("ScrollBar.gradient") != null) + { + MetalUtils.paintGradient(g, x + 2, y + 2, w - 4, h - 2, + SwingConstants.VERTICAL, + "ScrollBar.gradient"); + } else - g.fillRect(x, y, w, h); - + { + 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) @@ -405,6 +421,19 @@ public class MetalScrollBarUI extends BasicScrollBarUI g.setColor(UIManager.getColor("ScrollBar.shadow")); g.drawLine(x + w, y + 1, x + w, y + h - 1); + // For the OceanTheme, draw the 3 lines in the middle. + if (theme instanceof OceanTheme) + { + g.setColor(thumbLightShadowColor); + int middle = x + w / 2; + g.drawLine(middle - 2, y + 4, middle - 2, y + h - 5); + g.drawLine(middle, y + 4, middle, y + h - 5); + g.drawLine(middle + 2, y + 4, middle + 2, y + h - 5); + g.setColor(UIManager.getColor("ScrollBar.highlight")); + g.drawLine(middle - 1, y + 5, middle - 1, y + h - 4); + g.drawLine(middle + 1, y + 5, middle + 1, y + h - 4); + g.drawLine(middle + 3, y + 5, middle + 3, y + h - 4); + } } /** @@ -422,13 +451,24 @@ public class MetalScrollBarUI extends BasicScrollBarUI 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); + // First we fill the background. + MetalTheme theme = MetalLookAndFeel.getCurrentTheme(); + if (theme instanceof OceanTheme + && UIManager.get("ScrollBar.gradient") != null) + { + MetalUtils.paintGradient(g, x + 2, y + 2, w - 2, h - 4, + SwingConstants.HORIZONTAL, + "ScrollBar.gradient"); + } else - g.fillRect(x, y, w, h); - + { + 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) @@ -456,6 +496,20 @@ public class MetalScrollBarUI extends BasicScrollBarUI // draw the shadow line g.setColor(UIManager.getColor("ScrollBar.shadow")); g.drawLine(x + 1, y + h, x + w - 2, y + h); + + // For the OceanTheme, draw the 3 lines in the middle. + if (theme instanceof OceanTheme) + { + g.setColor(thumbLightShadowColor); + int middle = y + h / 2; + g.drawLine(x + 4, middle - 2, x + w - 5, middle - 2); + g.drawLine(x + 4, middle, x + w - 5, middle); + g.drawLine(x + 4, middle + 2, x + w - 5, middle + 2); + g.setColor(UIManager.getColor("ScrollBar.highlight")); + g.drawLine(x + 5, middle - 1, x + w - 4, middle - 1); + g.drawLine(x + 5, middle + 1, x + w - 4, middle + 1); + g.drawLine(x + 5, middle + 3, x + w - 4, middle + 3); + } } /** diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java index 08fb99d216c..f97717f31e0 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java @@ -1,5 +1,5 @@ /* MetalSliderUI.java - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -210,7 +210,7 @@ public class MetalSliderUI extends BasicSliderUI { int trackX = trackRect.x; int trackY = trackRect.y + (trackRect.height - getTrackWidth()) / 2; - int trackW = trackRect.width - 1; + int trackW = trackRect.width; int trackH = getTrackWidth(); // draw border @@ -224,29 +224,47 @@ public class MetalSliderUI extends BasicSliderUI } // 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); - } - } + if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme) + { + if (slider.isEnabled()) + { + int xPos = xPositionForValue(slider.getValue()); + int x = (slider.getInverted() ? xPos : trackRect.x); + int w = (slider.getInverted() ? trackX + trackW - xPos + : xPos - trackRect.x); + g.setColor(MetalLookAndFeel.getWhite()); + g.drawLine(x + 1, trackY + 1, x + w - 3, trackY + 1); + g.setColor(UIManager.getColor("Slider.altTrackColor")); + g.drawLine(x + 1, trackY + 2, x + w - 3, trackY + 2); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(x + 1, trackY + 3, x + w - 3, trackY + 3); + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.drawLine(x + 1, trackY + 4, x + w - 3, trackY + 4); + } + } + else if (filledSlider) + { + int xPos = xPositionForValue(slider.getValue()); + int x = (slider.getInverted() ? xPos : trackRect.x); + int w = (slider.getInverted() ? trackX + trackW - xPos + : xPos - trackRect.x); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.fillRect(x + 1, trackY + 1, w - 3, getTrackWidth() - 3); + if (slider.isEnabled()) + { + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(x + 1, trackY + 1, x + w - 3, trackY + 1); + g.drawLine(x + 1, trackY + 1, x + 1, + trackY + getTrackWidth() - 3); + } + } } else { int trackX = trackRect.x + (trackRect.width - getTrackWidth()) / 2; int trackY = trackRect.y; int trackW = getTrackWidth(); - int trackH = trackRect.height - 1; + int trackH = trackRect.height; if (slider.isEnabled()) BasicGraphicsUtils.drawEtchedRect(g, trackX, trackY, trackW, trackH, darkShadowColor, shadowColor, darkShadowColor, highlightColor); @@ -255,8 +273,28 @@ public class MetalSliderUI extends BasicSliderUI g.setColor(MetalLookAndFeel.getControlShadow()); g.drawRect(trackX, trackY, trackW - 2, trackH - 2); } - - if (filledSlider) + + // Fill track if necessary. + if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme) + { + if (slider.isEnabled()) + { + int yPos = yPositionForValue(slider.getValue()); + int y = (slider.getInverted() ? trackY : yPos); + int h = (slider.getInverted() ? yPos - trackY + : trackY + trackH - yPos); + + g.setColor(MetalLookAndFeel.getWhite()); + g.drawLine(trackX + 1, y + 1, trackX + 1, y + h - 3); + g.setColor(UIManager.getColor("Slider.altTrackColor")); + g.drawLine(trackX + 2, y + 1, trackX + 2, y + h - 3); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(trackX + 3, y + 1, trackX + 3, y + h - 3); + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.drawLine(trackX + 4, y + 1, trackX + 4, y + h - 3); + } + } + else if (filledSlider) { int yPos = yPositionForValue(slider.getValue()); int y = (slider.getInverted() ? trackY : yPos); diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java index c6c46ffe614..39dec3d663f 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java @@ -47,6 +47,7 @@ import javax.swing.JComponent; import javax.swing.JTabbedPane; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicTabbedPaneUI; /** @@ -101,6 +102,17 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI // do nothing, because the selected tab does not have extra padding in // the MetalLookAndFeel } + + /** + * Overridden because tab runs are only normalized for TOP and BOTTOM + * tab placement in the Metal L&F. + */ + protected void normalizeTabRuns(int tabPlacement, int tabCount, int start, + int max) + { + if (tabPlacement == TOP || tabPlacement == BOTTOM) + super.normalizeTabRuns(tabPlacement, tabCount, start, max); + } } /** @@ -125,7 +137,12 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI /** The graphics to draw the highlight below the tab. */ private Graphics hg; - + + /** + * Indicates if the tabs are having their background filled. + */ + private boolean tabsOpaque; + /** * Constructs a new instance of MetalTabbedPaneUI. */ @@ -153,7 +170,7 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI */ protected LayoutManager createLayoutManager() { - return super.createLayoutManager(); + return new TabbedPaneLayout(); } /** @@ -172,16 +189,24 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { - if (tabPlacement == TOP) - paintTopTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected); - else if (tabPlacement == LEFT) - paintLeftTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected); - else if (tabPlacement == BOTTOM) - paintBottomTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected); - else if (tabPlacement == RIGHT) - paintRightTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected); - else - throw new AssertionError("Unrecognised 'tabPlacement' argument."); + int bottom = y + h - 1; + int right = x + w - 1; + + switch (tabPlacement) + { + case LEFT: + paintLeftTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected); + break; + case BOTTOM: + paintBottomTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected); + break; + case RIGHT: + paintRightTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected); + break; + case TOP: + default: + paintTopTabBorder(tabIndex, g, x, y, w, h, bottom, right, isSelected); + } } /** @@ -194,35 +219,90 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI * @param y the y-coordinate for the tab's bounding rectangle. * @param w the width for the tab's bounding rectangle. * @param h the height for the tab's bounding rectangle. - * @param btm ??? - * @param rght ??? + * @param btm the y coordinate of the bottom border + * @param rght the x coordinate of the right border * @param isSelected indicates whether the tab is selected. */ protected void paintTopTabBorder(int tabIndex, Graphics g, int x, int y, int w, int h, int btm, int rght, boolean isSelected) { - int currentRun = getRunForTab(tabPane.getTabCount(), tabIndex); + int tabCount = tabPane.getTabCount(); + int currentRun = getRunForTab(tabCount, tabIndex); + int right = w - 1; + int bottom = h - 1; + + // Paint gap. if (shouldFillGap(currentRun, tabIndex, x, y)) { g.translate(x, y); - g.setColor(getColorForGap(currentRun, x, y)); + g.setColor(getColorForGap(currentRun, x, y + 1)); g.fillRect(1, 0, 5, 3); g.fillRect(1, 3, 2, 2); g.translate(-x, -y); } - - if (isSelected) - { - g.setColor(MetalLookAndFeel.getControlHighlight()); - g.drawLine(x + 1, y + h, x + 1, y + 6); - g.drawLine(x + 1, y + 6, x + 6, y + 1); - g.drawLine(x + 6, y + 1, x + w - 1, y + 1); - } - g.setColor(MetalLookAndFeel.getControlDarkShadow()); - g.drawLine(x, y + h - 1, x, y + 6); - g.drawLine(x, y + 6, x + 6, y); - g.drawLine(x + 6, y, x + w, y); - g.drawLine(x + w, y, x + w, y + h - 1); + + g.translate(x, y); + + boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme; + Color oceanSelectedBorder = + UIManager.getColor("TabbedPane.borderHightlightColor"); + if (isOcean && isSelected) + g.setColor(oceanSelectedBorder); + else + g.setColor(darkShadow); + + // Slant + g.drawLine(1, 5, 6, 0); + // Top. + g.drawLine(6, 0, right, 0); + // Right. + int lastIndex = lastTabInRun(tabCount, currentRun); + if (tabIndex == lastIndex) + g.drawLine(right, 1, right, bottom); + // Left. + int selectedIndex = tabPane.getSelectedIndex(); + if (isOcean && tabIndex - 1 == selectedIndex + && currentRun == getRunForTab(tabCount, selectedIndex)) + { + g.setColor(oceanSelectedBorder); + } + if (tabIndex != tabRuns[runCount - 1]) + { + if (isOcean && isSelected) + { + g.drawLine(0, 6, 0, bottom); + g.setColor(darkShadow); + g.drawLine(0, 0, 0, 5); + } + else + { + g.drawLine(0, 0, 0, bottom); + } + } + else + { + g.drawLine(0, 6, 0, bottom); + } + + // Paint the highlight. + g.setColor(isSelected ? selectHighlight : highlight); + // Slant. + g.drawLine(1, 6, 6, 1); + // Top. + g.drawLine(6, 1, right, 1); + // Left. + g.drawLine(1, 6, 1, bottom); + int firstIndex = tabRuns[currentRun]; + if (tabIndex == firstIndex && tabIndex != tabRuns[runCount - 1]) + { + if (tabPane.getSelectedIndex() == tabRuns[currentRun + 1]) + g.setColor(selectHighlight); + else + g.setColor(highlight); + g.drawLine(1, 0, 1, 4); + } + + g.translate(-x, -y); } /** @@ -242,18 +322,115 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI protected void paintLeftTabBorder(int tabIndex, Graphics g, int x, int y, int w, int h, int btm, int rght, boolean isSelected) { - if (isSelected) - { - g.setColor(MetalLookAndFeel.getControlHighlight()); - g.drawLine(x + 1, y + h, x + 1, y + 6); - g.drawLine(x + 1, y + 6, x + 6, y + 1); - g.drawLine(x + 6, y + 1, x + w - 1, y + 1); - } - g.setColor(MetalLookAndFeel.getControlDarkShadow()); - g.drawLine(x, y + h, x, y + 6); - g.drawLine(x, y + 6, x + 6, y); - g.drawLine(x + 6, y, x + w - 1, y); - g.drawLine(x, y + h, x + w - 1, y + h); + g.translate(x, y); + int bottom = h - 1; + int right = w - 1; + + + int tabCount = tabPane.getTabCount(); + int currentRun = getRunForTab(tabCount, tabIndex); + int firstIndex = tabRuns[currentRun]; + + // Paint the part of the above tab. + if (tabIndex != firstIndex && tabIndex > 0 && tabsOpaque) + { + Color c; + if (tabPane.getSelectedIndex() == tabIndex - 1) + c = selectColor; + else + c = getUnselectedBackground(tabIndex - 1); + g.setColor(c); + g.fillRect(2, 0, 4, 3); + g.drawLine(2, 3, 2, 3); + } + + // Paint the highlight. + boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme; + if (isOcean) + { + g.setColor(isSelected ? selectHighlight : MetalLookAndFeel.getWhite()); + } + else + { + g.setColor(isSelected ? selectHighlight : highlight); + } + // Slant. + g.drawLine(1, 6, 6, 1); + // Left. + g.drawLine(1, 6, 1, bottom); + // Top. + g.drawLine(6, 1, right, 1); + if (tabIndex != firstIndex) + { + if (isOcean) + { + g.setColor(MetalLookAndFeel.getWhite()); + } + g.drawLine(1, 0, 1, 4); + } + + // Paint border. + Color oceanSelectedBorder = + UIManager.getColor("TabbedPane.borderHightlightColor"); + if (isOcean && isSelected) + { + g.setColor(oceanSelectedBorder); + } + else + { + g.setColor(darkShadow); + } + + // Slant. + g.drawLine(1, 5, 6, 0); + // Top. + g.drawLine(6, 0, right, 0); + // Bottom. + int lastIndex = lastTabInRun(tabCount, currentRun); + if (tabIndex == lastIndex) + { + g.drawLine(0, bottom, right, bottom); + } + // Left. + if (isOcean) + { + if (tabPane.getSelectedIndex() == tabIndex - 1) + { + g.drawLine(0, 5, 0, bottom); + g.setColor(oceanSelectedBorder); + g.drawLine(0, 0, 0, 5); + } + else if (isSelected) + { + g.drawLine(0, 5, 0, bottom); + if (tabIndex != 0) + { + g.setColor(darkShadow); + g.drawLine(0, 0, 0, 5); + } + } + else if (tabIndex != firstIndex) + { + g.drawLine(0, 0, 0, bottom); + } + else + { + g.drawLine(0, 6, 0, bottom); + } + } + else + { + if (tabIndex != firstIndex) + { + g.drawLine(0, 0, 0, bottom); + } + else + { + g.drawLine(0, 6, 0, bottom); + } + } + + g.translate(-x, -y); } /** @@ -273,17 +450,92 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI protected void paintRightTabBorder(int tabIndex, Graphics g, int x, int y, int w, int h, int btm, int rght, boolean isSelected) { - if (isSelected) - { - g.setColor(MetalLookAndFeel.getControlHighlight()); - g.drawLine(x, y + 1, x + w - 7, y + 1); - g.drawLine(x + w - 7, y + 1, x + w - 1, y + 7); - } - g.setColor(MetalLookAndFeel.getControlDarkShadow()); - g.drawLine(x, y, x + w - 7, y); - g.drawLine(x + w - 7, y, x + w - 1, y + 6); - g.drawLine(x + w - 1, y + 6, x + w - 1, y + h - 1); - g.drawLine(x + w - 1, y + h, x, y + h); + g.translate(x, y); + int bottom = h - 1; + int right = w - 1; + + int tabCount = tabPane.getTabCount(); + int currentRun = getRunForTab(tabCount, tabIndex); + int firstIndex = tabRuns[currentRun]; + + // Paint part of the above tab. + if (tabIndex != firstIndex && tabIndex > 0 && tabsOpaque) + { + Color c; + if (tabPane.getSelectedIndex() == tabIndex - 1) + c = UIManager.getColor("TabbedPane.tabAreaBackground"); + else + c = getUnselectedBackground(tabIndex - 1); + g.fillRect(right - 5, 0, 5, 3); + g.fillRect(right - 2, 3, 2, 2); + } + + // Paint highlight. + g.setColor(isSelected ? selectHighlight : highlight); + + // Slant. + g.drawLine(right - 6, 1, right - 1, 6); + // Top. + g.drawLine(0, 1, right - 6, 1); + // Left. + if (! isSelected) + { + g.drawLine(0, 1, 0, bottom); + } + + // Paint border. + boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme; + Color oceanSelectedBorder = + UIManager.getColor("TabbedPane.borderHightlightColor"); + if (isOcean && isSelected) + { + g.setColor(oceanSelectedBorder); + } + else + { + g.setColor(darkShadow); + } + + // Bottom. + int lastIndex = lastTabInRun(tabCount, currentRun); + if (tabIndex == lastIndex) + { + g.drawLine(0, bottom, right, bottom); + } + // Slant. + if (isOcean && tabPane.getSelectedIndex() == tabIndex - 1) + { + g.setColor(oceanSelectedBorder); + } + g.drawLine(right - 6, 0, right, 6); + // Top. + g.drawLine(0, 0, right - 6, 0); + // Right. + if (isOcean && isSelected) + { + g.drawLine(right, 6, right, bottom); + if (tabIndex != firstIndex) + { + g.setColor(darkShadow); + g.drawLine(right, 0, right, 5); + } + } + else if (isOcean && tabPane.getSelectedIndex() == tabIndex - 1) + { + g.setColor(oceanSelectedBorder); + g.drawLine(right, 0, right, 6); + g.setColor(darkShadow); + g.drawLine(right, 6, right, bottom); + } + else if (tabIndex != firstIndex) + { + g.drawLine(right, 0, right, bottom); + } + else + { + g.drawLine(right, 6, right, bottom); + } + g.translate(-x, -y); } /** @@ -303,27 +555,94 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI protected void paintBottomTabBorder(int tabIndex, Graphics g, int x, int y, int w, int h, int btm, int rght, boolean isSelected) { - int currentRun = getRunForTab(tabPane.getTabCount(), tabIndex); + int bottom = h - 1; + int right = w - 1; + + int tabCount = tabPane.getTabCount(); + int currentRun = getRunForTab(tabCount, tabIndex); + // Paint gap if necessary. if (shouldFillGap(currentRun, tabIndex, x, y)) { g.translate(x, y); g.setColor(getColorForGap(currentRun, x, y)); - g.fillRect(1, h - 5, 3, 5); - g.fillRect(4, h - 2, 2, 2); + g.fillRect(1, bottom - 4, 3, 5); + g.fillRect(4, bottom - 1, 2, 2); g.translate(-x, -y); } - - if (isSelected) - { - g.setColor(MetalLookAndFeel.getControlHighlight()); - g.drawLine(x + 1, y, x + 1, y + h - 7); - g.drawLine(x + 1, y + h - 7, x + 7, y + h - 1); - } - g.setColor(MetalLookAndFeel.getControlDarkShadow()); - g.drawLine(x, y, x, y + h - 7); - g.drawLine(x, y + h - 7, x + 6, y + h - 1); - g.drawLine(x + 6, y + h - 1, x + w, y + h - 1); - g.drawLine(x + w, y + h - 1, x + w, y); + + g.translate(x, y); + + // Paint border. + boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme; + Color oceanSelectedBorder = + UIManager.getColor("TabbedPane.borderHightlightColor"); + if (isOcean && isSelected) + { + g.setColor(oceanSelectedBorder); + } + else + { + g.setColor(darkShadow); + } + // Slant. + g.drawLine(1, bottom - 5, 6, bottom); + // Bottom. + g.drawLine(6, bottom, right, bottom); + // Right. + int lastIndex = lastTabInRun(tabCount, currentRun); + if (tabIndex == lastIndex) + { + g.drawLine(right, 0, right, bottom); + } + // Left. + if (isOcean && isSelected) + { + g.drawLine(0, 0, 0, bottom - 5); + if ((currentRun == 0 && tabIndex != 0) + || (currentRun > 0 && tabIndex != tabRuns[currentRun - 1])) + { + g.setColor(darkShadow); + g.drawLine(0, bottom - 5, 0, bottom); + } + } + else + { + if (isOcean && tabIndex == tabPane.getSelectedIndex()+ 1) + { + g.setColor(oceanSelectedBorder); + } + if (tabIndex != tabRuns[runCount- 1]) + { + g.drawLine(0, 0, 0, bottom); + } + else + { + g.drawLine(0, 0, 0, bottom - 6); + } + } + + // Paint highlight. + g.setColor(isSelected ? selectHighlight : highlight); + // Slant. + g.drawLine(1, bottom - 6, 6, bottom - 1); + // Left. + g.drawLine(1, 0, 1, bottom - 6); + + int firstIndex = tabRuns[currentRun]; + if (tabIndex == firstIndex && tabIndex != tabRuns[runCount - 1]) + { + if (tabPane.getSelectedIndex() == tabRuns[currentRun + 1]) + { + g.setColor(selectHighlight); + } + else + { + g.setColor(highlight); + } + g.drawLine(1, bottom - 4, 1, bottom); + } + + g.translate(-x, -y); } /** @@ -343,42 +662,29 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI int tabIndex, int x, int y, int w, int h, boolean isSelected) { if (isSelected) - g.setColor(UIManager.getColor("TabbedPane.selected")); + g.setColor(selectColor); else - { - // This is only present in the OceanTheme, so we must check if it - // is actually there - Color background = UIManager.getColor("TabbedPane.unselectedBackground"); - if (background == null) - background = UIManager.getColor("TabbedPane.background"); - g.setColor(background); - } - int[] px, py; - if (tabPlacement == TOP) - { - px = new int[] {x + 6, x + w - 1, x + w -1, x + 2, x + 2}; - py = new int[] {y + 2, y + 2, y + h - 1, y + h -1, y + 6}; - } - else if (tabPlacement == LEFT) - { - px = new int[] {x + 6, x + w - 1, x + w -1, x + 2, x + 2}; - py = new int[] {y + 2, y + 2, y + h - 1, y + h -1, y + 6}; - } - else if (tabPlacement == BOTTOM) - { - px = new int[] {x + 2, x + w - 1, x + w -1, x + 8, x + 2}; - py = new int[] {y, y, y + h - 1, y + h -1, y + h - 7}; - } - else if (tabPlacement == RIGHT) - { - px = new int[] {x + 2, x + w - 7, x + w - 1, x + w - 1, x + 2}; - py = new int[] {y + 2, y + 2, y + 7, y + h -1, y + h - 1}; - } - else - throw new AssertionError("Unrecognised 'tabPlacement' argument."); - g.fillPolygon(px, py, 5); - hg = g; - paintHighlightBelowTab(); + g.setColor(getUnselectedBackground(tabIndex)); + + switch (tabPlacement) + { + case LEFT: + g.fillRect(x + 5, y + 1, w - 5, h - 1); + g.fillRect(x + 2, y + 4, 3, h - 4); + break; + case BOTTOM: + g.fillRect(x + 2, y, w - 2, h - 3); + g.fillRect(x + 5, y + h - 4, w - 5, 3); + break; + case RIGHT: + g.fillRect(x, y + 1, w - 4, h - 1); + g.fillRect(x + w - 4, y + 5, 3, h - 5); + break; + case TOP: + default: + g.fillRect(x + 4, y + 2, w - 4, h - 2); + g.fillRect(x + 2, y + 5, 2, h - 5); + } } /** @@ -408,6 +714,7 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI selectColor = UIManager.getColor("TabbedPane.selected"); selectHighlight = UIManager.getColor("TabbedPane.selectHighlight"); tabAreaBackground = UIManager.getColor("TabbedPane.tabAreaBackground"); + tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque"); minTabWidth = 0; } @@ -487,4 +794,354 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI // false because tab runs are not rotated in the MetalLookAndFeel return false; } + + protected int calculateMaxTabHeight(int tabPlacement) + { + // FIXME: Why is this overridden? + return super.calculateMaxTabHeight(tabPlacement); + } + + /** + * Returns the amount of overlay among the tabs. In + * the Metal L&F the overlay for LEFT and RIGHT placement + * is half of the maxTabHeight. For TOP and BOTTOM placement + * the tabs do not overlay. + * + * @param tabPlacement the placement + * + * @return the amount of overlay among the tabs + */ + protected int getTabRunOverlay(int tabPlacement) + { + int overlay = 0; + if (tabPlacement == LEFT || tabPlacement == RIGHT) + { + int maxHeight = calculateMaxTabHeight(tabPlacement); + overlay = maxTabHeight / 2; + } + return overlay; + } + + /** + * Paints the upper edge of the content border. + * + * @param g the graphics to use for painting + * @param tabPlacement the tab placement + * @param selectedIndex the index of the selected tab + * @param x the upper left coordinate of the content area + * @param y the upper left coordinate of the content area + * @param w the width of the content area + * @param h the height of the content area + */ + protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color oceanSelectedBorder = + UIManager.getColor("TabbedPane.borderHightlightColor"); + boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme; + if (isOcean) + { + g.setColor(oceanSelectedBorder); + } + else + { + g.setColor(selectHighlight); + } + + Rectangle rect = selectedIndex < 0 ? null : + getTabBounds(selectedIndex, calcRect); + + // If tabs are not placed on TOP, or if the selected tab is not in the + // run directly above the content or the selected tab is not visible, + // then we draw an unbroken line. + if (tabPlacement != TOP || selectedIndex < 0 + || rect.y + rect.height + 1 < y || rect.x < x ||rect.x > x + w) + { + g.drawLine(x, y, x + w - 2, y); + if (isOcean && tabPlacement == TOP) + { + g.setColor(MetalLookAndFeel.getWhite()); + g.drawLine(x, y + 1, x + w - 2, y + 1); + } + } + else + { + boolean isLast = isLastTabInRun(selectedIndex); + if (isLast) + { + g.drawLine(x, y, rect.x + 1, y); + } + else + { + g.drawLine(x, y, rect.x, y); + } + + int right = x + w - 1; + if (rect.x + rect.width < right - 1) + { + if (isLast) + { + g.drawLine(rect.x + rect.width - 1, y, right - 1, y); + } + else + { + g.drawLine(rect.x + rect.width, y, right - 1, y); + } + } + else + { + g.setColor(shadow); + g.drawLine(x + w - 2, y, x + w - 2, y); + } + + // When in OceanTheme, draw another white line. + if (isOcean) + { + g.setColor(MetalLookAndFeel.getWhite()); + if (isLast) + { + g.drawLine(x, y + 1, rect.x + 1, y + 1); + } + else + { + g.drawLine(x, y + 1, rect.x, y + 1); + } + + if (rect.x + rect.width < right - 1) + { + if (isLast) + { + g.drawLine(rect.x + rect.width - 1, y + 1, right - 1, + y + 1); + } + else + { + g.drawLine(rect.x + rect.width, y + 1, right - 1, y + 1); + } + } + else + { + g.setColor(shadow); + g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1); + } + } + } + } + + /** + * Paints the lower edge of the content border. + * + * @param g the graphics to use for painting + * @param tabPlacement the tab placement + * @param selectedIndex the index of the selected tab + * @param x the upper left coordinate of the content area + * @param y the upper left coordinate of the content area + * @param w the width of the content area + * @param h the height of the content area + */ + protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + g.setColor(darkShadow); + + // If tabs are not placed on BOTTOM, or if the selected tab is not in the + // run directly below the content or the selected tab is not visible, + // then we draw an unbroken line. + Rectangle rect = selectedIndex < 0 ? null : + getTabBounds(selectedIndex, calcRect); + boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme; + Color oceanSelectedBorder = + UIManager.getColor("TabbedPane.borderHightlightColor"); + if (tabPlacement != BOTTOM || selectedIndex < 0 || rect.y - 1 > h + || rect.x < x || rect.x > x + w) + { + if (isOcean && tabPlacement == BOTTOM) + { + g.setColor(oceanSelectedBorder); + } + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + } + else + { + boolean isLast = isLastTabInRun(selectedIndex); + if (isOcean) + { + g.setColor(oceanSelectedBorder); + } + + int bottom = y + h - 1; + int right = x + w - 1; + if (isLast) + { + g.drawLine(x, bottom, rect.x, bottom); + } + else + { + g.drawLine(x, bottom, rect.x - 1, bottom); + } + + if (rect.x + rect.width < x + w - 2) + { + if (isLast) + { + g.drawLine(rect.x + rect.width - 1, bottom, right, bottom); + } + else + { + g.drawLine(rect.x + rect.width, bottom, right, bottom); + } + } + } + } + + /** + * Paints the left edge of the content border. + * + * @param g the graphics to use for painting + * @param tabPlacement the tab placement + * @param selectedIndex the index of the selected tab + * @param x the upper left coordinate of the content area + * @param y the upper left coordinate of the content area + * @param w the width of the content area + * @param h the height of the content area + */ + protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme; + Color oceanSelectedBorder = + UIManager.getColor("TabbedPane.borderHightlightColor"); + Rectangle rect = selectedIndex < 0 ? null : + getTabBounds(selectedIndex, calcRect); + + if (isOcean) + { + g.setColor(oceanSelectedBorder); + } + else + { + g.setColor(selectHighlight); + } + + // If tabs are not placed on LEFT, or if the selected tab is not in the + // run directly left to the content or the selected tab is not visible, + // then we draw an unbroken line. + if (tabPlacement != LEFT || selectedIndex < 0 + || rect.x + rect.width + 1 < x || rect.y < y || rect.y > y + h) + { + g.drawLine(x, y + 1, x, y + h - 2); + if (isOcean && tabPlacement == LEFT) + { + g.setColor(MetalLookAndFeel.getWhite()); + g.drawLine(x, y + 1, x, y + h - 2); + } + } + else + { + g.drawLine(x, y, x, rect.y + 1); + if (rect.y + rect.height < y + h - 2) + { + g.drawLine(x, rect.y + rect.height + 1, x, y + h + 2); + } + if (isOcean) + { + g.setColor(MetalLookAndFeel.getWhite()); + g.drawLine(x + 1, y + 1, x + 1, rect.y + 1); + if (rect.y + rect.height < y + h - 2) + { + g.drawLine(x + y, rect.y + rect.height + 1, x + 1, y + h + 2); + } + } + } + + } + + /** + * Paints the right edge of the content border. + * + * @param g the graphics to use for painting + * @param tabPlacement the tab placement + * @param selectedIndex the index of the selected tab + * @param x the upper left coordinate of the content area + * @param y the upper left coordinate of the content area + * @param w the width of the content area + * @param h the height of the content area + */ + protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + g.setColor(darkShadow); + Rectangle rect = selectedIndex < 0 ? null : + getTabBounds(selectedIndex, calcRect); + boolean isOcean = MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme; + Color oceanSelectedBorder = + UIManager.getColor("TabbedPane.borderHightlightColor"); + + // If tabs are not placed on RIGHT, or if the selected tab is not in the + // run directly right to the content or the selected tab is not visible, + // then we draw an unbroken line. + if (tabPlacement != RIGHT || selectedIndex < 0 || rect.x - 1 > w + || rect.y < y || rect.y > y + h) + { + if (isOcean && tabPlacement == RIGHT) + { + g.setColor(oceanSelectedBorder); + } + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); + } + else + { + if (isOcean) + { + g.setColor(oceanSelectedBorder); + } + g.drawLine(x + w - 1, y, x + w - 1, rect.y); + + if (rect.y + rect.height < y + h - 2) + { + g.drawLine(x + w - 1, rect.y + rect.height, x + w - 1, y + h - 2); + } + } + } + + /** + * Determines if the specified tab is the last tab in its tab run. + * + * @param tabIndex the index of the tab + * + * @return if the specified tab is the last tab in its tab run + */ + private boolean isLastTabInRun(int tabIndex) + { + int count = tabPane.getTabCount(); + int run = getRunForTab(count, tabIndex); + int lastIndex = lastTabInRun(count, run); + return tabIndex == lastIndex; + } + + /** + * Returns the background for an unselected tab. This first asks the + * JTabbedPane for the background at the specified tab index, if this + * is an UIResource (that means, it is inherited from the JTabbedPane) + * and the TabbedPane.unselectedBackground UI property is not null, + * this returns the value of the TabbedPane.unselectedBackground property, + * otherwise the value returned by the JTabbedPane. + * + * @param tabIndex the index of the tab for which we query the background + * + * @return the background for an unselected tab + */ + private Color getUnselectedBackground(int tabIndex) + { + Color bg = tabPane.getBackgroundAt(tabIndex); + Color unselectedBackground = + UIManager.getColor("TabbedPane.unselectedBackground"); + if (bg instanceof UIResource && unselectedBackground != null) + bg = unselectedBackground; + return bg; + } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java index 0b56d591442..8c7a46e3a86 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java @@ -45,12 +45,14 @@ import java.awt.Graphics; import java.awt.Rectangle; import javax.swing.AbstractButton; +import javax.swing.ButtonModel; import javax.swing.JComponent; import javax.swing.JToggleButton; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicButtonUI; import javax.swing.plaf.basic.BasicToggleButtonUI; @@ -157,13 +159,15 @@ public class MetalToggleButtonUI /** * Paints the text for the button. * + * As of JDK 1.4 this method is obsolete. + * Use {@link BasicButtonUI#paintText(java.awt.Graphics, + * javax.swing.AbstractButton, java.awt.Rectangle, java.lang.String)}. + * * @param g the graphics device. * @param c the component. * @param textRect the bounds for the text. * @param text the text. * - * @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) @@ -207,7 +211,12 @@ public class MetalToggleButtonUI */ public void update(Graphics g, JComponent c) { - if (c.isOpaque() && UIManager.get(getPropertyPrefix() + "gradient") != null) + AbstractButton b = (AbstractButton) c; + ButtonModel m = b.getModel(); + if (b.getBackground() instanceof UIResource + && b.isContentAreaFilled() + && b.isEnabled() && ! m.isArmed() && ! m.isPressed() + && UIManager.get(getPropertyPrefix() + "gradient") != null) { MetalUtils.paintGradient(g, 0, 0, c.getWidth(), c.getHeight(), SwingConstants.VERTICAL, diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java index 16e22ac5286..1848c1f162d 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.Graphics; import java.awt.Point; import java.awt.event.ContainerListener; import java.awt.event.MouseEvent; @@ -46,6 +47,8 @@ import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JToolBar; +import javax.swing.SwingConstants; +import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.MouseInputListener; import javax.swing.plaf.ComponentUI; @@ -225,4 +228,71 @@ public class MetalToolBarUI extends BasicToolBarUI super.mouseDragged(e); } } + + /** + * Installs the UI on the toolbar. This calls super and sets the rollover + * property according to the <code>UIManager</code> property + * "ToolBar.isRollover". + * + * @param c the component to install the UI on + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JToolBar) + { + JToolBar tb = (JToolBar) c; + tb.setRollover(UIManager.getBoolean("ToolBar.isRollover")); + } + } + + /** + * Uninstalls the UI from the toolbar. This calls super and resets the + * rollover property. + * + * @param c the component to uninstall the UI from + */ + public void uninstallUI(JComponent c) + { + if (c instanceof JToolBar) + { + JToolBar tb = (JToolBar) c; + tb.setRollover(false); + } + super.uninstallUI(c); + } + + /** + * Paints the background of the component if necessary and then calls + * <code>paint(g, c)</code>. + * + * This is overridden to implement the OceanTheme gradient when an OceanTheme + * is installed. + * + * @param g the graphics to use + * @param c the component to paint. + * + * @since 1.5 + */ + public void update(Graphics g, JComponent c) + { + // TODO: Sun's implementation uses the MenuBar.gradient here. + // I would consider this a bug, but implement it like this + // for compatibility. + if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme + && UIManager.get("MenuBar.gradient") != null) + { + if (c.isOpaque()) + { + MetalUtils.paintGradient(g, 0, 0, c.getWidth(), c.getHeight(), + SwingConstants.VERTICAL, + "MenuBar.gradient"); + } + paint(g, c); + } + else + { + super.update(g, c); + } + } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java index 24432a2b5f6..3ea37c82f18 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import gnu.classpath.NotImplementedException; + import java.awt.Graphics; import java.awt.Insets; import java.awt.Rectangle; @@ -133,6 +135,7 @@ public class MetalTreeUI extends BasicTreeUI * @param lineStyleFlag - String representation */ protected void decodeLineStyle(Object lineStyleFlag) + throws NotImplementedException { // FIXME: not implemented } @@ -176,6 +179,7 @@ public class MetalTreeUI extends BasicTreeUI * @param c - the current component to draw */ protected void paintHorizontalSeparators(Graphics g, JComponent c) + throws NotImplementedException { // FIXME: not implemented } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java index b9d5ea76434..03617aa4099 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java @@ -91,7 +91,7 @@ class MetalUtils Color light, Color dark) { if (g instanceof Graphics2D - && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") != null) + && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") == null) fillMetalPattern2D((Graphics2D) g, x, y, w, h, light, dark); else { @@ -161,14 +161,35 @@ class MetalUtils /** * Paints the typical Metal gradient. See {@link #paintGradient(Graphics, - * int, int, int, int, double, double, Color, Color, Color, int)} + * int, int, int, int, float, float, Color, Color, Color, int, int[][])} + * for more details. + * + * This variant paints a gradient without a mask. + * + * @param g the graphics context to use + * @param x the X coordinate of the upper left corner of the rectangle + * @param y the Y coordinate of the upper left corner of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param dir the direction of the gradient, either + * @param uiProp the key of the UIManager property that has the parameters + */ + static void paintGradient(Graphics g, int x, int y, int w, int h, + int dir, String uiProp) + { + paintGradient(g, x, y, w, h, dir, uiProp, null); + } + + /** + * Paints the typical Metal gradient. See {@link #paintGradient(Graphics, + * int, int, int, int, float, float, Color, Color, Color, int, int[][])} * for more details. * * The parameters are fetched from the UIManager using the key * <code>uiProp</code>. The value is expected to be a {@link List} that * contains 4 values: two {@link Double}s and 3 {@link Color} object that * together make up the parameters passed to the painting method. - * + * * @param g the graphics context to use * @param x the X coordinate of the upper left corner of the rectangle * @param y the Y coordinate of the upper left corner of the rectangle @@ -176,17 +197,19 @@ class MetalUtils * @param h the height of the rectangle * @param dir the direction of the gradient, either * @param uiProp the key of the UIManager property that has the parameters + * @param mask the mask that should be used when painting the gradient as + * described above */ static void paintGradient(Graphics g, int x, int y, int w, int h, - int dir, String uiProp) + int dir, String uiProp, int[][] mask) { List params = (List) UIManager.get(uiProp); - double g1 = ((Double) params.get(0)).doubleValue(); - double g2 = ((Double) params.get(1)).doubleValue(); + float g1 = ((Float) params.get(0)).floatValue(); + float g2 = ((Float) params.get(1)).floatValue(); Color c1 = (Color) params.get(2); Color c2 = (Color) params.get(3); Color c3 = (Color) params.get(4); - paintGradient(g, x, y, w, h, g1, g2, c1, c2, c3, dir); + paintGradient(g, x, y, w, h, g1, g2, c1, c2, c3, dir, mask); } /** @@ -209,6 +232,33 @@ class MetalUtils * <li>A gradient from color 2 to color 1 with the relative width specified * by <code>g1</code></li> * + * The <code>mask</code> parameter is an array if int arrays, where the first + * index specifies the row (in the gradient direction), and the second index + * is the starting and end offset of that line. This way you can specify a + * mask that should be laid over the gradient for paintint non-rectangular + * gradients. The following example should demonstrate this for painting + * a circular shaped gradient (note that the first and last line should not + * be drawn at all, they are only here to show the circular shape more + * clearly). Everything <em>inside</code> the surrounded area is filled by + * the gradient: + * + * <pre> + * 012345678 + * xxx + * 0 x x { {4, 7}, + * 1 x x {3, 8}, + * 2 x x {3, 8}, + * 3 x x {3, 8}, + * 4 x x {4, 7} } + * xxx + * </pre> + * + * The <code>mask</code> array is expected to have <code>w</code> or + * <code>h</code> array elements, depending on the direction. + * + * If the <code>mask</code> parameter is null, then the gradient is painted + * without a mask. + * * @param g the graphics context to use * @param x the X coordinate of the upper left corner of the rectangle * @param y the Y coordinate of the upper left corner of the rectangle @@ -221,19 +271,23 @@ class MetalUtils * @param c3 the color 3 * @param dir the direction of the gradient, either * {@link SwingConstants#HORIZONTAL} or {@link SwingConstants#VERTICAL} + * @param mask the mask that should be used when painting the gradient as + * described above */ - static void paintGradient(Graphics g, int x, int y, int w, int h, double g1, - double g2, Color c1, Color c2, Color c3, int dir) + static void paintGradient(Graphics g, int x, int y, int w, int h, float g1, + float g2, Color c1, Color c2, Color c3, int dir, + int[][] mask) { if (dir == SwingConstants.HORIZONTAL) - paintHorizontalGradient(g, x, y, w, h, g1, g2, c1, c2, c3); + paintHorizontalGradient(g, x, y, w, h, g1, g2, c1, c2, c3, mask); else - paintVerticalGradient(g, x, y, w, h, g1, g2, c1, c2, c3); + paintVerticalGradient(g, x, y, w, h, g1, g2, c1, c2, c3, mask); } /** * Paints a horizontal gradient. See {@link #paintGradient(Graphics, int, - * int, int, int, double, double, Color, Color, Color, int)} for details. + * int, int, int, float, float, Color, Color, Color, int, int[][])} + * for details. * * @param x the X coordinate of the upper left corner of the rectangle * @param y the Y coordinate of the upper left corner of the rectangle @@ -244,12 +298,16 @@ class MetalUtils * @param c1 the color 1 * @param c2 the color 2 * @param c3 the color 3 + * @param mask the mask that should be used when painting the gradient as + * described above */ static void paintHorizontalGradient(Graphics g, int x, int y, int w, int h, - double g1, double g2, Color c1, Color c2, - Color c3) + float g1, float g2, Color c1, Color c2, + Color c3, int[][] mask) { // Calculate the coordinates. + int y0 = y; + int y1 = y + h; // The size of the first gradient area (c1->2). int w1 = (int) (w * g1); // The size of the solid c2 area. @@ -276,11 +334,28 @@ class MetalUtils + c1.getBlue()); Color interpolated = new Color(rInt, gInt, bInt); g.setColor(interpolated); - g.drawLine(xc, y, xc, y + h); + if (mask != null) + { + y0 = mask[xc - x0][0] + y; + y1 = mask[xc - x0][1] + y; + } + g.drawLine(xc, y0, xc, y1); } // Paint solid c2 area. g.setColor(c2); - g.fillRect(x1, y, x2 - x1, h); + if (mask == null) + { + g.fillRect(x1, y, x2 - x1, h); + } + else + { + for (xc = x1; xc < x2; xc++) + { + y0 = mask[xc - x0][0] + y; + y1 = mask[xc - x0][1] + y; + g.drawLine(xc, y0, xc, y1); + } + } // Paint second gradient area (c2->c1). for (xc = x2; xc < x3; xc++) @@ -297,7 +372,12 @@ class MetalUtils + c2.getBlue()); Color interpolated = new Color(rInt, gInt, bInt); g.setColor(interpolated); - g.drawLine(xc, y, xc, y + h); + if (mask != null) + { + y0 = mask[xc - x0][0] + y; + y1 = mask[xc - x0][1] + y; + } + g.drawLine(xc, y0, xc, y1); } // Paint third gradient area (c1->c3). @@ -315,13 +395,18 @@ class MetalUtils + c1.getBlue()); Color interpolated = new Color(rInt, gInt, bInt); g.setColor(interpolated); - g.drawLine(xc, y, xc, y + h); + if (mask != null) + { + y0 = mask[xc - x0][0] + y; + y1 = mask[xc - x0][1] + y; + } + g.drawLine(xc, y0, xc, y1); } } /** * Paints a vertical gradient. See {@link #paintGradient(Graphics, int, int, - * int, int, double, double, Color, Color, Color, int)} for details. + * int, int, float, float, Color, Color, Color, int, int[][])} for details. * * @param x the X coordinate of the upper left corner of the rectangle * @param y the Y coordinate of the upper left corner of the rectangle @@ -332,12 +417,16 @@ class MetalUtils * @param c1 the color 1 * @param c2 the color 2 * @param c3 the color 3 + * @param mask the mask that should be used when painting the gradient as + * described above */ static void paintVerticalGradient(Graphics g, int x, int y, int w, int h, double g1, double g2, Color c1, Color c2, - Color c3) + Color c3, int[][] mask) { // Calculate the coordinates. + int x0 = x; + int x1 = x + w; // The size of the first gradient area (c1->2). int w1 = (int) (h * g1); // The size of the solid c2 area. @@ -364,11 +453,28 @@ class MetalUtils + c1.getBlue()); Color interpolated = new Color(rInt, gInt, bInt); g.setColor(interpolated); - g.drawLine(x, yc, x + w, yc); + if (mask != null) + { + x0 = mask[yc - y0][0] + x; + x1 = mask[yc - y0][1] + x; + } + g.drawLine(x0, yc, x1, yc); } // Paint solid c2 area. g.setColor(c2); - g.fillRect(x, y1, w, y2 - y1); + if (mask == null) + { + g.fillRect(x, y1, w, y2 - y1); + } + else + { + for (yc = y1; yc < y2; yc++) + { + x0 = mask[yc - y0][0] + x; + x1 = mask[yc - y0][1] + x; + g.drawLine(x0, yc, x1, yc); + } + } // Paint second gradient area (c2->c1). for (yc = y2; yc < y3; yc++) @@ -385,7 +491,12 @@ class MetalUtils + c2.getBlue()); Color interpolated = new Color(rInt, gInt, bInt); g.setColor(interpolated); - g.drawLine(x, yc, x + w, yc); + if (mask != null) + { + x0 = mask[yc - y0][0] + x; + x1 = mask[yc - y0][1] + x; + } + g.drawLine(x0, yc, x1, yc); } // Paint third gradient area (c1->c3). @@ -403,7 +514,12 @@ class MetalUtils + c1.getBlue()); Color interpolated = new Color(rInt, gInt, bInt); g.setColor(interpolated); - g.drawLine(x, yc, x + w, yc); + if (mask != null) + { + x0 = mask[yc - y0][0] + x; + x1 = mask[yc - y0][1] + x; + } + g.drawLine(x0, yc, x1, yc); } } } diff --git a/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java index d1fc4cfecde..9d76ff7e808 100644 --- a/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java +++ b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java @@ -38,10 +38,12 @@ exception statement from your version. */ package javax.swing.plaf.metal; import java.awt.Color; +import java.awt.Insets; import java.util.Arrays; import javax.swing.UIDefaults; import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.BorderUIResource.LineBorderUIResource; /** * A modern theme for the Metal Look & Feel. @@ -207,41 +209,108 @@ public class OceanTheme extends DefaultMetalTheme */ public void addCustomEntriesToTable(UIDefaults defaults) { + // Gradients. defaults.put("Button.gradient", Arrays.asList(new Object[] - {new Double(0.3), new Double(0.0), new ColorUIResource(221, 232, 243), + {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243), new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); defaults.put("CheckBox.gradient", Arrays.asList(new Object[] - {new Double(0.3), new Double(0.0), new ColorUIResource(221, 232, 243), + {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243), new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); defaults.put("CheckBoxMenuItem.gradient", Arrays.asList(new Object[] - {new Double(0.3), new Double(0.0), new ColorUIResource(221, 232, 243), + {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243), new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); defaults.put("MenuBar.gradient", Arrays.asList(new Object[] - {new Double(1.0), new Double(0.0), new ColorUIResource(Color.WHITE), + {new Float(1.0), new Float(0.0), new ColorUIResource(Color.WHITE), new ColorUIResource(218, 218, 218), new ColorUIResource(218, 218, 218)})); defaults.put("RadioButton.gradient", Arrays.asList(new Object[] - {new Double(0.3), new Double(0.0), new ColorUIResource(221, 232, 243), + {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243), new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); defaults.put("RadioButtonMenuItem.gradient", Arrays.asList(new Object[] - {new Double(0.3), new Double(0.0), new ColorUIResource(221, 232, 243), + {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243), new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); defaults.put("ScrollBar.gradient", Arrays.asList(new Object[] - {new Double(1.0), new Double(0.0), new ColorUIResource(Color.WHITE), - new ColorUIResource(218, 218, 218), new ColorUIResource(218, 218, 218)})); + {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243), + new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); defaults.put("Slider.gradient", Arrays.asList(new Object[] - {new Double(0.3), new Double(0.2), new ColorUIResource(200, 221, 242), + {new Float(0.3), new Float(0.2), new ColorUIResource(200, 221, 242), + new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); + defaults.put("Slider.focusGradient", Arrays.asList(new Object[] + {new Float(0.3), new Float(0.2), new ColorUIResource(200, 221, 242), new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); defaults.put("ToggleButton.gradient", Arrays.asList(new Object[] - {new Double(0.3), new Double(0.0), new ColorUIResource(221, 232, 243), + {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243), new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); defaults.put("InternalFrame.activeTitleGradient", Arrays.asList(new Object[] - {new Double(0.3), new Double(0.0), new ColorUIResource(221, 232, 243), + {new Float(0.3), new Float(0.0), new ColorUIResource(221, 232, 243), new ColorUIResource(Color.WHITE), new ColorUIResource(184, 207, 229)})); - + // Colors. + ColorUIResource c1 = new ColorUIResource(200, 221, 242); + ColorUIResource c2 = new ColorUIResource(153, 153, 153); + ColorUIResource c3 = new ColorUIResource(204, 204, 204); + ColorUIResource c4 = new ColorUIResource(210, 226, 239); + ColorUIResource c5 = new ColorUIResource(218, 218, 218); + defaults.put("Button.disabledToolBarBorderBackground", c3); + defaults.put("Button.toolBarBorderBackground", c2); + defaults.put("Label.disabledForeground", c2); + defaults.put("MenuBar.borderColor", c3); + defaults.put("Slider.altTrackColor", c4); + defaults.put("SplitPane.dividerFocusColor", c1); + defaults.put("TabbedPane.contentAreaColor", c1); + defaults.put("TabbedPane.borderHightlightColor", PRIMARY1); + defaults.put("TabbedPane.selected", c1); + defaults.put("TabbedPane.tabAreaBackground", c5); + defaults.put("TabbedPane.unselectedBackground", SECONDARY3); + defaults.put("Table.gridColor", SECONDARY1); + defaults.put("ToolBar.borderColor", c3); + defaults.put("Tree.selectionBorderColor", PRIMARY1); + + // Borders. + defaults.put("Table.focusCellHighlightBorder", + new LineBorderUIResource(getPrimary1())); + + // Insets. + defaults.put("TabbedPane.contentBorderInsets", new Insets(4, 2, 3, 3)); + defaults.put("TabbedPane.tabAreaInsets", new Insets(2, 2, 0, 6)); + + // Flags. + defaults.put("SplitPane.oneTouchButtonsOpaque", Boolean.FALSE); + defaults.put("Menu.opaque", Boolean.FALSE); + defaults.put("ToolBar.isRollover", Boolean.TRUE); + defaults.put("RadioButton.rollover", Boolean.TRUE); + defaults.put("CheckBox.rollover", Boolean.TRUE); defaults.put("Button.rollover", Boolean.TRUE); - defaults.put("TabbedPane.selected", new ColorUIResource(200, 221, 242)); - defaults.put("TabbedPane.unselectedBackground", SECONDARY3); + // Icons. + // FIXME: Add OceanTheme icons. +// defaults.put("Tree.leafIcon", XXX); +// defaults.put("Tree.expandedIcon", XXX); +// defaults.put("Tree.openIcon", XXX); +// defaults.put("Tree.closedIcon", XXX); +// defaults.put("Tree.collapsedIcon", XXX); +// defaults.put("FileChooser.newFolderIcon", XXX); +// defaults.put("FileChooser.homeFolderIcon", XXX); +// defaults.put("FileChooser.upFolderIcon", XXX); +// defaults.put("FileView.hardDriveIcon", XXX); +// defaults.put("FileView.floppyDriveIcon", XXX); +// defaults.put("FileView.fileIcon", XXX); +// defaults.put("FileView.computerIcon", XXX); +// defaults.put("FileView.directoryIcon", XXX); +// defaults.put("OptionPane.questionIcon", XXX); +// defaults.put("OptionPane.errorIcon", XXX); +// defaults.put("OptionPane.warningIcon", XXX); +// defaults.put("OptionPane.informationIcon", XXX); +// defaults.put("InternalFrame.icon", XXX); +// defaults.put("InternalFrame.closeIcon", XXX); +// defaults.put("InternalFrame.iconifyIcon", XXX); +// defaults.put("InternalFrame.minimizeIcon", XXX); +// defaults.put("InternalFrame.maximizeIcon", XXX); +// defaults.put("InternalFrame.paletteCloseIcon", XXX); + + // UI classes. + defaults.put("MenuBarUI", "javax.swing.plaf.metal.MetalMenuBarUI"); + + // Others. + defaults.put("Button.rolloverIconType", "ocean"); } } |