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)