Source for javax.swing.plaf.metal.MetalBorders

   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:    * A border used for {@link JButton} components.
 107:    */
 108:   public static class ButtonBorder extends AbstractBorder implements UIResource
 109:   {
 110:     /** The borders insets. */
 111:     protected static Insets borderInsets = new Insets(3, 3, 3, 3);
 112: 
 113:     /**
 114:      * Creates a new instance of <code>ButtonBorder</code>.
 115:      */
 116:     public ButtonBorder()
 117:     {
 118:       // Nothing to do here.
 119:     }
 120: 
 121:     /**
 122:      * Paints the button border.
 123:      *
 124:      * @param c the component for which we paint the border
 125:      * @param g the Graphics context to use
 126:      * @param x the X coordinate of the upper left corner of c
 127:      * @param y the Y coordinate of the upper left corner of c
 128:      * @param w the width of c
 129:      * @param h the height of c
 130:      */
 131:     public void paintBorder(Component c, Graphics g, int x, int y, int w,
 132:                             int h)
 133:     {
 134:       // With the OceanTheme the button border is painted entirely different.
 135:       // However, I couldn't figure out how this is determined besides checking
 136:       // for instanceof OceanTheme. The button painting is definitely not
 137:       // influenced by a UI default property and it is definitely performed
 138:       // by the same Border class.
 139:       if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
 140:         paintOceanButtonBorder(c, g, x, y, w, h);
 141:       else
 142:         paintDefaultButtonBorder(c, g, x, y, w, h);
 143:     }
 144: 
 145:     /**
 146:      * Paints the button border for the DefaultMetalTheme.
 147:      *
 148:      * @param c the component (button)
 149:      * @param g the graphics object to use
 150:      * @param x the upper left corner of the component, X coordinate
 151:      * @param y the upper left corner of the component, Y coordinate
 152:      * @param w the width of the component
 153:      * @param h the height of the component
 154:      */
 155:     private void paintDefaultButtonBorder(Component c, Graphics g, int x,
 156:                                           int y, int w, int h)
 157:     {
 158:       ButtonModel bmodel = null;
 159: 
 160:       if (c instanceof AbstractButton)
 161:         bmodel = ((AbstractButton) c).getModel();
 162: 
 163:       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
 164:       Color shadow = MetalLookAndFeel.getControlShadow();
 165:       Color light = MetalLookAndFeel.getControlHighlight();
 166:       Color middle = MetalLookAndFeel.getControl();
 167: 
 168:       if (c.isEnabled())
 169:         {
 170:           // draw dark border
 171:           g.setColor(darkShadow);
 172:           g.drawRect(x, y, w - 2, h - 2);
 173: 
 174:           // If the button is the default button, we paint a special border,
 175:           // regardless of the pressed state.
 176:           if (c instanceof JButton && ((JButton) c).isDefaultButton())
 177:             {
 178:               g.drawRect(x + 1, y + 1, w - 4, h - 4);
 179:               // Draw white highlight.
 180:               g.setColor(light);
 181:               g.drawLine(x + 2, y + 2, x + w - 4, y + 2);
 182:               g.drawLine(x + 2, y + 2, x + 2, y + h - 4);
 183:               g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
 184:               g.drawLine(x + w - 1, y + 2, x + w - 1, y + h - 1);
 185:               // Draw crossing pixels.
 186:               g.setColor(middle);
 187:               g.fillRect(x + w - 2, y + 2, 1, 1);
 188:               g.fillRect(x + 2, y + h - 2, 1, 1);
 189:             }
 190:           else
 191:             {
 192:               // The normal border. This is used when the button is not
 193:               // pressed or the button is not armed.
 194:               if (! (bmodel.isPressed() && bmodel.isArmed()) )
 195:                 {
 196:                   // draw light border
 197:                   g.setColor(light);
 198:                   g.drawRect(x + 1, y + 1, w - 2, h - 2);
 199: 
 200:                   // draw crossing pixels of both borders
 201:                   g.setColor(middle);
 202:                   g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
 203:                   g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
 204:                 }
 205:               // The pressed border. This border is painted only when
 206:               // the button is both pressed and armed.
 207:               else
 208:                 {
 209:                   // draw light border
 210:                   g.setColor(light);
 211:                   g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
 212:                   g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
 213: 
 214:                   // draw shadow border
 215:                   g.setColor(middle);
 216:                   g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
 217:                   g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
 218:  
 219:                   // draw crossing pixels of both borders
 220:                   g.setColor(shadow);
 221:                   g.drawRect(x + 1, y + h - 2, 0, 0);
 222:                   g.drawRect(x + w - 2, y + 1, 0, 0);
 223:                 }
 224:             }
 225:         }
 226:       else 
 227:         {
 228:           // draw disabled border
 229:           g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
 230:           g.drawRect(x, y, w - 2, h - 2);          
 231:         }
 232:     }
 233: 
 234:     /**
 235:      * Paints the button border for the OceanTheme.
 236:      *
 237:      * @param c the button
 238:      * @param g the graphics context
 239:      * @param x the X coordinate of the upper left corner of the painting rect
 240:      * @param y the Y coordinate of the upper left corner of the painting rect
 241:      * @param w the width of the painting rect
 242:      * @param h the height of the painting rect
 243:      */
 244:     private void paintOceanButtonBorder(Component c, Graphics g, int x,
 245:                                         int y, int w, int h)
 246:     {
 247:       ButtonModel bmodel = null;
 248:       
 249:       if (c instanceof AbstractButton)
 250:         bmodel = ((AbstractButton) c).getModel();
 251: 
 252:       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
 253:       Color shadow = MetalLookAndFeel.getControlShadow();
 254:       Color light = MetalLookAndFeel.getControlHighlight();
 255:       Color middle = MetalLookAndFeel.getControl();
 256: 
 257:       if (c.isEnabled())
 258:         {
 259:           // Paint the pressed border if the button is pressed, or if
 260:           // the button is the default button. In the OceanTheme, the default
 261:           // button has the same border as a pressed button.
 262:           if (bmodel.isPressed() || ((c instanceof JButton)
 263:                                      && ((JButton) c).isDefaultButton()))
 264:             {
 265:               // Draw fat border.
 266:               g.setColor(darkShadow);
 267:               g.drawRect(x, y, w - 1, h - 1);
 268:               g.drawRect(x + 1, y + 1, w - 3, h - 3);
 269:             }
 270:           else if (bmodel.isRollover())
 271:             {
 272:               g.setColor(shadow);
 273:               g.drawRect(x, y, w - 1, h - 1);
 274:               g.drawRect(x + 2, y + 2, w - 5, h - 5);
 275:               g.setColor(darkShadow);
 276:               g.drawRect(x + 1, y + 1, w - 3, h - 3);
 277:             }
 278:           else
 279:             {
 280:               g.setColor(darkShadow);
 281:               g.drawRect(x, y, w - 1, h - 1);
 282:             }
 283:         }
 284:       else 
 285:         {
 286:           // draw disabled border
 287:           g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
 288:           g.drawRect(x, y, w - 2, h - 2);          
 289:         }
 290:     }
 291: 
 292:     /**
 293:      * Returns the insets of the <code>ButtonBorder</code>.
 294:      *
 295:      * @param c the component for which the border is used (ignored).
 296:      *
 297:      * @return The insets of the <code>ButtonBorder</code>.
 298:      */
 299:     public Insets getBorderInsets(Component c)
 300:     {
 301:       return borderInsets;
 302:     }
 303: 
 304:     /**
 305:      * Returns the insets of the <code>ButtonBorder</code> in the specified 
 306:      * <code>newInsets</code> object.
 307:      *
 308:      * @param c the component for which the border is used (ignored).
 309:      * @param newInsets the insets object where to put the values (
 310:      *                  <code>null</code> not permitted).
 311:      *
 312:      * @return The <code>newInsets</code> reference.
 313:      */
 314:     public Insets getBorderInsets(Component c, Insets newInsets)
 315:     {
 316:       newInsets.bottom = borderInsets.bottom;
 317:       newInsets.left = borderInsets.left;
 318:       newInsets.right = borderInsets.right;
 319:       newInsets.top = borderInsets.top;
 320:       return newInsets;
 321:     }
 322:   }
 323: 
 324:   /**
 325:    * A border used when painting {@link JInternalFrame} instances.
 326:    */
 327:   static class DesktopIconBorder extends AbstractBorder
 328:     implements UIResource
 329:   {
 330:     /**
 331:      * Creates a new border instance.
 332:      */
 333:     public DesktopIconBorder()
 334:     {
 335:       // Nothing to do here.
 336:     }
 337:     
 338:     /**
 339:      * Returns the border insets.
 340:      * 
 341:      * @param c  the component (ignored).
 342:      * 
 343:      * @return The border insets.
 344:      */
 345:     public Insets getBorderInsets(Component c)
 346:     {
 347:       return getBorderInsets(c, null);
 348:     }
 349:     
 350:     /**
 351:      * Returns the border insets.
 352:      * 
 353:      * @param c  the component (ignored).
 354:      * @return The border insets.
 355:      */
 356:     public Insets getBorderInsets(Component c, Insets newInsets)
 357:     {
 358:       if (newInsets == null)
 359:         newInsets = new Insets(3, 3, 2, 3);
 360:       else
 361:         {
 362:           newInsets.top = 3;
 363:           newInsets.left = 3;
 364:           newInsets.bottom = 2;
 365:           newInsets.right = 3;
 366:         }
 367:       return newInsets;  
 368:     }
 369:     
 370:     /**
 371:      * Paints the border for the specified component.
 372:      * 
 373:      * @param c  the component.
 374:      * @param g  the graphics device.
 375:      * @param x  the x-coordinate.
 376:      * @param y  the y-coordinate.
 377:      * @param w  the width.
 378:      * @param h  the height.
 379:      */
 380:     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
 381:         int h)
 382:     {
 383:       g.setColor(MetalLookAndFeel.getControlDarkShadow());      
 384:       g.drawRect(x, y, w - 1, h - 1); 
 385:     }
 386:     
 387:   }
 388: 
 389:   /**
 390:    * A simple 3D border.
 391:    */
 392:   public static class Flush3DBorder extends AbstractBorder
 393:     implements UIResource
 394:   {
 395:     private static final Insets borderInsets = new Insets(2, 2, 2, 2);
 396:     
 397:     /**
 398:      * Creates a new border instance.
 399:      */
 400:     public Flush3DBorder()
 401:     {
 402:       // Nothing to do here.
 403:     }
 404:     
 405:     /**
 406:      * Returns the border insets.
 407:      * 
 408:      * @param c  the component (ignored).
 409:      * 
 410:      * @return The border insets.
 411:      */
 412:     public Insets getBorderInsets(Component c)
 413:     {
 414:       return borderInsets;
 415:     }
 416:     
 417:     /**
 418:      * Returns the border insets.
 419:      * 
 420:      * @param c  the component (ignored).
 421:      * @param newInsets  an existing insets instance, that will be populated
 422:      *                   with the border insets and returned as the result
 423:      *                   (<code>null</code> not permitted).
 424:      *                   
 425:      * @return The <code>newInsets</code> reference.
 426:      */
 427:     public Insets getBorderInsets(Component c, Insets newInsets)
 428:     {
 429:       newInsets.top = borderInsets.top;
 430:       newInsets.left = borderInsets.left;
 431:       newInsets.bottom = borderInsets.bottom;
 432:       newInsets.right = borderInsets.right;
 433:       return newInsets;  
 434:     }
 435:     
 436:     /**
 437:      * Paints the border for the specified component.
 438:      * 
 439:      * @param c  the component (ignored).
 440:      * @param g  the graphics device.
 441:      * @param x  the x-coordinate.
 442:      * @param y  the y-coordinate.
 443:      * @param w  the width.
 444:      * @param h  the height.
 445:      */
 446:     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
 447:         int h)
 448:     {              
 449:       Color savedColor = g.getColor();
 450:       g.setColor(MetalLookAndFeel.getControlDarkShadow());
 451:       g.drawRect(x, y, w - 2, h - 2);
 452:       g.setColor(MetalLookAndFeel.getControlHighlight());
 453:       g.drawRect(x + 1, y + 1, w - 2, h - 2);
 454:       g.setColor(MetalLookAndFeel.getControl());
 455:       g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
 456:       g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
 457:       g.setColor(savedColor);
 458:     }
 459:     
 460:   }
 461:     
 462:   /**
 463:    * A border used for a {@link JInternalFrame} when it is being used as a 
 464:    * palette.
 465:    * 
 466:    * @since 1.3
 467:    */
 468:   public static class PaletteBorder extends AbstractBorder
 469:     implements UIResource
 470:   {
 471:     private static final Insets borderInsets = new Insets(1, 1, 1, 1);
 472: 
 473:     /**
 474:      * Creates a new <code>PaletteBorder</code>.
 475:      */
 476:     public PaletteBorder()
 477:     {
 478:       // Nothing to do here.
 479:     }
 480:     
 481:     /**
 482:      * Returns the border insets.
 483:      * 
 484:      * @param c  the component (ignored).
 485:      * 
 486:      * @return The border insets.
 487:      */
 488:     public Insets getBorderInsets(Component c)
 489:     {
 490:       return borderInsets;
 491:     }
 492: 
 493:     /**
 494:      * Returns the border insets.
 495:      * 
 496:      * @param c  the component (ignored).
 497:      * @param newInsets  an existing insets instance, that will be populated
 498:      *                   with the border insets and returned as the result
 499:      *                   (<code>null</code> not permitted).
 500:      *                   
 501:      * @return The <code>newInsets</code> reference.
 502:      */
 503:     public Insets getBorderInsets(Component c, Insets newInsets)
 504:     {        
 505:       newInsets.top = borderInsets.top;
 506:       newInsets.left = borderInsets.left;
 507:       newInsets.bottom = borderInsets.bottom;
 508:       newInsets.right = borderInsets.right;
 509:       return newInsets;  
 510:     }
 511:     
 512:     /**
 513:      * Paints the border for the specified component.
 514:      * 
 515:      * @param c  the component (ignored).
 516:      * @param g  the graphics device.
 517:      * @param x  the x-coordinate.
 518:      * @param y  the y-coordinate.
 519:      * @param w  the width.
 520:      * @param h  the height.
 521:      */
 522:     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
 523:             int h)
 524:     {
 525:       Color savedColor = g.getColor();
 526:       
 527:       // draw the outline
 528:       g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
 529:       g.drawRect(x, y, w - 1, h - 1);
 530:       
 531:       // put a dot in each corner
 532:       g.setColor(MetalLookAndFeel.getControl());
 533:       g.fillRect(x, y, 1, 1);
 534:       g.fillRect(x + w - 1, y, 1, 1);
 535:       g.fillRect(x + w - 1, y + h - 1, 1, 1);
 536:       g.fillRect(x, y + h - 1, 1, 1);      
 537:       g.setColor(savedColor);
 538:     }
 539: 
 540:   }
 541:     
 542:   /**
 543:    * A border used for the {@link JTextField} component.
 544:    */
 545:   public static class TextFieldBorder extends Flush3DBorder
 546:     implements UIResource
 547:   {
 548:     /**
 549:      * Creates a new border instance.
 550:      */
 551:     public TextFieldBorder()
 552:     {
 553:       // Nothing to do here.
 554:     }
 555:     
 556:     /**
 557:      * Paints the border for the specified component.
 558:      * 
 559:      * @param c  the component (ignored).
 560:      * @param g  the graphics device.
 561:      * @param x  the x-coordinate.
 562:      * @param y  the y-coordinate.
 563:      * @param w  the width.
 564:      * @param h  the height.
 565:      */
 566:     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
 567:         int h)
 568:     {
 569:       boolean enabledTextBorder;
 570:       if (c instanceof JTextComponent)
 571:     {
 572:       JTextComponent tc = (JTextComponent) c;
 573:       enabledTextBorder = tc.isEnabled() && tc.isEditable();
 574:     }
 575:       else
 576:     enabledTextBorder = false;
 577: 
 578:       if (enabledTextBorder)
 579:         super.paintBorder(c, g, x, y, w, h);
 580:       else
 581:         {
 582:           Color savedColor = g.getColor();
 583:           g.setColor(MetalLookAndFeel.getControlShadow());
 584:           g.drawRect(x, y, w - 1, h - 1);
 585:           g.setColor(savedColor);
 586:         }
 587:     }
 588:     
 589:   }
 590: 
 591:   /**
 592:    * A border used for the {@link JInternalFrame} component.
 593:    */
 594:   public static class InternalFrameBorder extends AbstractBorder
 595:     implements UIResource
 596:   {
 597:     private static final Insets borderInsets = new Insets(5, 5, 5, 5);
 598: 
 599:     /**
 600:      * Creates a new border instance.
 601:      */
 602:     public InternalFrameBorder()
 603:     {
 604:       // Nothing to do here.
 605:     }
 606:     
 607:     /**
 608:      * Returns the border insets.
 609:      * 
 610:      * @param c  the component (ignored).
 611:      * 
 612:      * @return The border insets.
 613:      */
 614:     public Insets getBorderInsets(Component c)
 615:     {
 616:       return borderInsets;
 617:     }
 618:     
 619:     /**
 620:      * Returns the border insets.
 621:      * 
 622:      * @param c  the component (ignored).
 623:      * @param newInsets  an existing insets instance, that will be populated
 624:      *                   with the border insets and returned as the result
 625:      *                   (<code>null</code> not permitted).
 626:      *                   
 627:      * @return The <code>newInsets</code> reference.
 628:      */
 629:     public Insets getBorderInsets(Component c, Insets newInsets)
 630:     {
 631:       newInsets.top = borderInsets.top;
 632:       newInsets.left = borderInsets.left;
 633:       newInsets.bottom = borderInsets.bottom;
 634:       newInsets.right = borderInsets.right;
 635:       return newInsets;  
 636:     }
 637:     
 638:     /**
 639:      * Paints the border for the specified component.
 640:      * 
 641:      * @param c  the component.
 642:      * @param g  the graphics device.
 643:      * @param x  the x-coordinate.
 644:      * @param y  the y-coordinate.
 645:      * @param w  the width.
 646:      * @param h  the height.
 647:      */
 648:     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
 649:         int h)
 650:     {
 651:         
 652:       JInternalFrame f = (JInternalFrame) c;
 653:       if (f.isSelected())
 654:         g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
 655:       else
 656:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 657:       
 658:       // fill the border background
 659:       g.fillRect(x, y, w, 5);
 660:       g.fillRect(x, y, 5, h);
 661:       g.fillRect(x + w - 5, y, 5, h);
 662:       g.fillRect(x, y + h - 5, w, 5);
 663:       
 664:       // draw a dot in each corner
 665:       g.setColor(MetalLookAndFeel.getControl());
 666:       g.fillRect(x, y, 1, 1);
 667:       g.fillRect(x + w - 1, y, 1, 1);
 668:       g.fillRect(x + w - 1, y + h - 1, 1, 1);
 669:       g.fillRect(x, y + h - 1, 1, 1);
 670:       
 671:       // draw the lines
 672:       g.setColor(MetalLookAndFeel.getBlack());
 673:       g.drawLine(x + 14, y + 2, x + w - 15, y + 2);
 674:       g.drawLine(x + 14, y + h - 3, x + w - 15, y + h - 3);
 675:       g.drawLine(x + 2, y + 14, x + 2, y + h - 15);
 676:       g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15);
 677:       
 678:       // draw the line highlights
 679:       if (f.isSelected())
 680:         g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
 681:       else 
 682:         g.setColor(MetalLookAndFeel.getControlShadow());
 683:       g.drawLine(x + 15, y + 3, x + w - 14, y + 3);
 684:       g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2);
 685:       g.drawLine(x + 3, y + 15, x + 3, y + h - 14);
 686:       g.drawLine(x + w - 2, y + 15, x + w - 2, y + h - 14);
 687:     }
 688:     
 689:   }
 690: 
 691:   /**
 692:    * A border used for {@link JInternalFrame} components that are
 693:    * presented as dialogs (by the {@link JOptionPane} class).
 694:    */
 695:   public static class OptionDialogBorder extends AbstractBorder
 696:     implements UIResource
 697:   {
 698:       
 699:     /**
 700:      * Creates a new border instance.
 701:      */
 702:     public OptionDialogBorder()
 703:     {
 704:       // Nothing to do here.
 705:     }
 706:     
 707:     /**
 708:      * Returns the border insets.
 709:      * 
 710:      * @param c  the component (ignored).
 711:      * 
 712:      * @return The border insets.
 713:      */
 714:     public Insets getBorderInsets(Component c)
 715:     {
 716:       return getBorderInsets(c, null);
 717:     }
 718:     
 719:     /**
 720:      * Returns the border insets.
 721:      * 
 722:      * @param c  the component (ignored).
 723:      * @return The border insets.
 724:      */
 725:     public Insets getBorderInsets(Component c, Insets newInsets)
 726:     {
 727:       if (newInsets == null)
 728:         newInsets = new Insets(3, 3, 3, 3);
 729:       else
 730:         {
 731:           newInsets.top = 3;
 732:           newInsets.left = 3;
 733:           newInsets.bottom = 3;
 734:           newInsets.right = 3;
 735:         }
 736:       return newInsets;  
 737:     }
 738:         
 739:     /**
 740:      * Paints the border for the specified component.
 741:      * 
 742:      * @param c  the component.
 743:      * @param g  the graphics device.
 744:      * @param x  the x-coordinate.
 745:      * @param y  the y-coordinate.
 746:      * @param w  the width.
 747:      * @param h  the height.
 748:      */
 749:     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
 750:         int h)
 751:     {
 752:         
 753:       JInternalFrame f = (JInternalFrame) c;
 754:       g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
 755:       if (f.getContentPane() instanceof JOptionPane)
 756:         {
 757:           JOptionPane pane = (JOptionPane) f.getContentPane();
 758:           int type = pane.getMessageType();
 759:           if (type == JOptionPane.QUESTION_MESSAGE)
 760:             {
 761:               Color bc = UIManager.getColor(
 762:                   "OptionPane.questionDialog.border.background");
 763:               if (bc != null)
 764:                 g.setColor(bc);
 765:             }
 766:           if (type == JOptionPane.WARNING_MESSAGE)
 767:             {
 768:               Color bc = UIManager.getColor(
 769:                   "OptionPane.warningDialog.border.background");
 770:               if (bc != null)
 771:                 g.setColor(bc);              
 772:             }
 773:           else if (type == JOptionPane.ERROR_MESSAGE)
 774:             {
 775:               Color bc = UIManager.getColor(
 776:                   "OptionPane.errorDialog.border.background");
 777:               if (bc != null)
 778:                 g.setColor(bc);              
 779:             }
 780:         }
 781:       
 782:       // fill the border background
 783:       g.fillRect(x, y, w, 3);
 784:       g.fillRect(x, y, 3, h);
 785:       g.fillRect(x + w - 3, y, 3, h);
 786:       g.fillRect(x, y + h - 3, w, 3);
 787:       
 788:       // draw a dot in each corner
 789:       g.setColor(MetalLookAndFeel.getControl());
 790:       g.fillRect(x, y, 1, 1);
 791:       g.fillRect(x + w - 1, y, 1, 1);
 792:       g.fillRect(x + w - 1, y + h - 1, 1, 1);
 793:       g.fillRect(x, y + h - 1, 1, 1);
 794:       
 795:     }
 796:     
 797:   }
 798: 
 799:   /**
 800:    * A border used for {@link JMenu} and {@link JMenuItem} components.
 801:    */
 802:   public static class MenuItemBorder extends AbstractBorder
 803:     implements UIResource
 804:   {
 805:     /** The border insets. */
 806:     protected static Insets borderInsets = new Insets(2, 2, 2, 2);
 807:     
 808:     /**
 809:      * Creates a new border instance.
 810:      */
 811:     public MenuItemBorder()
 812:     {
 813:       // Nothing to do here.
 814:     }
 815:     
 816:     /**
 817:      * Paints the border for the component.  A border is painted only if the
 818:      * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
 819:      * 
 820:      * @param c  the component.
 821:      * @param g  the graphics device.
 822:      * @param x  the x-coordinate of the border area.
 823:      * @param y  the y-coordinate of the border area.
 824:      * @param w  the width of the border area.
 825:      * @param h  the height of the border area.
 826:      */
 827:     public void paintBorder(Component c, Graphics g, int x, int y, int w,
 828:         int h)
 829:     {
 830:       Color dark = MetalLookAndFeel.getPrimaryControlDarkShadow();
 831:       Color light = MetalLookAndFeel.getPrimaryControlHighlight();
 832:       if (c instanceof JMenu) {
 833:         JMenu menu = (JMenu) c;
 834:         if (menu.isSelected())
 835:         {
 836:           g.setColor(dark);
 837:           g.drawLine(x, y, x, y + h);
 838:           g.drawLine(x, y, x + w, y);
 839:           g.drawLine(x + w - 2, y + 1, x + w - 2, y + h);
 840:           g.setColor(light);
 841:           g.drawLine(x + w - 1, y + 1, x + w - 1, y + h);
 842:         }
 843:       }
 844:       else if (c instanceof JMenuItem)
 845:       {
 846:         JMenuItem item = (JMenuItem) c;
 847:         if (item.isArmed()) 
 848:           {
 849:             g.setColor(dark);
 850:             g.drawLine(x, y, x + w, y);
 851:             g.setColor(light);
 852:             g.drawLine(x, y + h - 1, x + w, y + h - 1);
 853:           }
 854:         else
 855:           {
 856:             // Normally we draw a light line on the left.
 857:             g.setColor(light);
 858:             g.drawLine(x, y, x, y + h);
 859:           }
 860:       }
 861:     }
 862:     
 863:     /**
 864:      * Returns the border insets.
 865:      * 
 866:      * @param c  the component (ignored).
 867:      * 
 868:      * @return The border insets.
 869:      */
 870:     public Insets getBorderInsets(Component c)
 871:     {
 872:       return borderInsets;
 873:     }
 874:     
 875:     /**
 876:      * Populates <code>insets</code> with the border insets, then returns it.
 877:      * 
 878:      * @param c  the component (ignored).
 879:      * @param insets  the object to populate with the border insets.
 880:      * 
 881:      * @return The border insets.
 882:      * 
 883:      * @throws NullPointerException if <code>insets</code> is <code>null</code>.
 884:      */
 885:     public Insets getBorderInsets(Component c, Insets insets)
 886:     {
 887:       insets.left = borderInsets.left;
 888:       insets.top = borderInsets.top;
 889:       insets.bottom = borderInsets.bottom;
 890:       insets.right = borderInsets.right;
 891:       return insets;
 892:     }
 893:   }
 894: 
 895:   /**
 896:    * A border used for {@link JMenuBar} components.
 897:    */
 898:   public static class MenuBarBorder
 899:       extends AbstractBorder
 900:       implements UIResource
 901:   {
 902:     /** The border insets. */
 903:     protected static Insets borderInsets = new Insets(1, 0, 1, 0);
 904:     
 905:     // TODO: find where this color really comes from
 906:     private static Color borderColor = new Color(153, 153, 153);
 907:     
 908:     /**
 909:      * Creates a new border instance.
 910:      */
 911:     public MenuBarBorder()
 912:     {
 913:       // Nothing to do here.
 914:     }
 915:     
 916:     /**
 917:      * Paints the border for the component.  A border is painted only if the
 918:      * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
 919:      * 
 920:      * @param c  the component.
 921:      * @param g  the graphics device.
 922:      * @param x  the x-coordinate of the border area.
 923:      * @param y  the y-coordinate of the border area.
 924:      * @param w  the width of the border area.
 925:      * @param h  the height of the border area.
 926:      */
 927:     public void paintBorder(Component c, Graphics g, int x, int y, int w,
 928:         int h)
 929:     {
 930:       g.setColor(borderColor);
 931:       g.drawLine(x, y + h - 1, x + w, y + h - 1);
 932:     }
 933:     
 934:     /**
 935:      * Returns the border insets.
 936:      * 
 937:      * @param c  the component (ignored).
 938:      * 
 939:      * @return The border insets.
 940:      */
 941:     public Insets getBorderInsets(Component c)
 942:     {
 943:       return borderInsets;
 944:     }
 945:     
 946:     /**
 947:      * Populates <code>insets</code> with the border insets, then returns it.
 948:      * 
 949:      * @param c  the component (ignored).
 950:      * @param insets  the object to populate with the border insets.
 951:      * 
 952:      * @return The border insets.
 953:      * 
 954:      * @throws NullPointerException if <code>insets</code> is <code>null</code>.
 955:      */
 956:     public Insets getBorderInsets(Component c, Insets insets)
 957:     {
 958:       insets.left = borderInsets.left;
 959:       insets.top = borderInsets.top;
 960:       insets.bottom = borderInsets.bottom;
 961:       insets.right = borderInsets.right;
 962:       return insets;
 963:     }
 964:   }
 965: 
 966:   /**
 967:    * A border for {@link JScrollPane} components.
 968:    */
 969:   public static class ScrollPaneBorder
 970:     extends AbstractBorder
 971:     implements UIResource
 972:   {
 973:     /** The border insets. */
 974:     private static Insets insets = new Insets(1, 1, 2, 2);
 975:     
 976:     /**
 977:      * Constructs a new ScrollPaneBorder.
 978:      */
 979:     public ScrollPaneBorder()
 980:     {
 981:       // Nothing to do here.
 982:     }
 983:     
 984:     /**
 985:      * Returns the insets of the border for the Component <code>c</code>.
 986:      *
 987:      * @param c the Component for which we return the border insets
 988:      */
 989:     public Insets getBorderInsets(Component c)
 990:     {
 991:       return insets;
 992:     }
 993: 
 994:     /**
 995:      * Paints the border.
 996:      *
 997:      * @param c the Component for which the border is painted
 998:      * @param g the Graphics context
 999:      * @param x the X coordinate of the upper left corner of the border
1000:      * @param y the Y coordinate of the upper left corner of the border
1001:      * @param w the width of the border
1002:      * @param h the height of the border
1003:      */
1004:     public void paintBorder(Component c, Graphics g, int x, int y,
1005:                             int w, int h)
1006:     {
1007:       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
1008:       Color shadow = MetalLookAndFeel.getControlShadow();
1009:       Color light = MetalLookAndFeel.getWhite();
1010:       Color middle = MetalLookAndFeel.getControl();
1011: 
1012:       // paint top border line
1013:       g.setColor(darkShadow);
1014:       g.drawLine(x, y, x + w - 2, y);
1015: 
1016:       // paint left border line
1017:       g.drawLine(x, y, x, y + h - 2);
1018:  
1019:       // paint right inner border line
1020:       g.drawLine(x + w - 2, y, x + w - 2, y + h + 1);
1021: 
1022:       // paint bottom inner border line
1023:       g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2);
1024: 
1025:       // draw right outer border line
1026:       g.setColor(light);
1027:       g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
1028: 
1029:       // draw bottom outer border line
1030:       g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
1031: 
1032:       // paint the lighter points
1033:       g.setColor(middle);
1034:       g.drawLine(x + w - 1, y, x + w - 1, y);
1035:       g.drawLine(x + w - 2, y + 2, x + w - 2, y + 2);
1036:       g.drawLine(x, y + h - 1, x, y + h - 1);
1037:       g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1038: 
1039:     }
1040:     
1041:   }
1042:   
1043:   /**
1044:    * A button border that is only visible when the mouse pointer is within 
1045:    * the button's bounds.
1046:    */
1047:   public static class RolloverButtonBorder
1048:     extends MetalBorders.ButtonBorder
1049:   {
1050:     /**
1051:      * Creates a new border instance.
1052:      */
1053:     public RolloverButtonBorder()
1054:     {
1055:       // Nothing to do here.
1056:     }
1057:     
1058:     /**
1059:      * Paints the border.
1060:      * 
1061:      * @param c  the component.
1062:      * @param g  the graphics device.
1063:      * @param x  the x-coordinate.
1064:      * @param y  the y-coordinate.
1065:      * @param w  the width.
1066:      * @param h  the height.
1067:      */
1068:     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
1069:             int h)
1070:     {
1071:       // TODO: What should be done here? Obviously the ButtonBorder already
1072:       // handles the rollover state in Sun's impl. Maybe this is only there
1073:       // for backwards compatibility.
1074:       super.paintBorder(c, g, x, y, w, h);
1075:     }
1076:   }
1077:   
1078:   /**
1079:    * This border is used in Toolbar buttons as inner border.
1080:    */
1081:   static class RolloverMarginBorder extends AbstractBorder
1082:   {
1083:     /** The borders insets. */
1084:     protected static Insets borderInsets = new Insets(3, 3, 3, 3);
1085: 
1086:     /**
1087:      * Creates a new instance of RolloverBorder.
1088:      */
1089:     public RolloverMarginBorder()
1090:     {
1091:       // Nothing to do here.
1092:     }
1093:     
1094:     /**
1095:      * Returns the insets of the RolloverBorder.
1096:      *
1097:      * @param c the component for which the border is used
1098:      *
1099:      * @return the insets of the RolloverBorder
1100:      */
1101:     public Insets getBorderInsets(Component c)
1102:     {
1103:       return getBorderInsets(c, null);
1104:     }
1105: 
1106:     /**
1107:      * Returns the insets of the RolloverMarginBorder in the specified
1108:      * Insets object.
1109:      *
1110:      * @param c the component for which the border is used
1111:      * @param newInsets the insets object where to put the values
1112:      *
1113:      * @return the insets of the RolloverMarginBorder
1114:      */
1115:     public Insets getBorderInsets(Component c, Insets newInsets)
1116:     {
1117:       if (newInsets == null)
1118:         newInsets = new Insets(0, 0, 0, 0);
1119: 
1120:       AbstractButton b = (AbstractButton) c;
1121:       Insets margin = b.getMargin();
1122:       newInsets.bottom = borderInsets.bottom;
1123:       newInsets.left = borderInsets.left;
1124:       newInsets.right = borderInsets.right;
1125:       newInsets.top = borderInsets.top;
1126:       return newInsets;
1127:     }
1128:   }
1129: 
1130:   /**
1131:    * A border implementation for popup menus.
1132:    */
1133:   public static class PopupMenuBorder
1134:     extends AbstractBorder
1135:     implements UIResource
1136:   {
1137: 
1138:     /** The border's insets. */
1139:     protected static Insets borderInsets = new Insets(3, 1, 2, 1);
1140: 
1141:     /**
1142:      * Constructs a new PopupMenuBorder.
1143:      */
1144:     public PopupMenuBorder()
1145:     {
1146:       // Nothing to do here.
1147:     }
1148:     
1149:     /**
1150:      * Returns the insets of the border, creating a new Insets instance
1151:      * with each call.
1152:      *
1153:      * @param c the component for which we return the border insets
1154:      *          (not used here)
1155:      */
1156:     public Insets getBorderInsets(Component c)
1157:     {
1158:       return getBorderInsets(c, null);
1159:     }
1160:     
1161:     /**
1162:      * Returns the insets of the border, using the supplied Insets instance.
1163:      *
1164:      * @param c the component for which we return the border insets
1165:      *          (not used here)
1166:      * @param i the Insets instance to fill with the Insets values
1167:      */
1168:     public Insets getBorderInsets(Component c, Insets i)
1169:     {
1170:       Insets insets;
1171:       if (i == null)
1172:         insets = new Insets(borderInsets.top, borderInsets.left,
1173:                             borderInsets.bottom, borderInsets.right);
1174:       else
1175:         {
1176:           insets = i;
1177:           insets.top = borderInsets.top;
1178:           insets.left = borderInsets.left;
1179:           insets.bottom = borderInsets.bottom;
1180:           insets.right = borderInsets.right;
1181:         }
1182:       
1183:       return insets;
1184:     }
1185: 
1186:     /**
1187:      * Paints the border for component <code>c</code> using the
1188:      * Graphics context <code>g</code> with the dimension
1189:      * <code>x, y, w, h</code>.
1190:      *
1191:      * @param c the component for which we paint the border
1192:      * @param g the Graphics context to use
1193:      * @param x the X coordinate of the upper left corner of c
1194:      * @param y the Y coordinate of the upper left corner of c
1195:      * @param w the width of c
1196:      * @param h the height of c
1197:      */
1198:     public void paintBorder(Component c, Graphics g, int x, int y, int w,
1199:                             int h)
1200:     {
1201:       Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
1202:       Color light = MetalLookAndFeel.getPrimaryControlHighlight();
1203: 
1204:       // draw dark outer border
1205:       g.setColor(darkShadow);
1206:       g.drawRect(x, y, w - 1, h - 1);
1207:       
1208:       // draw highlighted inner border (only top and left)
1209:       g.setColor(light);
1210:       g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
1211:     }
1212:     
1213:   }
1214: 
1215:   /**
1216:    * A border used for the {@link JToggleButton} component.
1217:    * 
1218:    * @since 1.3
1219:    */
1220:   public static class ToggleButtonBorder
1221:     extends ButtonBorder 
1222:   {
1223:     /**
1224:      * Creates a new border instance.
1225:      */
1226:     public ToggleButtonBorder()
1227:     {
1228:       // Nothing to do here.
1229:     }
1230:     
1231:     /**
1232:      * Paints the toggle button border.
1233:      *
1234:      * @param c the component for which we paint the border
1235:      * @param g the Graphics context to use
1236:      * @param x the X coordinate of the upper left corner of c
1237:      * @param y the Y coordinate of the upper left corner of c
1238:      * @param w the width of c
1239:      * @param h the height of c
1240:      */
1241:     public void paintBorder(Component c, Graphics g, int x, int y, int w,
1242:                             int h)
1243:     {
1244:       ButtonModel bmodel = null;
1245:       
1246:       if (c instanceof AbstractButton)
1247:         bmodel = ((AbstractButton) c).getModel();
1248: 
1249:       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
1250:       Color shadow = MetalLookAndFeel.getControlShadow();
1251:       Color light = MetalLookAndFeel.getWhite();
1252:       Color middle = MetalLookAndFeel.getControl();
1253: 
1254:       if (c.isEnabled())
1255:         {
1256:           // draw dark border
1257:           g.setColor(darkShadow);
1258:           g.drawRect(x, y, w - 2, h - 2);
1259: 
1260:           if (!bmodel.isArmed())
1261:             {
1262:               // draw light border
1263:               g.setColor(light);
1264:               g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1265:               g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
1266:               if (bmodel.isSelected())
1267:                 g.setColor(middle);
1268:               g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
1269:               g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
1270: 
1271:               // draw crossing pixels of both borders
1272:               g.setColor(shadow);
1273:               g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1274:               g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
1275:             }
1276:           else
1277:             {
1278:               // draw light border
1279:               g.setColor(light);
1280:               g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
1281:               g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1282: 
1283:               // draw shadow border
1284:               g.setColor(shadow);
1285:               g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
1286:               g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
1287:  
1288:               // draw crossing pixels of both borders
1289:               g.setColor(shadow);
1290:               g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1291:               g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
1292:               
1293:             }
1294:           // draw corners
1295:           g.setColor(middle);
1296:           g.drawLine(x, y + h - 1, x, y + h - 1);
1297:           g.drawLine(x + w - 1, y, x + w - 1, y);
1298:         }
1299:       else 
1300:         {
1301:           // draw disabled border
1302:           g.setColor(MetalLookAndFeel.getControlDisabled());
1303:           g.drawRect(x, y, w - 2, h - 2);          
1304:         }
1305:     }
1306:   }
1307: 
1308:   /**
1309:    * A border used for the {@link JToolBar} component.
1310:    */
1311:   public static class ToolBarBorder extends AbstractBorder
1312:     implements UIResource, SwingConstants
1313:   {
1314:     /**
1315:      * Creates a new border instance.
1316:      */
1317:     public ToolBarBorder()
1318:     {
1319:       // Nothing to do here.
1320:     }
1321:     
1322:     /**
1323:      * Returns the border insets.
1324:      * 
1325:      * @param c  the component (ignored).
1326:      * 
1327:      * @return The border insets.
1328:      */
1329:     public Insets getBorderInsets(Component c)
1330:     {
1331:       return getBorderInsets(c, null);
1332:     }
1333:     
1334:     /**
1335:      * Returns the border insets.
1336:      * 
1337:      * @param c  the component (ignored).
1338:      * @return The border insets.
1339:      */
1340:     public Insets getBorderInsets(Component c, Insets newInsets)
1341:     {
1342:       JToolBar tb = (JToolBar) c;
1343:       if (tb.getOrientation() == JToolBar.HORIZONTAL)
1344:         {   
1345:           if (newInsets == null)
1346:             newInsets = new Insets(2, 16, 2, 2);
1347:           else
1348:             {
1349:               newInsets.top = 2;
1350:               newInsets.left = 16;
1351:               newInsets.bottom = 2;
1352:               newInsets.right = 2;
1353:             }
1354:           return newInsets;  
1355:         }
1356:       else // assume JToolBar.VERTICAL
1357:         { 
1358:           if (newInsets == null)
1359:             newInsets = new Insets(16, 2, 2, 2);
1360:           else
1361:             {
1362:               newInsets.top = 16;
1363:               newInsets.left = 2;
1364:               newInsets.bottom = 2;
1365:               newInsets.right = 2;
1366:             }
1367:           return newInsets;  
1368:         }
1369: 
1370:     }
1371:     
1372:     /**
1373:      * Paints the border for the specified component.
1374:      * 
1375:      * @param c  the component.
1376:      * @param g  the graphics device.
1377:      * @param x  the x-coordinate.
1378:      * @param y  the y-coordinate.
1379:      * @param w  the width.
1380:      * @param h  the height.
1381:      */
1382:     public void paintBorder(Component c, Graphics g, int x, int y, int w, 
1383:         int h)
1384:     {
1385:         
1386:       JToolBar tb = (JToolBar) c;
1387:       if (tb.getOrientation() == JToolBar.HORIZONTAL)
1388:         {
1389:            MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + 11, y + h - 5, 
1390:                   MetalLookAndFeel.getControlHighlight(), 
1391:                   MetalLookAndFeel.getControlDarkShadow());
1392:         }
1393:       else
1394:         { 
1395:           MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + w - 5, y + 11, 
1396:                   MetalLookAndFeel.getControlHighlight(), 
1397:                   MetalLookAndFeel.getControlDarkShadow());
1398:         }
1399:     }
1400:     
1401:   }
1402:   
1403:   /**
1404:    * A border for table header cells.
1405:    *
1406:    * @since 1.3
1407:    */
1408:   public static class TableHeaderBorder extends AbstractBorder
1409:   {
1410:     /**
1411:      * The insets of this border.
1412:      */
1413:     // TODO: According to tests that I have done, this is really the border
1414:     // that should be returned by getBorderInsets(). However, the name
1415:     // is very distracting. Is there any deeper meaning in it?
1416:     protected Insets editorBorderInsets;
1417: 
1418:     /**
1419:      * Creates a new instance of <code>TableHeaderBorder</code>.
1420:      */
1421:     public TableHeaderBorder()
1422:     {
1423:       editorBorderInsets = new Insets(1, 1, 1, 1);
1424:     }
1425: 
1426:     /**
1427:      * Return the insets of this border.
1428:      *
1429:      * @return the insets of this border
1430:      */
1431:     public Insets getBorderInsets(Component c)
1432:     {
1433:       return editorBorderInsets;
1434:     }
1435: 
1436:     /**
1437:      * Paints the border.
1438:      *
1439:      * @param c the component for which to paint the border
1440:      * @param g the graphics context to use
1441:      * @param x the x cooridinate of the border rectangle
1442:      * @param y the y cooridinate of the border rectangle
1443:      * @param w the width of the border rectangle
1444:      * @param h the height of the border rectangle
1445:      */
1446:     public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
1447:     {
1448:       Color dark = MetalLookAndFeel.getControlDarkShadow();
1449:       Color light = MetalLookAndFeel.getWhite();
1450:       Color old = g.getColor();
1451:       g.setColor(light);
1452:       g.drawLine(x, y, x + w - 2, y);
1453:       g.drawLine(x, y, x, y + h - 2);
1454:       g.setColor(dark);
1455:       g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
1456:       g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1457:       g.setColor(old);
1458:     }
1459:   }
1460: 
1461:   /**
1462:    * Returns a border for Swing buttons in the Metal Look &amp; Feel.
1463:    *
1464:    * @return a border for Swing buttons in the Metal Look &amp; Feel
1465:    */
1466:   public static Border getButtonBorder()
1467:   {
1468:     if (buttonBorder == null)
1469:       {
1470:         Border outer = new ButtonBorder();
1471:         Border inner = getMarginBorder();
1472:         buttonBorder = new BorderUIResource.CompoundBorderUIResource
1473:             (outer, inner);
1474:       }
1475:     return buttonBorder;
1476:   }
1477:   
1478:   /**
1479:    * Returns a border for use with {@link JToggleButton} components.
1480:    *
1481:    * @return A border.
1482:    * 
1483:    * @since 1.3
1484:    */
1485:   public static Border getToggleButtonBorder()
1486:   {
1487:     if (toggleButtonBorder == null)
1488:       {
1489:         Border outer = new ToggleButtonBorder();
1490:         Border inner = getMarginBorder();
1491:         toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource
1492:             (outer, inner);
1493:       }
1494:     return toggleButtonBorder;
1495:   }
1496: 
1497:   /**
1498:    * Returns a border instance that is used with a {@link JInternalFrame} when
1499:    * it is in the iconified state.
1500:    * 
1501:    * @return A border.
1502:    * 
1503:    * @since 1.3
1504:    */
1505:   public static Border getDesktopIconBorder()
1506:   {
1507:     if (desktopIconBorder == null)
1508:       desktopIconBorder = new DesktopIconBorder();
1509:     return desktopIconBorder;      
1510:   }
1511: 
1512:   /**
1513:    * Returns a border for use by the {@link JTextField} component.
1514:    * 
1515:    * @return A border.
1516:    * 
1517:    * @since 1.3
1518:    */
1519:   public static Border getTextFieldBorder()
1520:   {
1521:     if (textFieldBorder == null)
1522:       {
1523:         Border inner = getMarginBorder();
1524:         Border outer = new TextFieldBorder();
1525:         textFieldBorder =
1526:           new BorderUIResource.CompoundBorderUIResource(outer, inner);
1527:       }
1528:     return textFieldBorder;
1529:   }
1530: 
1531:   /**
1532:    * Returns the border that is used for text components (except text fields,
1533:    * which use {@link #getTextFieldBorder}.
1534:    *
1535:    * @return the border that is used for text components
1536:    *
1537:    * @since 1.3
1538:    */
1539:   public static Border getTextBorder()
1540:   {
1541:     if (textBorder == null)
1542:       {
1543:         Border inner = getMarginBorder();
1544:         Border outer = new Flush3DBorder();
1545:         textBorder =
1546:           new BorderUIResource.CompoundBorderUIResource(outer, inner);
1547:       }
1548:     return textBorder;
1549:   }
1550: 
1551:   /**
1552:    * Returns a border for Toolbar buttons in the Metal Look &amp; Feel.
1553:    *
1554:    * @return a border for Toolbar buttons in the Metal Look &amp; Feel
1555:    */
1556:   static Border getToolbarButtonBorder()
1557:   {
1558:     if (toolbarButtonBorder == null)
1559:       {
1560:         Border outer = new ButtonBorder();
1561:         Border inner = new RolloverMarginBorder();
1562:         toolbarButtonBorder = new CompoundBorder(outer, inner);
1563:       }
1564:     return toolbarButtonBorder;
1565:   }
1566: 
1567:   /**
1568:    * Returns a shared instance of {@link BasicBorders.MarginBorder}.
1569:    *
1570:    * @return a shared instance of {@link BasicBorders.MarginBorder}
1571:    */
1572:   static Border getMarginBorder()
1573:   {
1574:     if (marginBorder == null)
1575:       marginBorder = new BasicBorders.MarginBorder();
1576:     return marginBorder;
1577:   }
1578: 
1579:   /**
1580:    * Returns a shared instance of a compound border for rollover buttons.
1581:    * 
1582:    * @return A shared border instance.
1583:    */
1584:   static Border getRolloverBorder()
1585:   {
1586:     if (rolloverBorder == null)
1587:       {
1588:         Border outer = new MetalBorders.RolloverButtonBorder();
1589:         Border inner = MetalBorders.getMarginBorder();
1590:         rolloverBorder = new BorderUIResource.CompoundBorderUIResource(outer, 
1591:             inner);
1592:       }
1593:     return rolloverBorder;
1594:   }
1595: 
1596: }