OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / plaf / metal / MetalBorders.java
1 /* MetalBorders.java
2    Copyright (C) 2005, 2006, Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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)
9 any later version.
10
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.
15
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
19 02110-1301 USA.
20
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
24 combination.
25
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. */
37
38
39 package javax.swing.plaf.metal;
40
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Graphics;
44 import java.awt.Insets;
45
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;
67
68
69 /**
70  * A factory class that creates borders for the different Swing components.
71  *
72  * @author Roman Kennke (roman@kennke.org)
73  */
74 public class MetalBorders
75 {
76
77   /** The shared instance for getButtonBorder(). */
78   private static Border buttonBorder;
79
80   /** The shared instance for getToggleButtonBorder(). */
81   private static Border toggleButtonBorder;
82
83   /** The shared instance for getDesktopIconBorder(). */
84   private static Border desktopIconBorder;
85
86   /** The shared instance for getRolloverButtonBorder(). */
87   private static Border toolbarButtonBorder;
88
89   /** The shared instance for getTextFieldBorder(). */
90   private static Border textFieldBorder;
91
92   /** The shared instance for getTextBorder(). */
93   private static Border textBorder;
94
95   /** The shared instance for getRolloverBorder(). */
96   private static Border rolloverBorder;
97
98   /**
99    * A MarginBorder that gets shared by multiple components.
100    * Created on demand by the private helper function {@link
101    * #getMarginBorder()}.
102    */
103   private static BasicBorders.MarginBorder marginBorder;
104
105   /**
106    * <p>A border used for {@link JButton} components.</p>
107    * 
108    * <p>This {@link Border} implementation can handle only instances of
109    * {@link AbstractButton} and their subclasses.</p>
110    * 
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> 
116    */
117   public static class ButtonBorder extends AbstractBorder implements UIResource
118   {
119     /** The borders insets. */
120     protected static Insets borderInsets = new Insets(3, 3, 3, 3);
121
122     /**
123      * Creates a new instance of <code>ButtonBorder</code>.
124      */
125     public ButtonBorder()
126     {
127       // Nothing to do here.
128     }
129
130     /**
131      * Paints the button border.
132      *
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
139      */
140     public void paintBorder(Component c, Graphics g, int x, int y, int w,
141                             int h)
142     {
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);
150       else
151         paintDefaultButtonBorder(c, g, x, y, w, h);
152     }
153
154     /**
155      * Paints the button border for the DefaultMetalTheme.
156      *
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
163      */
164     private void paintDefaultButtonBorder(Component c, Graphics g, int x,
165                                           int y, int w, int h)
166     {
167       ButtonModel bmodel = null;
168
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();
173       else
174         throw new IllegalStateException("A ButtonBorder is supposed to work "
175                                         + "only with AbstractButton and"
176                                         + "subclasses.");
177
178       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
179       Color shadow = MetalLookAndFeel.getControlShadow();
180       Color light = MetalLookAndFeel.getControlHighlight();
181       Color middle = MetalLookAndFeel.getControl();
182
183       if (c.isEnabled())
184         {
185           // draw dark border
186           g.setColor(darkShadow);
187           g.drawRect(x, y, w - 2, h - 2);
188
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())
192             {
193               g.drawRect(x + 1, y + 1, w - 4, h - 4);
194               // Draw white highlight.
195               g.setColor(light);
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.
201               g.setColor(middle);
202               g.fillRect(x + w - 2, y + 2, 1, 1);
203               g.fillRect(x + 2, y + h - 2, 1, 1);
204             }
205           else
206             {
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()))
210                 {
211                   // draw light border
212                   g.setColor(light);
213                   g.drawRect(x + 1, y + 1, w - 2, h - 2);
214
215                   // draw crossing pixels of both borders
216                   g.setColor(middle);
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);
219                 }
220               // The pressed border. This border is painted only when
221               // the button is both pressed and armed.
222               else
223                 {
224                   // draw light border
225                   g.setColor(light);
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);
228
229                   // draw shadow border
230                   g.setColor(middle);
231                   g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
232                   g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
233  
234                   // draw crossing pixels of both borders
235                   g.setColor(shadow);
236                   g.drawRect(x + 1, y + h - 2, 0, 0);
237                   g.drawRect(x + w - 2, y + 1, 0, 0);
238                 }
239             }
240         }
241       else 
242         {
243           // draw disabled border
244           g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
245           g.drawRect(x, y, w - 2, h - 2);          
246         }
247     }
248
249     /**
250      * Paints the button border for the OceanTheme.
251      *
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
258      */
259     private void paintOceanButtonBorder(Component c, Graphics g, int x,
260                                         int y, int w, int h)
261     {
262       ButtonModel bmodel = null;
263       
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();
268       else
269         throw new IllegalStateException("A ButtonBorder is supposed to work "
270                                         + "only with AbstractButton and"
271                                         + "subclasses.");
272
273       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
274       Color shadow = MetalLookAndFeel.getControlShadow();
275       Color light = MetalLookAndFeel.getControlHighlight();
276       Color middle = MetalLookAndFeel.getControl();
277
278       if (c.isEnabled())
279         {
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()))
285             {
286               // Draw fat border.
287               g.setColor(darkShadow);
288               g.drawRect(x, y, w - 1, h - 1);
289               g.drawRect(x + 1, y + 1, w - 3, h - 3);
290             }
291           else if (bmodel.isRollover() && !(c.getParent() instanceof JToolBar))
292             {
293               // Paint a bigger border when the mouse is over the button but
294               // only if it is *not* part of a JToolBar.
295               g.setColor(shadow);
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);
300             }
301           else
302             {
303               g.setColor(darkShadow);
304               g.drawRect(x, y, w - 1, h - 1);
305             }
306         }
307       else 
308         {
309           // draw disabled border
310           g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
311           g.drawRect(x, y, w - 2, h - 2);          
312         }
313     }
314
315     /**
316      * Returns the insets of the <code>ButtonBorder</code>.
317      *
318      * @param c the component for which the border is used (ignored).
319      *
320      * @return The insets of the <code>ButtonBorder</code>.
321      */
322     public Insets getBorderInsets(Component c)
323     {
324       return borderInsets;
325     }
326
327     /**
328      * Returns the insets of the <code>ButtonBorder</code> in the specified 
329      * <code>newInsets</code> object.
330      *
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).
334      *
335      * @return The <code>newInsets</code> reference.
336      */
337     public Insets getBorderInsets(Component c, Insets newInsets)
338     {
339       newInsets.bottom = borderInsets.bottom;
340       newInsets.left = borderInsets.left;
341       newInsets.right = borderInsets.right;
342       newInsets.top = borderInsets.top;
343       return newInsets;
344     }
345   }
346
347   /**
348    * A border used when painting {@link JInternalFrame} instances.
349    */
350   static class DesktopIconBorder extends AbstractBorder
351     implements UIResource
352   {
353     /**
354      * Creates a new border instance.
355      */
356     public DesktopIconBorder()
357     {
358       // Nothing to do here.
359     }
360     
361     /**
362      * Returns the border insets.
363      * 
364      * @param c  the component (ignored).
365      * 
366      * @return The border insets.
367      */
368     public Insets getBorderInsets(Component c)
369     {
370       return getBorderInsets(c, null);
371     }
372     
373     /**
374      * Returns the border insets.
375      * 
376      * @param c  the component (ignored).
377      * @return The border insets.
378      */
379     public Insets getBorderInsets(Component c, Insets newInsets)
380     {
381       if (newInsets == null)
382         newInsets = new Insets(3, 3, 2, 3);
383       else
384         {
385           newInsets.top = 3;
386           newInsets.left = 3;
387           newInsets.bottom = 2;
388           newInsets.right = 3;
389         }
390       return newInsets;  
391     }
392     
393     /**
394      * Paints the border for the specified component.
395      * 
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.
402      */
403     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
404         int h)
405     {
406       g.setColor(MetalLookAndFeel.getControlDarkShadow());      
407       g.drawRect(x, y, w - 1, h - 1); 
408     }
409     
410   }
411
412   /**
413    * A simple 3D border.
414    */
415   public static class Flush3DBorder extends AbstractBorder
416     implements UIResource
417   {
418     private static final Insets borderInsets = new Insets(2, 2, 2, 2);
419     
420     /**
421      * Creates a new border instance.
422      */
423     public Flush3DBorder()
424     {
425       // Nothing to do here.
426     }
427     
428     /**
429      * Returns the border insets.
430      * 
431      * @param c  the component (ignored).
432      * 
433      * @return The border insets.
434      */
435     public Insets getBorderInsets(Component c)
436     {
437       return borderInsets;
438     }
439     
440     /**
441      * Returns the border insets.
442      * 
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).
447      *                   
448      * @return The <code>newInsets</code> reference.
449      */
450     public Insets getBorderInsets(Component c, Insets newInsets)
451     {
452       newInsets.top = borderInsets.top;
453       newInsets.left = borderInsets.left;
454       newInsets.bottom = borderInsets.bottom;
455       newInsets.right = borderInsets.right;
456       return newInsets;  
457     }
458     
459     /**
460      * Paints the border for the specified component.
461      * 
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.
468      */
469     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
470         int h)
471     {              
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);
481     }
482     
483   }
484     
485   /**
486    * A border used for a {@link JInternalFrame} when it is being used as a 
487    * palette.
488    * 
489    * @since 1.3
490    */
491   public static class PaletteBorder extends AbstractBorder
492     implements UIResource
493   {
494     private static final Insets borderInsets = new Insets(1, 1, 1, 1);
495
496     /**
497      * Creates a new <code>PaletteBorder</code>.
498      */
499     public PaletteBorder()
500     {
501       // Nothing to do here.
502     }
503     
504     /**
505      * Returns the border insets.
506      * 
507      * @param c  the component (ignored).
508      * 
509      * @return The border insets.
510      */
511     public Insets getBorderInsets(Component c)
512     {
513       return borderInsets;
514     }
515
516     /**
517      * Returns the border insets.
518      * 
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).
523      *                   
524      * @return The <code>newInsets</code> reference.
525      */
526     public Insets getBorderInsets(Component c, Insets newInsets)
527     {        
528       newInsets.top = borderInsets.top;
529       newInsets.left = borderInsets.left;
530       newInsets.bottom = borderInsets.bottom;
531       newInsets.right = borderInsets.right;
532       return newInsets;  
533     }
534     
535     /**
536      * Paints the border for the specified component.
537      * 
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.
544      */
545     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
546             int h)
547     {
548       Color savedColor = g.getColor();
549       
550       // draw the outline
551       g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
552       g.drawRect(x, y, w - 1, h - 1);
553       
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);
561     }
562
563   }
564     
565   /**
566    * A border used for the {@link JTextField} component.
567    */
568   public static class TextFieldBorder extends Flush3DBorder
569     implements UIResource
570   {
571     /**
572      * Creates a new border instance.
573      */
574     public TextFieldBorder()
575     {
576       // Nothing to do here.
577     }
578     
579     /**
580      * Paints the border for the specified component.
581      * 
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.
588      */
589     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
590         int h)
591     {
592       boolean enabledTextBorder;
593       if (c instanceof JTextComponent)
594         {
595           JTextComponent tc = (JTextComponent) c;
596           enabledTextBorder = tc.isEnabled() && tc.isEditable();
597         }
598       else
599         enabledTextBorder = false;
600
601       if (enabledTextBorder)
602         super.paintBorder(c, g, x, y, w, h);
603       else
604         {
605           Color savedColor = g.getColor();
606           g.setColor(MetalLookAndFeel.getControlShadow());
607           g.drawRect(x, y, w - 1, h - 1);
608           g.setColor(savedColor);
609         }
610     }
611     
612   }
613
614   /**
615    * A border used for the {@link JInternalFrame} component.
616    */
617   public static class InternalFrameBorder extends AbstractBorder
618     implements UIResource
619   {
620     private static final Insets borderInsets = new Insets(5, 5, 5, 5);
621
622     /**
623      * Creates a new border instance.
624      */
625     public InternalFrameBorder()
626     {
627       // Nothing to do here.
628     }
629     
630     /**
631      * Returns the border insets.
632      * 
633      * @param c  the component (ignored).
634      * 
635      * @return The border insets.
636      */
637     public Insets getBorderInsets(Component c)
638     {
639       return borderInsets;
640     }
641     
642     /**
643      * Returns the border insets.
644      * 
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).
649      *                   
650      * @return The <code>newInsets</code> reference.
651      */
652     public Insets getBorderInsets(Component c, Insets newInsets)
653     {
654       newInsets.top = borderInsets.top;
655       newInsets.left = borderInsets.left;
656       newInsets.bottom = borderInsets.bottom;
657       newInsets.right = borderInsets.right;
658       return newInsets;  
659     }
660     
661     /**
662      * Paints the border for the specified component.
663      * 
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.
670      */
671     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
672         int h)
673     {
674         
675       JInternalFrame f = (JInternalFrame) c;
676       if (f.isSelected())
677         g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
678       else
679         g.setColor(MetalLookAndFeel.getControlDarkShadow());
680       
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);
686       
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);
693       
694       // draw the lines
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);
700       
701       // draw the line highlights
702       if (f.isSelected())
703         g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
704       else 
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);
710     }
711     
712   }
713
714   /**
715    * A border used for {@link JInternalFrame} components that are
716    * presented as dialogs (by the {@link JOptionPane} class).
717    */
718   public static class OptionDialogBorder extends AbstractBorder
719     implements UIResource
720   {
721       
722     /**
723      * Creates a new border instance.
724      */
725     public OptionDialogBorder()
726     {
727       // Nothing to do here.
728     }
729     
730     /**
731      * Returns the border insets.
732      * 
733      * @param c  the component (ignored).
734      * 
735      * @return The border insets.
736      */
737     public Insets getBorderInsets(Component c)
738     {
739       return getBorderInsets(c, null);
740     }
741     
742     /**
743      * Returns the border insets.
744      * 
745      * @param c  the component (ignored).
746      * @return The border insets.
747      */
748     public Insets getBorderInsets(Component c, Insets newInsets)
749     {
750       if (newInsets == null)
751         newInsets = new Insets(3, 3, 3, 3);
752       else
753         {
754           newInsets.top = 3;
755           newInsets.left = 3;
756           newInsets.bottom = 3;
757           newInsets.right = 3;
758         }
759       return newInsets;  
760     }
761         
762     /**
763      * Paints the border for the specified component.
764      * 
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.
771      */
772     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
773         int h)
774     {
775         
776       JInternalFrame f = (JInternalFrame) c;
777       g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
778       if (f.getContentPane() instanceof JOptionPane)
779         {
780           JOptionPane pane = (JOptionPane) f.getContentPane();
781           int type = pane.getMessageType();
782           if (type == JOptionPane.QUESTION_MESSAGE)
783             {
784               Color bc = UIManager.getColor(
785                   "OptionPane.questionDialog.border.background");
786               if (bc != null)
787                 g.setColor(bc);
788             }
789           if (type == JOptionPane.WARNING_MESSAGE)
790             {
791               Color bc = UIManager.getColor(
792                   "OptionPane.warningDialog.border.background");
793               if (bc != null)
794                 g.setColor(bc);              
795             }
796           else if (type == JOptionPane.ERROR_MESSAGE)
797             {
798               Color bc = UIManager.getColor(
799                   "OptionPane.errorDialog.border.background");
800               if (bc != null)
801                 g.setColor(bc);              
802             }
803         }
804       
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);
810       
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);
817       
818     }
819     
820   }
821
822   /**
823    * A border used for {@link JMenu} and {@link JMenuItem} components.
824    */
825   public static class MenuItemBorder extends AbstractBorder
826     implements UIResource
827   {
828     /** The border insets. */
829     protected static Insets borderInsets = new Insets(2, 2, 2, 2);
830     
831     /**
832      * Creates a new border instance.
833      */
834     public MenuItemBorder()
835     {
836       // Nothing to do here.
837     }
838     
839     /**
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}.
842      * 
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.
849      */
850     public void paintBorder(Component c, Graphics g, int x, int y, int w,
851         int h)
852     {
853       Color dark = MetalLookAndFeel.getPrimaryControlDarkShadow();
854       Color light = MetalLookAndFeel.getPrimaryControlHighlight();
855       if (c instanceof JMenu) 
856         {
857           JMenu menu = (JMenu) c;
858           if (menu.isSelected())
859             {
860               g.setColor(dark);
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);
864               g.setColor(light);
865               g.drawLine(x + w - 1, y + 1, x + w - 1, y + h);
866             }
867         }
868       else if (c instanceof JMenuItem)
869         {
870           JMenuItem item = (JMenuItem) c;
871           if (item.isArmed()) 
872             {
873               g.setColor(dark);
874               g.drawLine(x, y, x + w, y);
875               g.setColor(light);
876               g.drawLine(x, y + h - 1, x + w, y + h - 1);
877             }
878           else
879             {
880               // Normally we draw a light line on the left.
881               g.setColor(light);
882               g.drawLine(x, y, x, y + h);
883             }
884         }
885     }
886     
887     /**
888      * Returns the border insets.
889      * 
890      * @param c  the component (ignored).
891      * 
892      * @return The border insets.
893      */
894     public Insets getBorderInsets(Component c)
895     {
896       return borderInsets;
897     }
898     
899     /**
900      * Populates <code>insets</code> with the border insets, then returns it.
901      * 
902      * @param c  the component (ignored).
903      * @param insets  the object to populate with the border insets.
904      * 
905      * @return The border insets.
906      * 
907      * @throws NullPointerException if <code>insets</code> is <code>null</code>.
908      */
909     public Insets getBorderInsets(Component c, Insets insets)
910     {
911       insets.left = borderInsets.left;
912       insets.top = borderInsets.top;
913       insets.bottom = borderInsets.bottom;
914       insets.right = borderInsets.right;
915       return insets;
916     }
917   }
918
919   /**
920    * A border used for {@link JMenuBar} components.
921    */
922   public static class MenuBarBorder
923       extends AbstractBorder
924       implements UIResource
925   {
926     /** The border insets. */
927     protected static Insets borderInsets = new Insets(1, 0, 1, 0);
928     
929     /**
930      * Creates a new border instance.
931      */
932     public MenuBarBorder()
933     {
934     }
935     
936     /**
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}.
939      * 
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.
946      */
947     public void paintBorder(Component c, Graphics g, int x, int y, int w,
948         int h)
949     {
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"));
958       else
959         g.setColor(MetalLookAndFeel.getControlShadow());
960       
961       g.drawLine(x, y + h - 1, x + w, y + h - 1);
962     }
963     
964     /**
965      * Returns the border insets.
966      * 
967      * @param c  the component (ignored).
968      * 
969      * @return The border insets.
970      */
971     public Insets getBorderInsets(Component c)
972     {
973       return borderInsets;
974     }
975     
976     /**
977      * Populates <code>insets</code> with the border insets, then returns it.
978      * 
979      * @param c  the component (ignored).
980      * @param insets  the object to populate with the border insets.
981      * 
982      * @return The border insets.
983      * 
984      * @throws NullPointerException if <code>insets</code> is <code>null</code>.
985      */
986     public Insets getBorderInsets(Component c, Insets insets)
987     {
988       insets.left = borderInsets.left;
989       insets.top = borderInsets.top;
990       insets.bottom = borderInsets.bottom;
991       insets.right = borderInsets.right;
992       return insets;
993     }
994   }
995
996   /**
997    * A border for {@link JScrollPane} components.
998    */
999   public static class ScrollPaneBorder
1000     extends AbstractBorder
1001     implements UIResource
1002   {
1003     /** The border insets. */
1004     private static Insets insets = new Insets(1, 1, 2, 2);
1005     
1006     /**
1007      * Constructs a new ScrollPaneBorder.
1008      */
1009     public ScrollPaneBorder()
1010     {
1011       // Nothing to do here.
1012     }
1013     
1014     /**
1015      * Returns the insets of the border for the Component <code>c</code>.
1016      *
1017      * @param c the Component for which we return the border insets
1018      */
1019     public Insets getBorderInsets(Component c)
1020     {
1021       return insets;
1022     }
1023
1024     /**
1025      * Paints the border.
1026      *
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
1033      */
1034     public void paintBorder(Component c, Graphics g, int x, int y,
1035                             int w, int h)
1036     {
1037       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
1038       Color shadow = MetalLookAndFeel.getControlShadow();
1039       Color light = MetalLookAndFeel.getWhite();
1040       Color middle = MetalLookAndFeel.getControl();
1041
1042       // paint top border line
1043       g.setColor(darkShadow);
1044       g.drawLine(x, y, x + w - 2, y);
1045
1046       // paint left border line
1047       g.drawLine(x, y, x, y + h - 2);
1048  
1049       // paint right inner border line
1050       g.drawLine(x + w - 2, y, x + w - 2, y + h + 1);
1051
1052       // paint bottom inner border line
1053       g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2);
1054
1055       // draw right outer border line
1056       g.setColor(light);
1057       g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
1058
1059       // draw bottom outer border line
1060       g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
1061
1062       // paint the lighter points
1063       g.setColor(middle);
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);
1068
1069     }
1070     
1071   }
1072   
1073   /**
1074    * A button border that is only visible when the mouse pointer is within 
1075    * the button's bounds.
1076    */
1077   public static class RolloverButtonBorder
1078     extends MetalBorders.ButtonBorder
1079   {
1080     /**
1081      * Creates a new border instance.
1082      */
1083     public RolloverButtonBorder()
1084     {
1085       // Nothing to do here.
1086     }
1087     
1088     /**
1089      * Paints the border.
1090      * 
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.
1097      */
1098     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
1099             int h)
1100     {
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);
1105     }
1106   }
1107   
1108   /**
1109    * This border is used in Toolbar buttons as inner border.
1110    */
1111   static class RolloverMarginBorder extends AbstractBorder
1112   {
1113     /** The borders insets. */
1114     protected static Insets borderInsets = new Insets(3, 3, 3, 3);
1115
1116     /**
1117      * Creates a new instance of RolloverBorder.
1118      */
1119     public RolloverMarginBorder()
1120     {
1121       // Nothing to do here.
1122     }
1123     
1124     /**
1125      * Returns the insets of the RolloverBorder.
1126      *
1127      * @param c the component for which the border is used
1128      *
1129      * @return the insets of the RolloverBorder
1130      */
1131     public Insets getBorderInsets(Component c)
1132     {
1133       return getBorderInsets(c, null);
1134     }
1135
1136     /**
1137      * Returns the insets of the RolloverMarginBorder in the specified
1138      * Insets object.
1139      *
1140      * @param c the component for which the border is used
1141      * @param newInsets the insets object where to put the values
1142      *
1143      * @return the insets of the RolloverMarginBorder
1144      */
1145     public Insets getBorderInsets(Component c, Insets newInsets)
1146     {
1147       if (newInsets == null)
1148         newInsets = new Insets(0, 0, 0, 0);
1149
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;
1156       return newInsets;
1157     }
1158   }
1159
1160   /**
1161    * A border implementation for popup menus.
1162    */
1163   public static class PopupMenuBorder
1164     extends AbstractBorder
1165     implements UIResource
1166   {
1167
1168     /** The border's insets. */
1169     protected static Insets borderInsets = new Insets(3, 1, 2, 1);
1170
1171     /**
1172      * Constructs a new PopupMenuBorder.
1173      */
1174     public PopupMenuBorder()
1175     {
1176       // Nothing to do here.
1177     }
1178     
1179     /**
1180      * Returns the insets of the border, creating a new Insets instance
1181      * with each call.
1182      *
1183      * @param c the component for which we return the border insets
1184      *          (not used here)
1185      */
1186     public Insets getBorderInsets(Component c)
1187     {
1188       return getBorderInsets(c, null);
1189     }
1190     
1191     /**
1192      * Returns the insets of the border, using the supplied Insets instance.
1193      *
1194      * @param c the component for which we return the border insets
1195      *          (not used here)
1196      * @param i the Insets instance to fill with the Insets values
1197      */
1198     public Insets getBorderInsets(Component c, Insets i)
1199     {
1200       Insets insets;
1201       if (i == null)
1202         insets = new Insets(borderInsets.top, borderInsets.left,
1203                             borderInsets.bottom, borderInsets.right);
1204       else
1205         {
1206           insets = i;
1207           insets.top = borderInsets.top;
1208           insets.left = borderInsets.left;
1209           insets.bottom = borderInsets.bottom;
1210           insets.right = borderInsets.right;
1211         }
1212       
1213       return insets;
1214     }
1215
1216     /**
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>.
1220      *
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
1227      */
1228     public void paintBorder(Component c, Graphics g, int x, int y, int w,
1229                             int h)
1230     {
1231       Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
1232       Color light = MetalLookAndFeel.getPrimaryControlHighlight();
1233
1234       // draw dark outer border
1235       g.setColor(darkShadow);
1236       g.drawRect(x, y, w - 1, h - 1);
1237       
1238       // draw highlighted inner border (only top and left)
1239       g.setColor(light);
1240       g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
1241     }
1242     
1243   }
1244
1245   /**
1246    * A border used for the {@link JToggleButton} component.
1247    * 
1248    * @since 1.3
1249    */
1250   public static class ToggleButtonBorder
1251     extends ButtonBorder 
1252   {
1253     /**
1254      * Creates a new border instance.
1255      */
1256     public ToggleButtonBorder()
1257     {
1258       // Nothing to do here.
1259     }
1260     
1261     /**
1262      * Paints the toggle button border.
1263      *
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
1270      */
1271     public void paintBorder(Component c, Graphics g, int x, int y, int w,
1272                             int h)
1273     {
1274       ButtonModel bmodel = null;
1275       
1276       if (c instanceof AbstractButton)
1277         bmodel = ((AbstractButton) c).getModel();
1278
1279       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
1280       Color shadow = MetalLookAndFeel.getControlShadow();
1281       Color light = MetalLookAndFeel.getWhite();
1282       Color middle = MetalLookAndFeel.getControl();
1283
1284       if (c.isEnabled())
1285         {
1286           // draw dark border
1287           g.setColor(darkShadow);
1288           g.drawRect(x, y, w - 2, h - 2);
1289
1290           if (!bmodel.isArmed())
1291             {
1292               // draw light border
1293               g.setColor(light);
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())
1297                 g.setColor(middle);
1298               g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
1299               g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
1300
1301               // draw crossing pixels of both borders
1302               g.setColor(shadow);
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);
1305             }
1306           else
1307             {
1308               // draw light border
1309               g.setColor(light);
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);
1312
1313               // draw shadow border
1314               g.setColor(shadow);
1315               g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
1316               g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
1317  
1318               // draw crossing pixels of both borders
1319               g.setColor(shadow);
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);
1322               
1323             }
1324           // draw corners
1325           g.setColor(middle);
1326           g.drawLine(x, y + h - 1, x, y + h - 1);
1327           g.drawLine(x + w - 1, y, x + w - 1, y);
1328         }
1329       else 
1330         {
1331           // draw disabled border
1332           g.setColor(MetalLookAndFeel.getControlDisabled());
1333           g.drawRect(x, y, w - 2, h - 2);          
1334         }
1335     }
1336   }
1337
1338   /**
1339    * A border used for the {@link JToolBar} component.
1340    */
1341   public static class ToolBarBorder extends AbstractBorder
1342     implements UIResource, SwingConstants
1343   {
1344     /**
1345      * Creates a new border instance.
1346      */
1347     public ToolBarBorder()
1348     {
1349       // Nothing to do here.
1350     }
1351     
1352     /**
1353      * Returns the border insets.
1354      * 
1355      * @param c  the component (ignored).
1356      * 
1357      * @return The border insets.
1358      */
1359     public Insets getBorderInsets(Component c)
1360     {
1361       return getBorderInsets(c, null);
1362     }
1363     
1364     /**
1365      * Returns the border insets.
1366      * 
1367      * @param c  the component (ignored).
1368      * @return The border insets.
1369      */
1370     public Insets getBorderInsets(Component c, Insets newInsets)
1371     {
1372       JToolBar tb = (JToolBar) c;
1373       if (tb.getOrientation() == JToolBar.HORIZONTAL)
1374         {   
1375           if (newInsets == null)
1376             newInsets = new Insets(2, 16, 2, 2);
1377           else
1378             {
1379               newInsets.top = 2;
1380               newInsets.left = 16;
1381               newInsets.bottom = 2;
1382               newInsets.right = 2;
1383             }
1384           return newInsets;  
1385         }
1386       else // assume JToolBar.VERTICAL
1387         { 
1388           if (newInsets == null)
1389             newInsets = new Insets(16, 2, 2, 2);
1390           else
1391             {
1392               newInsets.top = 16;
1393               newInsets.left = 2;
1394               newInsets.bottom = 2;
1395               newInsets.right = 2;
1396             }
1397           return newInsets;  
1398         }
1399
1400     }
1401     
1402     /**
1403      * Paints the border for the specified component.
1404      * 
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.
1411      */
1412     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
1413         int h)
1414     {
1415         
1416       JToolBar tb = (JToolBar) c;
1417       if (tb.getOrientation() == JToolBar.HORIZONTAL)
1418         {
1419            MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + 11, y + h - 5, 
1420                   MetalLookAndFeel.getControlHighlight(), 
1421                   MetalLookAndFeel.getControlDarkShadow());
1422         }
1423       else
1424         { 
1425           MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + w - 5, y + 11, 
1426                   MetalLookAndFeel.getControlHighlight(), 
1427                   MetalLookAndFeel.getControlDarkShadow());
1428         }
1429     }
1430     
1431   }
1432   
1433   /**
1434    * A border for table header cells.
1435    *
1436    * @since 1.3
1437    */
1438   public static class TableHeaderBorder extends AbstractBorder
1439   {
1440     /**
1441      * The insets of this border.
1442      */
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;
1447
1448     /**
1449      * Creates a new instance of <code>TableHeaderBorder</code>.
1450      */
1451     public TableHeaderBorder()
1452     {
1453       editorBorderInsets = new Insets(1, 1, 1, 1);
1454     }
1455
1456     /**
1457      * Return the insets of this border.
1458      *
1459      * @return the insets of this border
1460      */
1461     public Insets getBorderInsets(Component c)
1462     {
1463       return editorBorderInsets;
1464     }
1465
1466     /**
1467      * Paints the border.
1468      *
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
1475      */
1476     public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
1477     {
1478       Color dark = MetalLookAndFeel.getControlDarkShadow();
1479       Color light = MetalLookAndFeel.getWhite();
1480       Color old = g.getColor();
1481       g.setColor(light);
1482       g.drawLine(x, y, x + w - 2, y);
1483       g.drawLine(x, y, x, y + h - 2);
1484       g.setColor(dark);
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);
1487       g.setColor(old);
1488     }
1489   }
1490
1491   /**
1492    * Returns a border for Swing buttons in the Metal Look &amp; Feel.
1493    *
1494    * @return a border for Swing buttons in the Metal Look &amp; Feel
1495    */
1496   public static Border getButtonBorder()
1497   {
1498     if (buttonBorder == null)
1499       {
1500         Border outer = new ButtonBorder();
1501         Border inner = getMarginBorder();
1502         buttonBorder = new BorderUIResource.CompoundBorderUIResource(outer, 
1503             inner);
1504       }
1505     return buttonBorder;
1506   }
1507   
1508   /**
1509    * Returns a border for use with {@link JToggleButton} components.
1510    *
1511    * @return A border.
1512    * 
1513    * @since 1.3
1514    */
1515   public static Border getToggleButtonBorder()
1516   {
1517     if (toggleButtonBorder == null)
1518       {
1519         Border outer = new ToggleButtonBorder();
1520         Border inner = getMarginBorder();
1521         toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
1522             outer, inner);
1523       }
1524     return toggleButtonBorder;
1525   }
1526
1527   /**
1528    * Returns a border instance that is used with a {@link JInternalFrame} when
1529    * it is in the iconified state.
1530    * 
1531    * @return A border.
1532    * 
1533    * @since 1.3
1534    */
1535   public static Border getDesktopIconBorder()
1536   {
1537     if (desktopIconBorder == null)
1538       desktopIconBorder = new DesktopIconBorder();
1539     return desktopIconBorder;      
1540   }
1541
1542   /**
1543    * Returns a border for use by the {@link JTextField} component.
1544    * 
1545    * @return A border.
1546    * 
1547    * @since 1.3
1548    */
1549   public static Border getTextFieldBorder()
1550   {
1551     if (textFieldBorder == null)
1552       {
1553         Border inner = getMarginBorder();
1554         Border outer = new TextFieldBorder();
1555         textFieldBorder =
1556           new BorderUIResource.CompoundBorderUIResource(outer, inner);
1557       }
1558     return textFieldBorder;
1559   }
1560
1561   /**
1562    * Returns the border that is used for text components (except text fields,
1563    * which use {@link #getTextFieldBorder}.
1564    *
1565    * @return the border that is used for text components
1566    *
1567    * @since 1.3
1568    */
1569   public static Border getTextBorder()
1570   {
1571     if (textBorder == null)
1572       {
1573         Border inner = getMarginBorder();
1574         Border outer = new Flush3DBorder();
1575         textBorder =
1576           new BorderUIResource.CompoundBorderUIResource(outer, inner);
1577       }
1578     return textBorder;
1579   }
1580
1581   /**
1582    * Returns a border for Toolbar buttons in the Metal Look &amp; Feel.
1583    *
1584    * @return a border for Toolbar buttons in the Metal Look &amp; Feel
1585    */
1586   static Border getToolbarButtonBorder()
1587   {
1588     if (toolbarButtonBorder == null)
1589       {
1590         Border outer = new ButtonBorder();
1591         Border inner = new RolloverMarginBorder();
1592         toolbarButtonBorder = new CompoundBorder(outer, inner);
1593       }
1594     return toolbarButtonBorder;
1595   }
1596
1597   /**
1598    * Returns a shared instance of {@link BasicBorders.MarginBorder}.
1599    *
1600    * @return a shared instance of {@link BasicBorders.MarginBorder}
1601    */
1602   static Border getMarginBorder()
1603   {
1604     if (marginBorder == null)
1605       marginBorder = new BasicBorders.MarginBorder();
1606     return marginBorder;
1607   }
1608
1609   /**
1610    * Returns a shared instance of a compound border for rollover buttons.
1611    * 
1612    * @return A shared border instance.
1613    */
1614   static Border getRolloverBorder()
1615   {
1616     if (rolloverBorder == null)
1617       {
1618         Border outer = new MetalBorders.RolloverButtonBorder();
1619         Border inner = MetalBorders.getMarginBorder();
1620         rolloverBorder = new BorderUIResource.CompoundBorderUIResource(outer, 
1621             inner);
1622       }
1623     return rolloverBorder;
1624   }
1625
1626 }