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:    * <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: }