2 Copyright (C) 2005, 2006, Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing.plaf.metal;
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Graphics;
44 import java.awt.Insets;
46 import javax.swing.AbstractButton;
47 import javax.swing.ButtonModel;
48 import javax.swing.JButton;
49 import javax.swing.JInternalFrame;
50 import javax.swing.JMenu;
51 import javax.swing.JMenuBar;
52 import javax.swing.JMenuItem;
53 import javax.swing.JOptionPane;
54 import javax.swing.JScrollPane;
55 import javax.swing.JTextField;
56 import javax.swing.JToggleButton;
57 import javax.swing.JToolBar;
58 import javax.swing.SwingConstants;
59 import javax.swing.UIManager;
60 import javax.swing.border.AbstractBorder;
61 import javax.swing.border.Border;
62 import javax.swing.border.CompoundBorder;
63 import javax.swing.plaf.BorderUIResource;
64 import javax.swing.plaf.UIResource;
65 import javax.swing.plaf.basic.BasicBorders;
66 import javax.swing.text.JTextComponent;
70 * A factory class that creates borders for the different Swing components.
72 * @author Roman Kennke (roman@kennke.org)
74 public class MetalBorders
77 /** The shared instance for getButtonBorder(). */
78 private static Border buttonBorder;
80 /** The shared instance for getToggleButtonBorder(). */
81 private static Border toggleButtonBorder;
83 /** The shared instance for getDesktopIconBorder(). */
84 private static Border desktopIconBorder;
86 /** The shared instance for getRolloverButtonBorder(). */
87 private static Border toolbarButtonBorder;
89 /** The shared instance for getTextFieldBorder(). */
90 private static Border textFieldBorder;
92 /** The shared instance for getTextBorder(). */
93 private static Border textBorder;
95 /** The shared instance for getRolloverBorder(). */
96 private static Border rolloverBorder;
99 * A MarginBorder that gets shared by multiple components.
100 * Created on demand by the private helper function {@link
101 * #getMarginBorder()}.
103 private static BasicBorders.MarginBorder marginBorder;
106 * <p>A border used for {@link JButton} components.</p>
108 * <p>This {@link Border} implementation can handle only instances of
109 * {@link AbstractButton} and their subclasses.</p>
111 * <p>If the Metal Look and Feel's current theme is 'Ocean' the border
112 * will be painted with a special highlight when the mouse cursor if
113 * over the button (ie. the property <code>rollover</code> of the
114 * button's model is <code>true</code>) and is not a <b>direct</b>
115 * child of a {@link JToolBar}.</p>
117 public static class ButtonBorder extends AbstractBorder implements UIResource
119 /** The borders insets. */
120 protected static Insets borderInsets = new Insets(3, 3, 3, 3);
123 * Creates a new instance of <code>ButtonBorder</code>.
125 public ButtonBorder()
127 // Nothing to do here.
131 * Paints the button border.
133 * @param c the component for which we paint the border
134 * @param g the Graphics context to use
135 * @param x the X coordinate of the upper left corner of c
136 * @param y the Y coordinate of the upper left corner of c
137 * @param w the width of c
138 * @param h the height of c
140 public void paintBorder(Component c, Graphics g, int x, int y, int w,
143 // With the OceanTheme the button border is painted entirely different.
144 // However, I couldn't figure out how this is determined besides checking
145 // for instanceof OceanTheme. The button painting is definitely not
146 // influenced by a UI default property and it is definitely performed
147 // by the same Border class.
148 if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
149 paintOceanButtonBorder(c, g, x, y, w, h);
151 paintDefaultButtonBorder(c, g, x, y, w, h);
155 * Paints the button border for the DefaultMetalTheme.
157 * @param c the component (button)
158 * @param g the graphics object to use
159 * @param x the upper left corner of the component, X coordinate
160 * @param y the upper left corner of the component, Y coordinate
161 * @param w the width of the component
162 * @param h the height of the component
164 private void paintDefaultButtonBorder(Component c, Graphics g, int x,
167 ButtonModel bmodel = null;
169 // The RI will fail with a ClassCastException in such a situation.
170 // This code tries to be more helpful.
171 if (c instanceof AbstractButton)
172 bmodel = ((AbstractButton) c).getModel();
174 throw new IllegalStateException("A ButtonBorder is supposed to work "
175 + "only with AbstractButton and"
178 Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
179 Color shadow = MetalLookAndFeel.getControlShadow();
180 Color light = MetalLookAndFeel.getControlHighlight();
181 Color middle = MetalLookAndFeel.getControl();
186 g.setColor(darkShadow);
187 g.drawRect(x, y, w - 2, h - 2);
189 // If the button is the default button, we paint a special border,
190 // regardless of the pressed state.
191 if (c instanceof JButton && ((JButton) c).isDefaultButton())
193 g.drawRect(x + 1, y + 1, w - 4, h - 4);
194 // Draw white highlight.
196 g.drawLine(x + 2, y + 2, x + w - 4, y + 2);
197 g.drawLine(x + 2, y + 2, x + 2, y + h - 4);
198 g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
199 g.drawLine(x + w - 1, y + 2, x + w - 1, y + h - 1);
200 // Draw crossing pixels.
202 g.fillRect(x + w - 2, y + 2, 1, 1);
203 g.fillRect(x + 2, y + h - 2, 1, 1);
207 // The normal border. This is used when the button is not
208 // pressed or the button is not armed.
209 if (! (bmodel.isPressed() && bmodel.isArmed()))
213 g.drawRect(x + 1, y + 1, w - 2, h - 2);
215 // draw crossing pixels of both borders
217 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
218 g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
220 // The pressed border. This border is painted only when
221 // the button is both pressed and armed.
226 g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
227 g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
229 // draw shadow border
231 g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
232 g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
234 // draw crossing pixels of both borders
236 g.drawRect(x + 1, y + h - 2, 0, 0);
237 g.drawRect(x + w - 2, y + 1, 0, 0);
243 // draw disabled border
244 g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
245 g.drawRect(x, y, w - 2, h - 2);
250 * Paints the button border for the OceanTheme.
252 * @param c the button
253 * @param g the graphics context
254 * @param x the X coordinate of the upper left corner of the painting rect
255 * @param y the Y coordinate of the upper left corner of the painting rect
256 * @param w the width of the painting rect
257 * @param h the height of the painting rect
259 private void paintOceanButtonBorder(Component c, Graphics g, int x,
262 ButtonModel bmodel = null;
264 // The RI will fail with a ClassCastException in such a situation.
265 // This code tries to be more helpful.
266 if (c instanceof AbstractButton)
267 bmodel = ((AbstractButton) c).getModel();
269 throw new IllegalStateException("A ButtonBorder is supposed to work "
270 + "only with AbstractButton and"
273 Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
274 Color shadow = MetalLookAndFeel.getControlShadow();
275 Color light = MetalLookAndFeel.getControlHighlight();
276 Color middle = MetalLookAndFeel.getControl();
280 // Paint the pressed border if the button is pressed, or if
281 // the button is the default button. In the OceanTheme, the default
282 // button has the same border as a pressed button.
283 if (bmodel.isPressed() || ((c instanceof JButton)
284 && ((JButton) c).isDefaultButton()))
287 g.setColor(darkShadow);
288 g.drawRect(x, y, w - 1, h - 1);
289 g.drawRect(x + 1, y + 1, w - 3, h - 3);
291 else if (bmodel.isRollover() && !(c.getParent() instanceof JToolBar))
293 // Paint a bigger border when the mouse is over the button but
294 // only if it is *not* part of a JToolBar.
296 g.drawRect(x, y, w - 1, h - 1);
297 g.drawRect(x + 2, y + 2, w - 5, h - 5);
298 g.setColor(darkShadow);
299 g.drawRect(x + 1, y + 1, w - 3, h - 3);
303 g.setColor(darkShadow);
304 g.drawRect(x, y, w - 1, h - 1);
309 // draw disabled border
310 g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
311 g.drawRect(x, y, w - 2, h - 2);
316 * Returns the insets of the <code>ButtonBorder</code>.
318 * @param c the component for which the border is used (ignored).
320 * @return The insets of the <code>ButtonBorder</code>.
322 public Insets getBorderInsets(Component c)
328 * Returns the insets of the <code>ButtonBorder</code> in the specified
329 * <code>newInsets</code> object.
331 * @param c the component for which the border is used (ignored).
332 * @param newInsets the insets object where to put the values (
333 * <code>null</code> not permitted).
335 * @return The <code>newInsets</code> reference.
337 public Insets getBorderInsets(Component c, Insets newInsets)
339 newInsets.bottom = borderInsets.bottom;
340 newInsets.left = borderInsets.left;
341 newInsets.right = borderInsets.right;
342 newInsets.top = borderInsets.top;
348 * A border used when painting {@link JInternalFrame} instances.
350 static class DesktopIconBorder extends AbstractBorder
351 implements UIResource
354 * Creates a new border instance.
356 public DesktopIconBorder()
358 // Nothing to do here.
362 * Returns the border insets.
364 * @param c the component (ignored).
366 * @return The border insets.
368 public Insets getBorderInsets(Component c)
370 return getBorderInsets(c, null);
374 * Returns the border insets.
376 * @param c the component (ignored).
377 * @return The border insets.
379 public Insets getBorderInsets(Component c, Insets newInsets)
381 if (newInsets == null)
382 newInsets = new Insets(3, 3, 2, 3);
387 newInsets.bottom = 2;
394 * Paints the border for the specified component.
396 * @param c the component.
397 * @param g the graphics device.
398 * @param x the x-coordinate.
399 * @param y the y-coordinate.
400 * @param w the width.
401 * @param h the height.
403 public void paintBorder(Component c, Graphics g, int x, int y, int w,
406 g.setColor(MetalLookAndFeel.getControlDarkShadow());
407 g.drawRect(x, y, w - 1, h - 1);
413 * A simple 3D border.
415 public static class Flush3DBorder extends AbstractBorder
416 implements UIResource
418 private static final Insets borderInsets = new Insets(2, 2, 2, 2);
421 * Creates a new border instance.
423 public Flush3DBorder()
425 // Nothing to do here.
429 * Returns the border insets.
431 * @param c the component (ignored).
433 * @return The border insets.
435 public Insets getBorderInsets(Component c)
441 * Returns the border insets.
443 * @param c the component (ignored).
444 * @param newInsets an existing insets instance, that will be populated
445 * with the border insets and returned as the result
446 * (<code>null</code> not permitted).
448 * @return The <code>newInsets</code> reference.
450 public Insets getBorderInsets(Component c, Insets newInsets)
452 newInsets.top = borderInsets.top;
453 newInsets.left = borderInsets.left;
454 newInsets.bottom = borderInsets.bottom;
455 newInsets.right = borderInsets.right;
460 * Paints the border for the specified component.
462 * @param c the component (ignored).
463 * @param g the graphics device.
464 * @param x the x-coordinate.
465 * @param y the y-coordinate.
466 * @param w the width.
467 * @param h the height.
469 public void paintBorder(Component c, Graphics g, int x, int y, int w,
472 Color savedColor = g.getColor();
473 g.setColor(MetalLookAndFeel.getControlDarkShadow());
474 g.drawRect(x, y, w - 2, h - 2);
475 g.setColor(MetalLookAndFeel.getControlHighlight());
476 g.drawRect(x + 1, y + 1, w - 2, h - 2);
477 g.setColor(MetalLookAndFeel.getControl());
478 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
479 g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
480 g.setColor(savedColor);
486 * A border used for a {@link JInternalFrame} when it is being used as a
491 public static class PaletteBorder extends AbstractBorder
492 implements UIResource
494 private static final Insets borderInsets = new Insets(1, 1, 1, 1);
497 * Creates a new <code>PaletteBorder</code>.
499 public PaletteBorder()
501 // Nothing to do here.
505 * Returns the border insets.
507 * @param c the component (ignored).
509 * @return The border insets.
511 public Insets getBorderInsets(Component c)
517 * Returns the border insets.
519 * @param c the component (ignored).
520 * @param newInsets an existing insets instance, that will be populated
521 * with the border insets and returned as the result
522 * (<code>null</code> not permitted).
524 * @return The <code>newInsets</code> reference.
526 public Insets getBorderInsets(Component c, Insets newInsets)
528 newInsets.top = borderInsets.top;
529 newInsets.left = borderInsets.left;
530 newInsets.bottom = borderInsets.bottom;
531 newInsets.right = borderInsets.right;
536 * Paints the border for the specified component.
538 * @param c the component (ignored).
539 * @param g the graphics device.
540 * @param x the x-coordinate.
541 * @param y the y-coordinate.
542 * @param w the width.
543 * @param h the height.
545 public void paintBorder(Component c, Graphics g, int x, int y, int w,
548 Color savedColor = g.getColor();
551 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
552 g.drawRect(x, y, w - 1, h - 1);
554 // put a dot in each corner
555 g.setColor(MetalLookAndFeel.getControl());
556 g.fillRect(x, y, 1, 1);
557 g.fillRect(x + w - 1, y, 1, 1);
558 g.fillRect(x + w - 1, y + h - 1, 1, 1);
559 g.fillRect(x, y + h - 1, 1, 1);
560 g.setColor(savedColor);
566 * A border used for the {@link JTextField} component.
568 public static class TextFieldBorder extends Flush3DBorder
569 implements UIResource
572 * Creates a new border instance.
574 public TextFieldBorder()
576 // Nothing to do here.
580 * Paints the border for the specified component.
582 * @param c the component (ignored).
583 * @param g the graphics device.
584 * @param x the x-coordinate.
585 * @param y the y-coordinate.
586 * @param w the width.
587 * @param h the height.
589 public void paintBorder(Component c, Graphics g, int x, int y, int w,
592 boolean enabledTextBorder;
593 if (c instanceof JTextComponent)
595 JTextComponent tc = (JTextComponent) c;
596 enabledTextBorder = tc.isEnabled() && tc.isEditable();
599 enabledTextBorder = false;
601 if (enabledTextBorder)
602 super.paintBorder(c, g, x, y, w, h);
605 Color savedColor = g.getColor();
606 g.setColor(MetalLookAndFeel.getControlShadow());
607 g.drawRect(x, y, w - 1, h - 1);
608 g.setColor(savedColor);
615 * A border used for the {@link JInternalFrame} component.
617 public static class InternalFrameBorder extends AbstractBorder
618 implements UIResource
620 private static final Insets borderInsets = new Insets(5, 5, 5, 5);
623 * Creates a new border instance.
625 public InternalFrameBorder()
627 // Nothing to do here.
631 * Returns the border insets.
633 * @param c the component (ignored).
635 * @return The border insets.
637 public Insets getBorderInsets(Component c)
643 * Returns the border insets.
645 * @param c the component (ignored).
646 * @param newInsets an existing insets instance, that will be populated
647 * with the border insets and returned as the result
648 * (<code>null</code> not permitted).
650 * @return The <code>newInsets</code> reference.
652 public Insets getBorderInsets(Component c, Insets newInsets)
654 newInsets.top = borderInsets.top;
655 newInsets.left = borderInsets.left;
656 newInsets.bottom = borderInsets.bottom;
657 newInsets.right = borderInsets.right;
662 * Paints the border for the specified component.
664 * @param c the component.
665 * @param g the graphics device.
666 * @param x the x-coordinate.
667 * @param y the y-coordinate.
668 * @param w the width.
669 * @param h the height.
671 public void paintBorder(Component c, Graphics g, int x, int y, int w,
675 JInternalFrame f = (JInternalFrame) c;
677 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
679 g.setColor(MetalLookAndFeel.getControlDarkShadow());
681 // fill the border background
682 g.fillRect(x, y, w, 5);
683 g.fillRect(x, y, 5, h);
684 g.fillRect(x + w - 5, y, 5, h);
685 g.fillRect(x, y + h - 5, w, 5);
687 // draw a dot in each corner
688 g.setColor(MetalLookAndFeel.getControl());
689 g.fillRect(x, y, 1, 1);
690 g.fillRect(x + w - 1, y, 1, 1);
691 g.fillRect(x + w - 1, y + h - 1, 1, 1);
692 g.fillRect(x, y + h - 1, 1, 1);
695 g.setColor(MetalLookAndFeel.getBlack());
696 g.drawLine(x + 14, y + 2, x + w - 15, y + 2);
697 g.drawLine(x + 14, y + h - 3, x + w - 15, y + h - 3);
698 g.drawLine(x + 2, y + 14, x + 2, y + h - 15);
699 g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15);
701 // draw the line highlights
703 g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
705 g.setColor(MetalLookAndFeel.getControlShadow());
706 g.drawLine(x + 15, y + 3, x + w - 14, y + 3);
707 g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2);
708 g.drawLine(x + 3, y + 15, x + 3, y + h - 14);
709 g.drawLine(x + w - 2, y + 15, x + w - 2, y + h - 14);
715 * A border used for {@link JInternalFrame} components that are
716 * presented as dialogs (by the {@link JOptionPane} class).
718 public static class OptionDialogBorder extends AbstractBorder
719 implements UIResource
723 * Creates a new border instance.
725 public OptionDialogBorder()
727 // Nothing to do here.
731 * Returns the border insets.
733 * @param c the component (ignored).
735 * @return The border insets.
737 public Insets getBorderInsets(Component c)
739 return getBorderInsets(c, null);
743 * Returns the border insets.
745 * @param c the component (ignored).
746 * @return The border insets.
748 public Insets getBorderInsets(Component c, Insets newInsets)
750 if (newInsets == null)
751 newInsets = new Insets(3, 3, 3, 3);
756 newInsets.bottom = 3;
763 * Paints the border for the specified component.
765 * @param c the component.
766 * @param g the graphics device.
767 * @param x the x-coordinate.
768 * @param y the y-coordinate.
769 * @param w the width.
770 * @param h the height.
772 public void paintBorder(Component c, Graphics g, int x, int y, int w,
776 JInternalFrame f = (JInternalFrame) c;
777 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
778 if (f.getContentPane() instanceof JOptionPane)
780 JOptionPane pane = (JOptionPane) f.getContentPane();
781 int type = pane.getMessageType();
782 if (type == JOptionPane.QUESTION_MESSAGE)
784 Color bc = UIManager.getColor(
785 "OptionPane.questionDialog.border.background");
789 if (type == JOptionPane.WARNING_MESSAGE)
791 Color bc = UIManager.getColor(
792 "OptionPane.warningDialog.border.background");
796 else if (type == JOptionPane.ERROR_MESSAGE)
798 Color bc = UIManager.getColor(
799 "OptionPane.errorDialog.border.background");
805 // fill the border background
806 g.fillRect(x, y, w, 3);
807 g.fillRect(x, y, 3, h);
808 g.fillRect(x + w - 3, y, 3, h);
809 g.fillRect(x, y + h - 3, w, 3);
811 // draw a dot in each corner
812 g.setColor(MetalLookAndFeel.getControl());
813 g.fillRect(x, y, 1, 1);
814 g.fillRect(x + w - 1, y, 1, 1);
815 g.fillRect(x + w - 1, y + h - 1, 1, 1);
816 g.fillRect(x, y + h - 1, 1, 1);
823 * A border used for {@link JMenu} and {@link JMenuItem} components.
825 public static class MenuItemBorder extends AbstractBorder
826 implements UIResource
828 /** The border insets. */
829 protected static Insets borderInsets = new Insets(2, 2, 2, 2);
832 * Creates a new border instance.
834 public MenuItemBorder()
836 // Nothing to do here.
840 * Paints the border for the component. A border is painted only if the
841 * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
843 * @param c the component.
844 * @param g the graphics device.
845 * @param x the x-coordinate of the border area.
846 * @param y the y-coordinate of the border area.
847 * @param w the width of the border area.
848 * @param h the height of the border area.
850 public void paintBorder(Component c, Graphics g, int x, int y, int w,
853 Color dark = MetalLookAndFeel.getPrimaryControlDarkShadow();
854 Color light = MetalLookAndFeel.getPrimaryControlHighlight();
855 if (c instanceof JMenu)
857 JMenu menu = (JMenu) c;
858 if (menu.isSelected())
861 g.drawLine(x, y, x, y + h);
862 g.drawLine(x, y, x + w, y);
863 g.drawLine(x + w - 2, y + 1, x + w - 2, y + h);
865 g.drawLine(x + w - 1, y + 1, x + w - 1, y + h);
868 else if (c instanceof JMenuItem)
870 JMenuItem item = (JMenuItem) c;
874 g.drawLine(x, y, x + w, y);
876 g.drawLine(x, y + h - 1, x + w, y + h - 1);
880 // Normally we draw a light line on the left.
882 g.drawLine(x, y, x, y + h);
888 * Returns the border insets.
890 * @param c the component (ignored).
892 * @return The border insets.
894 public Insets getBorderInsets(Component c)
900 * Populates <code>insets</code> with the border insets, then returns it.
902 * @param c the component (ignored).
903 * @param insets the object to populate with the border insets.
905 * @return The border insets.
907 * @throws NullPointerException if <code>insets</code> is <code>null</code>.
909 public Insets getBorderInsets(Component c, Insets insets)
911 insets.left = borderInsets.left;
912 insets.top = borderInsets.top;
913 insets.bottom = borderInsets.bottom;
914 insets.right = borderInsets.right;
920 * A border used for {@link JMenuBar} components.
922 public static class MenuBarBorder
923 extends AbstractBorder
924 implements UIResource
926 /** The border insets. */
927 protected static Insets borderInsets = new Insets(1, 0, 1, 0);
930 * Creates a new border instance.
932 public MenuBarBorder()
937 * Paints the border for the component. A border is painted only if the
938 * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
940 * @param c the component.
941 * @param g the graphics device.
942 * @param x the x-coordinate of the border area.
943 * @param y the y-coordinate of the border area.
944 * @param w the width of the border area.
945 * @param h the height of the border area.
947 public void paintBorder(Component c, Graphics g, int x, int y, int w,
950 // Although it is not correct to decide on the static property
951 // currentTheme which color to use the RI does it like that.
952 // The trouble is that by simply changing the current theme to
953 // e.g. DefaultMetalLookAndFeel this method will use another color
954 // although a change in painting behavior should be expected only
955 // after setting a new look and feel and updating all components.
956 if(MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
957 g.setColor(UIManager.getColor("MenuBar.borderColor"));
959 g.setColor(MetalLookAndFeel.getControlShadow());
961 g.drawLine(x, y + h - 1, x + w, y + h - 1);
965 * Returns the border insets.
967 * @param c the component (ignored).
969 * @return The border insets.
971 public Insets getBorderInsets(Component c)
977 * Populates <code>insets</code> with the border insets, then returns it.
979 * @param c the component (ignored).
980 * @param insets the object to populate with the border insets.
982 * @return The border insets.
984 * @throws NullPointerException if <code>insets</code> is <code>null</code>.
986 public Insets getBorderInsets(Component c, Insets insets)
988 insets.left = borderInsets.left;
989 insets.top = borderInsets.top;
990 insets.bottom = borderInsets.bottom;
991 insets.right = borderInsets.right;
997 * A border for {@link JScrollPane} components.
999 public static class ScrollPaneBorder
1000 extends AbstractBorder
1001 implements UIResource
1003 /** The border insets. */
1004 private static Insets insets = new Insets(1, 1, 2, 2);
1007 * Constructs a new ScrollPaneBorder.
1009 public ScrollPaneBorder()
1011 // Nothing to do here.
1015 * Returns the insets of the border for the Component <code>c</code>.
1017 * @param c the Component for which we return the border insets
1019 public Insets getBorderInsets(Component c)
1025 * Paints the border.
1027 * @param c the Component for which the border is painted
1028 * @param g the Graphics context
1029 * @param x the X coordinate of the upper left corner of the border
1030 * @param y the Y coordinate of the upper left corner of the border
1031 * @param w the width of the border
1032 * @param h the height of the border
1034 public void paintBorder(Component c, Graphics g, int x, int y,
1037 Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
1038 Color shadow = MetalLookAndFeel.getControlShadow();
1039 Color light = MetalLookAndFeel.getWhite();
1040 Color middle = MetalLookAndFeel.getControl();
1042 // paint top border line
1043 g.setColor(darkShadow);
1044 g.drawLine(x, y, x + w - 2, y);
1046 // paint left border line
1047 g.drawLine(x, y, x, y + h - 2);
1049 // paint right inner border line
1050 g.drawLine(x + w - 2, y, x + w - 2, y + h + 1);
1052 // paint bottom inner border line
1053 g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2);
1055 // draw right outer border line
1057 g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
1059 // draw bottom outer border line
1060 g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
1062 // paint the lighter points
1064 g.drawLine(x + w - 1, y, x + w - 1, y);
1065 g.drawLine(x + w - 2, y + 2, x + w - 2, y + 2);
1066 g.drawLine(x, y + h - 1, x, y + h - 1);
1067 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1074 * A button border that is only visible when the mouse pointer is within
1075 * the button's bounds.
1077 public static class RolloverButtonBorder
1078 extends MetalBorders.ButtonBorder
1081 * Creates a new border instance.
1083 public RolloverButtonBorder()
1085 // Nothing to do here.
1089 * Paints the border.
1091 * @param c the component.
1092 * @param g the graphics device.
1093 * @param x the x-coordinate.
1094 * @param y the y-coordinate.
1095 * @param w the width.
1096 * @param h the height.
1098 public void paintBorder(Component c, Graphics g, int x, int y, int w,
1101 // TODO: What should be done here? Obviously the ButtonBorder already
1102 // handles the rollover state in Sun's impl. Maybe this is only there
1103 // for backwards compatibility.
1104 super.paintBorder(c, g, x, y, w, h);
1109 * This border is used in Toolbar buttons as inner border.
1111 static class RolloverMarginBorder extends AbstractBorder
1113 /** The borders insets. */
1114 protected static Insets borderInsets = new Insets(3, 3, 3, 3);
1117 * Creates a new instance of RolloverBorder.
1119 public RolloverMarginBorder()
1121 // Nothing to do here.
1125 * Returns the insets of the RolloverBorder.
1127 * @param c the component for which the border is used
1129 * @return the insets of the RolloverBorder
1131 public Insets getBorderInsets(Component c)
1133 return getBorderInsets(c, null);
1137 * Returns the insets of the RolloverMarginBorder in the specified
1140 * @param c the component for which the border is used
1141 * @param newInsets the insets object where to put the values
1143 * @return the insets of the RolloverMarginBorder
1145 public Insets getBorderInsets(Component c, Insets newInsets)
1147 if (newInsets == null)
1148 newInsets = new Insets(0, 0, 0, 0);
1150 AbstractButton b = (AbstractButton) c;
1151 Insets margin = b.getMargin();
1152 newInsets.bottom = borderInsets.bottom;
1153 newInsets.left = borderInsets.left;
1154 newInsets.right = borderInsets.right;
1155 newInsets.top = borderInsets.top;
1161 * A border implementation for popup menus.
1163 public static class PopupMenuBorder
1164 extends AbstractBorder
1165 implements UIResource
1168 /** The border's insets. */
1169 protected static Insets borderInsets = new Insets(3, 1, 2, 1);
1172 * Constructs a new PopupMenuBorder.
1174 public PopupMenuBorder()
1176 // Nothing to do here.
1180 * Returns the insets of the border, creating a new Insets instance
1183 * @param c the component for which we return the border insets
1186 public Insets getBorderInsets(Component c)
1188 return getBorderInsets(c, null);
1192 * Returns the insets of the border, using the supplied Insets instance.
1194 * @param c the component for which we return the border insets
1196 * @param i the Insets instance to fill with the Insets values
1198 public Insets getBorderInsets(Component c, Insets i)
1202 insets = new Insets(borderInsets.top, borderInsets.left,
1203 borderInsets.bottom, borderInsets.right);
1207 insets.top = borderInsets.top;
1208 insets.left = borderInsets.left;
1209 insets.bottom = borderInsets.bottom;
1210 insets.right = borderInsets.right;
1217 * Paints the border for component <code>c</code> using the
1218 * Graphics context <code>g</code> with the dimension
1219 * <code>x, y, w, h</code>.
1221 * @param c the component for which we paint the border
1222 * @param g the Graphics context to use
1223 * @param x the X coordinate of the upper left corner of c
1224 * @param y the Y coordinate of the upper left corner of c
1225 * @param w the width of c
1226 * @param h the height of c
1228 public void paintBorder(Component c, Graphics g, int x, int y, int w,
1231 Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
1232 Color light = MetalLookAndFeel.getPrimaryControlHighlight();
1234 // draw dark outer border
1235 g.setColor(darkShadow);
1236 g.drawRect(x, y, w - 1, h - 1);
1238 // draw highlighted inner border (only top and left)
1240 g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
1246 * A border used for the {@link JToggleButton} component.
1250 public static class ToggleButtonBorder
1251 extends ButtonBorder
1254 * Creates a new border instance.
1256 public ToggleButtonBorder()
1258 // Nothing to do here.
1262 * Paints the toggle button border.
1264 * @param c the component for which we paint the border
1265 * @param g the Graphics context to use
1266 * @param x the X coordinate of the upper left corner of c
1267 * @param y the Y coordinate of the upper left corner of c
1268 * @param w the width of c
1269 * @param h the height of c
1271 public void paintBorder(Component c, Graphics g, int x, int y, int w,
1274 ButtonModel bmodel = null;
1276 if (c instanceof AbstractButton)
1277 bmodel = ((AbstractButton) c).getModel();
1279 Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
1280 Color shadow = MetalLookAndFeel.getControlShadow();
1281 Color light = MetalLookAndFeel.getWhite();
1282 Color middle = MetalLookAndFeel.getControl();
1287 g.setColor(darkShadow);
1288 g.drawRect(x, y, w - 2, h - 2);
1290 if (!bmodel.isArmed())
1292 // draw light border
1294 g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1295 g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
1296 if (bmodel.isSelected())
1298 g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
1299 g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
1301 // draw crossing pixels of both borders
1303 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1304 g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
1308 // draw light border
1310 g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
1311 g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1313 // draw shadow border
1315 g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
1316 g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
1318 // draw crossing pixels of both borders
1320 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1321 g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
1326 g.drawLine(x, y + h - 1, x, y + h - 1);
1327 g.drawLine(x + w - 1, y, x + w - 1, y);
1331 // draw disabled border
1332 g.setColor(MetalLookAndFeel.getControlDisabled());
1333 g.drawRect(x, y, w - 2, h - 2);
1339 * A border used for the {@link JToolBar} component.
1341 public static class ToolBarBorder extends AbstractBorder
1342 implements UIResource, SwingConstants
1345 * Creates a new border instance.
1347 public ToolBarBorder()
1349 // Nothing to do here.
1353 * Returns the border insets.
1355 * @param c the component (ignored).
1357 * @return The border insets.
1359 public Insets getBorderInsets(Component c)
1361 return getBorderInsets(c, null);
1365 * Returns the border insets.
1367 * @param c the component (ignored).
1368 * @return The border insets.
1370 public Insets getBorderInsets(Component c, Insets newInsets)
1372 JToolBar tb = (JToolBar) c;
1373 if (tb.getOrientation() == JToolBar.HORIZONTAL)
1375 if (newInsets == null)
1376 newInsets = new Insets(2, 16, 2, 2);
1380 newInsets.left = 16;
1381 newInsets.bottom = 2;
1382 newInsets.right = 2;
1386 else // assume JToolBar.VERTICAL
1388 if (newInsets == null)
1389 newInsets = new Insets(16, 2, 2, 2);
1394 newInsets.bottom = 2;
1395 newInsets.right = 2;
1403 * Paints the border for the specified component.
1405 * @param c the component.
1406 * @param g the graphics device.
1407 * @param x the x-coordinate.
1408 * @param y the y-coordinate.
1409 * @param w the width.
1410 * @param h the height.
1412 public void paintBorder(Component c, Graphics g, int x, int y, int w,
1416 JToolBar tb = (JToolBar) c;
1417 if (tb.getOrientation() == JToolBar.HORIZONTAL)
1419 MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + 11, y + h - 5,
1420 MetalLookAndFeel.getControlHighlight(),
1421 MetalLookAndFeel.getControlDarkShadow());
1425 MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + w - 5, y + 11,
1426 MetalLookAndFeel.getControlHighlight(),
1427 MetalLookAndFeel.getControlDarkShadow());
1434 * A border for table header cells.
1438 public static class TableHeaderBorder extends AbstractBorder
1441 * The insets of this border.
1443 // TODO: According to tests that I have done, this is really the border
1444 // that should be returned by getBorderInsets(). However, the name
1445 // is very distracting. Is there any deeper meaning in it?
1446 protected Insets editorBorderInsets;
1449 * Creates a new instance of <code>TableHeaderBorder</code>.
1451 public TableHeaderBorder()
1453 editorBorderInsets = new Insets(1, 1, 1, 1);
1457 * Return the insets of this border.
1459 * @return the insets of this border
1461 public Insets getBorderInsets(Component c)
1463 return editorBorderInsets;
1467 * Paints the border.
1469 * @param c the component for which to paint the border
1470 * @param g the graphics context to use
1471 * @param x the x cooridinate of the border rectangle
1472 * @param y the y cooridinate of the border rectangle
1473 * @param w the width of the border rectangle
1474 * @param h the height of the border rectangle
1476 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
1478 Color dark = MetalLookAndFeel.getControlDarkShadow();
1479 Color light = MetalLookAndFeel.getWhite();
1480 Color old = g.getColor();
1482 g.drawLine(x, y, x + w - 2, y);
1483 g.drawLine(x, y, x, y + h - 2);
1485 g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
1486 g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1492 * Returns a border for Swing buttons in the Metal Look & Feel.
1494 * @return a border for Swing buttons in the Metal Look & Feel
1496 public static Border getButtonBorder()
1498 if (buttonBorder == null)
1500 Border outer = new ButtonBorder();
1501 Border inner = getMarginBorder();
1502 buttonBorder = new BorderUIResource.CompoundBorderUIResource(outer,
1505 return buttonBorder;
1509 * Returns a border for use with {@link JToggleButton} components.
1515 public static Border getToggleButtonBorder()
1517 if (toggleButtonBorder == null)
1519 Border outer = new ToggleButtonBorder();
1520 Border inner = getMarginBorder();
1521 toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
1524 return toggleButtonBorder;
1528 * Returns a border instance that is used with a {@link JInternalFrame} when
1529 * it is in the iconified state.
1535 public static Border getDesktopIconBorder()
1537 if (desktopIconBorder == null)
1538 desktopIconBorder = new DesktopIconBorder();
1539 return desktopIconBorder;
1543 * Returns a border for use by the {@link JTextField} component.
1549 public static Border getTextFieldBorder()
1551 if (textFieldBorder == null)
1553 Border inner = getMarginBorder();
1554 Border outer = new TextFieldBorder();
1556 new BorderUIResource.CompoundBorderUIResource(outer, inner);
1558 return textFieldBorder;
1562 * Returns the border that is used for text components (except text fields,
1563 * which use {@link #getTextFieldBorder}.
1565 * @return the border that is used for text components
1569 public static Border getTextBorder()
1571 if (textBorder == null)
1573 Border inner = getMarginBorder();
1574 Border outer = new Flush3DBorder();
1576 new BorderUIResource.CompoundBorderUIResource(outer, inner);
1582 * Returns a border for Toolbar buttons in the Metal Look & Feel.
1584 * @return a border for Toolbar buttons in the Metal Look & Feel
1586 static Border getToolbarButtonBorder()
1588 if (toolbarButtonBorder == null)
1590 Border outer = new ButtonBorder();
1591 Border inner = new RolloverMarginBorder();
1592 toolbarButtonBorder = new CompoundBorder(outer, inner);
1594 return toolbarButtonBorder;
1598 * Returns a shared instance of {@link BasicBorders.MarginBorder}.
1600 * @return a shared instance of {@link BasicBorders.MarginBorder}
1602 static Border getMarginBorder()
1604 if (marginBorder == null)
1605 marginBorder = new BasicBorders.MarginBorder();
1606 return marginBorder;
1610 * Returns a shared instance of a compound border for rollover buttons.
1612 * @return A shared border instance.
1614 static Border getRolloverBorder()
1616 if (rolloverBorder == null)
1618 Border outer = new MetalBorders.RolloverButtonBorder();
1619 Border inner = MetalBorders.getMarginBorder();
1620 rolloverBorder = new BorderUIResource.CompoundBorderUIResource(outer,
1623 return rolloverBorder;