1 /*
   2  * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing.plaf.metal;
  27 
  28 import javax.swing.*;
  29 import javax.swing.border.*;
  30 import javax.swing.plaf.*;
  31 import javax.swing.plaf.basic.BasicBorders;
  32 import javax.swing.text.JTextComponent;
  33 
  34 import java.awt.Component;
  35 import java.awt.Insets;
  36 import java.awt.Color;
  37 import java.awt.Dialog;
  38 import java.awt.Frame;
  39 import java.awt.Graphics;
  40 import java.awt.Window;
  41 
  42 import sun.swing.StringUIClientPropertyKey;
  43 
  44 
  45 /**
  46  * Factory object that can vend Borders appropriate for the metal L & F.
  47  * @author Steve Wilson
  48  */
  49 
  50 public class MetalBorders {
  51 
  52     /**
  53      * Client property indicating the button shouldn't provide a rollover
  54      * indicator. Only used with the Ocean theme.
  55      */
  56     static Object NO_BUTTON_ROLLOVER =
  57         new StringUIClientPropertyKey("NoButtonRollover");
  58 
  59 
  60     public static class Flush3DBorder extends AbstractBorder implements UIResource{
  61         public void paintBorder(Component c, Graphics g, int x, int y,
  62                           int w, int h) {
  63             if (c.isEnabled()) {
  64                 MetalUtils.drawFlush3DBorder(g, x, y, w, h);
  65             } else {
  66                 MetalUtils.drawDisabledBorder(g, x, y, w, h);
  67             }
  68         }
  69 
  70         public Insets getBorderInsets(Component c, Insets newInsets) {
  71             newInsets.set(2, 2, 2, 2);
  72             return newInsets;
  73         }
  74     }
  75 
  76     public static class ButtonBorder extends AbstractBorder implements UIResource {
  77 
  78         protected static Insets borderInsets = new Insets( 3, 3, 3, 3 );
  79 
  80         public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
  81             if (!(c instanceof AbstractButton)) {
  82                 return;
  83             }
  84             if (MetalLookAndFeel.usingOcean()) {
  85                 paintOceanBorder(c, g, x, y, w, h);
  86                 return;
  87             }
  88             AbstractButton button = (AbstractButton)c;
  89             ButtonModel model = button.getModel();
  90 
  91             if ( model.isEnabled() ) {
  92                 boolean isPressed = model.isPressed() && model.isArmed();
  93                 boolean isDefault = (button instanceof JButton && ((JButton)button).isDefaultButton());
  94 
  95                 if (isPressed && isDefault) {
  96                     MetalUtils.drawDefaultButtonPressedBorder(g, x, y, w, h);
  97                 } else if (isPressed) {
  98                     MetalUtils.drawPressed3DBorder( g, x, y, w, h );
  99                 } else if (isDefault) {
 100                     MetalUtils.drawDefaultButtonBorder( g, x, y, w, h, false);
 101                 } else {
 102                     MetalUtils.drawButtonBorder( g, x, y, w, h, false);
 103                 }
 104             } else { // disabled state
 105                 MetalUtils.drawDisabledBorder( g, x, y, w-1, h-1 );
 106             }
 107         }
 108 
 109         private void paintOceanBorder(Component c, Graphics g, int x, int y,
 110                                       int w, int h) {
 111             AbstractButton button = (AbstractButton)c;
 112             ButtonModel model = ((AbstractButton)c).getModel();
 113 
 114             g.translate(x, y);
 115             if (MetalUtils.isToolBarButton(button)) {
 116                 if (model.isEnabled()) {
 117                     if (model.isPressed()) {
 118                         g.setColor(MetalLookAndFeel.getWhite());
 119                         g.fillRect(1, h - 1, w - 1, 1);
 120                         g.fillRect(w - 1, 1, 1, h - 1);
 121                         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 122                         g.drawRect(0, 0, w - 2, h - 2);
 123                         g.fillRect(1, 1, w - 3, 1);
 124                     }
 125                     else if (model.isSelected() || model.isRollover()) {
 126                         g.setColor(MetalLookAndFeel.getWhite());
 127                         g.fillRect(1, h - 1, w - 1, 1);
 128                         g.fillRect(w - 1, 1, 1, h - 1);
 129                         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 130                         g.drawRect(0, 0, w - 2, h - 2);
 131                     }
 132                     else {
 133                         g.setColor(MetalLookAndFeel.getWhite());
 134                         g.drawRect(1, 1, w - 2, h - 2);
 135                         g.setColor(UIManager.getColor(
 136                                 "Button.toolBarBorderBackground"));
 137                         g.drawRect(0, 0, w - 2, h - 2);
 138                     }
 139                 }
 140                 else {
 141                    g.setColor(UIManager.getColor(
 142                            "Button.disabledToolBarBorderBackground"));
 143                    g.drawRect(0, 0, w - 2, h - 2);
 144                 }
 145             }
 146             else if (model.isEnabled()) {
 147                 boolean pressed = model.isPressed();
 148                 boolean armed = model.isArmed();
 149 
 150                 if ((c instanceof JButton) && ((JButton)c).isDefaultButton()) {
 151                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
 152                     g.drawRect(0, 0, w - 1, h - 1);
 153                     g.drawRect(1, 1, w - 3, h - 3);
 154                 }
 155                 else if (pressed) {
 156                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
 157                     g.fillRect(0, 0, w, 2);
 158                     g.fillRect(0, 2, 2, h - 2);
 159                     g.fillRect(w - 1, 1, 1, h - 1);
 160                     g.fillRect(1, h - 1, w - 2, 1);
 161                 }
 162                 else if (model.isRollover() && button.getClientProperty(
 163                                NO_BUTTON_ROLLOVER) == null) {
 164                     g.setColor(MetalLookAndFeel.getPrimaryControl());
 165                     g.drawRect(0, 0, w - 1, h - 1);
 166                     g.drawRect(2, 2, w - 5, h - 5);
 167                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
 168                     g.drawRect(1, 1, w - 3, h - 3);
 169                 }
 170                 else {
 171                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
 172                     g.drawRect(0, 0, w - 1, h - 1);
 173                 }
 174             }
 175             else {
 176                 g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
 177                 g.drawRect(0, 0, w - 1, h - 1);
 178                 if ((c instanceof JButton) && ((JButton)c).isDefaultButton()) {
 179                     g.drawRect(1, 1, w - 3, h - 3);
 180                 }
 181             }
 182         }
 183 
 184         public Insets getBorderInsets(Component c, Insets newInsets) {
 185             newInsets.set(3, 3, 3, 3);
 186             return newInsets;
 187         }
 188     }
 189 
 190     public static class InternalFrameBorder extends AbstractBorder implements UIResource {
 191         private static final int corner = 14;
 192 
 193         public void paintBorder(Component c, Graphics g, int x, int y,
 194                           int w, int h) {
 195 
 196             Color background;
 197             Color highlight;
 198             Color shadow;
 199 
 200             if (c instanceof JInternalFrame && ((JInternalFrame)c).isSelected()) {
 201                 background = MetalLookAndFeel.getPrimaryControlDarkShadow();
 202                 highlight = MetalLookAndFeel.getPrimaryControlShadow();
 203                 shadow = MetalLookAndFeel.getPrimaryControlInfo();
 204             } else {
 205                 background = MetalLookAndFeel.getControlDarkShadow();
 206                 highlight = MetalLookAndFeel.getControlShadow();
 207                 shadow = MetalLookAndFeel.getControlInfo();
 208             }
 209 
 210               g.setColor(background);
 211               // Draw outermost lines
 212               g.drawLine( 1, 0, w-2, 0);
 213               g.drawLine( 0, 1, 0, h-2);
 214               g.drawLine( w-1, 1, w-1, h-2);
 215               g.drawLine( 1, h-1, w-2, h-1);
 216 
 217               // Draw the bulk of the border
 218               for (int i = 1; i < 5; i++) {
 219                   g.drawRect(x+i,y+i,w-(i*2)-1, h-(i*2)-1);
 220               }
 221 
 222               if (c instanceof JInternalFrame &&
 223                                ((JInternalFrame)c).isResizable()) {
 224                   g.setColor(highlight);
 225                   // Draw the Long highlight lines
 226                   g.drawLine( corner+1, 3, w-corner, 3);
 227                   g.drawLine( 3, corner+1, 3, h-corner);
 228                   g.drawLine( w-2, corner+1, w-2, h-corner);
 229                   g.drawLine( corner+1, h-2, w-corner, h-2);
 230 
 231                   g.setColor(shadow);
 232                   // Draw the Long shadow lines
 233                   g.drawLine( corner, 2, w-corner-1, 2);
 234                   g.drawLine( 2, corner, 2, h-corner-1);
 235                   g.drawLine( w-3, corner, w-3, h-corner-1);
 236                   g.drawLine( corner, h-3, w-corner-1, h-3);
 237               }
 238 
 239           }
 240 
 241           public Insets getBorderInsets(Component c, Insets newInsets) {
 242               newInsets.set(5, 5, 5, 5);
 243               return newInsets;
 244           }
 245     }
 246 
 247     /**
 248      * Border for a Frame.
 249      * @since 1.4
 250      */
 251     static class FrameBorder extends AbstractBorder implements UIResource {
 252         private static final int corner = 14;
 253 
 254         public void paintBorder(Component c, Graphics g, int x, int y,
 255             int w, int h) {
 256 
 257             Color background;
 258             Color highlight;
 259             Color shadow;
 260 
 261             Window window = SwingUtilities.getWindowAncestor(c);
 262             if (window != null && window.isActive()) {
 263                 background = MetalLookAndFeel.getPrimaryControlDarkShadow();
 264                 highlight = MetalLookAndFeel.getPrimaryControlShadow();
 265                 shadow = MetalLookAndFeel.getPrimaryControlInfo();
 266             } else {
 267                 background = MetalLookAndFeel.getControlDarkShadow();
 268                 highlight = MetalLookAndFeel.getControlShadow();
 269                 shadow = MetalLookAndFeel.getControlInfo();
 270             }
 271 
 272             g.setColor(background);
 273             // Draw outermost lines
 274             g.drawLine( x+1, y+0, x+w-2, y+0);
 275             g.drawLine( x+0, y+1, x+0, y +h-2);
 276             g.drawLine( x+w-1, y+1, x+w-1, y+h-2);
 277             g.drawLine( x+1, y+h-1, x+w-2, y+h-1);
 278 
 279             // Draw the bulk of the border
 280             for (int i = 1; i < 5; i++) {
 281                 g.drawRect(x+i,y+i,w-(i*2)-1, h-(i*2)-1);
 282             }
 283 
 284             if ((window instanceof Frame) && ((Frame) window).isResizable()) {
 285                 g.setColor(highlight);
 286                 // Draw the Long highlight lines
 287                 g.drawLine( corner+1, 3, w-corner, 3);
 288                 g.drawLine( 3, corner+1, 3, h-corner);
 289                 g.drawLine( w-2, corner+1, w-2, h-corner);
 290                 g.drawLine( corner+1, h-2, w-corner, h-2);
 291 
 292                 g.setColor(shadow);
 293                 // Draw the Long shadow lines
 294                 g.drawLine( corner, 2, w-corner-1, 2);
 295                 g.drawLine( 2, corner, 2, h-corner-1);
 296                 g.drawLine( w-3, corner, w-3, h-corner-1);
 297                 g.drawLine( corner, h-3, w-corner-1, h-3);
 298             }
 299 
 300         }
 301 
 302         public Insets getBorderInsets(Component c, Insets newInsets)
 303         {
 304             newInsets.set(5, 5, 5, 5);
 305             return newInsets;
 306         }
 307     }
 308 
 309     /**
 310      * Border for a Frame.
 311      * @since 1.4
 312      */
 313     static class DialogBorder extends AbstractBorder implements UIResource
 314     {
 315         private static final int corner = 14;
 316 
 317         protected Color getActiveBackground()
 318         {
 319             return MetalLookAndFeel.getPrimaryControlDarkShadow();
 320         }
 321 
 322         protected Color getActiveHighlight()
 323         {
 324             return MetalLookAndFeel.getPrimaryControlShadow();
 325         }
 326 
 327         protected Color getActiveShadow()
 328         {
 329             return MetalLookAndFeel.getPrimaryControlInfo();
 330         }
 331 
 332         protected Color getInactiveBackground()
 333         {
 334             return MetalLookAndFeel.getControlDarkShadow();
 335         }
 336 
 337         protected Color getInactiveHighlight()
 338         {
 339             return MetalLookAndFeel.getControlShadow();
 340         }
 341 
 342         protected Color getInactiveShadow()
 343         {
 344             return MetalLookAndFeel.getControlInfo();
 345         }
 346 
 347         public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
 348         {
 349             Color background;
 350             Color highlight;
 351             Color shadow;
 352 
 353             Window window = SwingUtilities.getWindowAncestor(c);
 354             if (window != null && window.isActive()) {
 355                 background = getActiveBackground();
 356                 highlight = getActiveHighlight();
 357                 shadow = getActiveShadow();
 358             } else {
 359                 background = getInactiveBackground();
 360                 highlight = getInactiveHighlight();
 361                 shadow = getInactiveShadow();
 362             }
 363 
 364             g.setColor(background);
 365             // Draw outermost lines
 366             g.drawLine( x + 1, y + 0, x + w-2, y + 0);
 367             g.drawLine( x + 0, y + 1, x + 0, y + h - 2);
 368             g.drawLine( x + w - 1, y + 1, x + w - 1, y + h - 2);
 369             g.drawLine( x + 1, y + h - 1, x + w - 2, y + h - 1);
 370 
 371             // Draw the bulk of the border
 372             for (int i = 1; i < 5; i++) {
 373                 g.drawRect(x+i,y+i,w-(i*2)-1, h-(i*2)-1);
 374             }
 375 
 376 
 377             if ((window instanceof Dialog) && ((Dialog) window).isResizable()) {
 378                 g.setColor(highlight);
 379                 // Draw the Long highlight lines
 380                 g.drawLine( corner+1, 3, w-corner, 3);
 381                 g.drawLine( 3, corner+1, 3, h-corner);
 382                 g.drawLine( w-2, corner+1, w-2, h-corner);
 383                 g.drawLine( corner+1, h-2, w-corner, h-2);
 384 
 385                 g.setColor(shadow);
 386                 // Draw the Long shadow lines
 387                 g.drawLine( corner, 2, w-corner-1, 2);
 388                 g.drawLine( 2, corner, 2, h-corner-1);
 389                 g.drawLine( w-3, corner, w-3, h-corner-1);
 390                 g.drawLine( corner, h-3, w-corner-1, h-3);
 391             }
 392 
 393         }
 394 
 395         public Insets getBorderInsets(Component c, Insets newInsets)
 396         {
 397             newInsets.set(5, 5, 5, 5);
 398             return newInsets;
 399         }
 400     }
 401 
 402     /**
 403      * Border for an Error Dialog.
 404      * @since 1.4
 405      */
 406     static class ErrorDialogBorder extends DialogBorder implements UIResource
 407     {
 408         protected Color getActiveBackground() {
 409             return UIManager.getColor("OptionPane.errorDialog.border.background");
 410         }
 411     }
 412 
 413 
 414     /**
 415      * Border for a QuestionDialog.  Also used for a JFileChooser and a
 416      * JColorChooser..
 417      * @since 1.4
 418      */
 419     static class QuestionDialogBorder extends DialogBorder implements UIResource
 420     {
 421         protected Color getActiveBackground() {
 422             return UIManager.getColor("OptionPane.questionDialog.border.background");
 423         }
 424     }
 425 
 426 
 427     /**
 428      * Border for a Warning Dialog.
 429      * @since 1.4
 430      */
 431     static class WarningDialogBorder extends DialogBorder implements UIResource
 432     {
 433         protected Color getActiveBackground() {
 434             return UIManager.getColor("OptionPane.warningDialog.border.background");
 435         }
 436     }
 437 
 438 
 439     /**
 440      * Border for a Palette.
 441      * @since 1.3
 442      */
 443     public static class PaletteBorder extends AbstractBorder implements UIResource {
 444         int titleHeight = 0;
 445 
 446         public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) {
 447 
 448             g.translate(x,y);
 449             g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
 450             g.drawLine(0, 1, 0, h-2);
 451             g.drawLine(1, h-1, w-2, h-1);
 452             g.drawLine(w-1,  1, w-1, h-2);
 453             g.drawLine( 1, 0, w-2, 0);
 454             g.drawRect(1,1, w-3, h-3);
 455             g.translate(-x,-y);
 456 
 457         }
 458 
 459         public Insets getBorderInsets(Component c, Insets newInsets) {
 460             newInsets.set(1, 1, 1, 1);
 461             return newInsets;
 462         }
 463     }
 464 
 465     public static class OptionDialogBorder extends AbstractBorder implements UIResource {
 466         int titleHeight = 0;
 467 
 468         public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) {
 469 
 470             g.translate(x,y);
 471 
 472             int messageType = JOptionPane.PLAIN_MESSAGE;
 473             if (c instanceof JInternalFrame) {
 474                 Object obj = ((JInternalFrame) c).getClientProperty(
 475                               "JInternalFrame.messageType");
 476                 if (obj instanceof Integer) {
 477                     messageType = (Integer) obj;
 478                 }
 479             }
 480 
 481             Color borderColor;
 482 
 483             switch (messageType) {
 484             case(JOptionPane.ERROR_MESSAGE):
 485                 borderColor = UIManager.getColor(
 486                     "OptionPane.errorDialog.border.background");
 487                 break;
 488             case(JOptionPane.QUESTION_MESSAGE):
 489                 borderColor = UIManager.getColor(
 490                     "OptionPane.questionDialog.border.background");
 491                 break;
 492             case(JOptionPane.WARNING_MESSAGE):
 493                 borderColor = UIManager.getColor(
 494                     "OptionPane.warningDialog.border.background");
 495                 break;
 496             case(JOptionPane.INFORMATION_MESSAGE):
 497             case(JOptionPane.PLAIN_MESSAGE):
 498             default:
 499                 borderColor = MetalLookAndFeel.getPrimaryControlDarkShadow();
 500                 break;
 501             }
 502 
 503             g.setColor(borderColor);
 504 
 505               // Draw outermost lines
 506               g.drawLine( 1, 0, w-2, 0);
 507               g.drawLine( 0, 1, 0, h-2);
 508               g.drawLine( w-1, 1, w-1, h-2);
 509               g.drawLine( 1, h-1, w-2, h-1);
 510 
 511               // Draw the bulk of the border
 512               for (int i = 1; i < 3; i++) {
 513                   g.drawRect(i, i, w-(i*2)-1, h-(i*2)-1);
 514               }
 515 
 516             g.translate(-x,-y);
 517 
 518         }
 519 
 520         public Insets getBorderInsets(Component c, Insets newInsets) {
 521             newInsets.set(3, 3, 3, 3);
 522             return newInsets;
 523         }
 524     }
 525 
 526 
 527     public static class MenuBarBorder extends AbstractBorder implements UIResource {
 528         protected static Insets borderInsets = new Insets( 1, 0, 1, 0 );
 529 
 530         public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) {
 531             g.translate( x, y );
 532 
 533             if (MetalLookAndFeel.usingOcean()) {
 534                 // Only paint a border if we're not next to a horizontal
 535                 // toolbar
 536                 if ((c instanceof JMenuBar) && !MetalToolBarUI.doesMenuBarBorderToolBar((JMenuBar)c)) {
 537                     g.setColor(MetalLookAndFeel.getControl());
 538                     g.drawLine(0, h - 2, w, h - 2);
 539                     g.setColor(UIManager.getColor("MenuBar.borderColor"));
 540                     g.drawLine(0, h - 1, w, h - 1);
 541                 }
 542             }
 543             else {
 544                 g.setColor( MetalLookAndFeel.getControlShadow() );
 545                 g.drawLine( 0, h-1, w, h-1 );
 546             }
 547 
 548             g.translate( -x, -y );
 549 
 550         }
 551 
 552         public Insets getBorderInsets(Component c, Insets newInsets) {
 553             if (MetalLookAndFeel.usingOcean()) {
 554                 newInsets.set(0, 0, 2, 0);
 555             }
 556             else {
 557                 newInsets.set(1, 0, 1, 0);
 558             }
 559             return newInsets;
 560         }
 561     }
 562 
 563     public static class MenuItemBorder extends AbstractBorder implements UIResource {
 564         protected static Insets borderInsets = new Insets( 2, 2, 2, 2 );
 565 
 566         public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) {
 567             if (!(c instanceof JMenuItem)) {
 568                 return;
 569             }
 570             JMenuItem b = (JMenuItem) c;
 571             ButtonModel model = b.getModel();
 572 
 573             g.translate( x, y );
 574 
 575             if ( c.getParent() instanceof JMenuBar ) {
 576                 if ( model.isArmed() || model.isSelected() ) {
 577                     g.setColor( MetalLookAndFeel.getControlDarkShadow() );
 578                     g.drawLine( 0, 0, w - 2, 0 );
 579                     g.drawLine( 0, 0, 0, h - 1 );
 580                     g.drawLine( w - 2, 2, w - 2, h - 1 );
 581 
 582                     g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
 583                     g.drawLine( w - 1, 1, w - 1, h - 1 );
 584 
 585                     g.setColor( MetalLookAndFeel.getMenuBackground() );
 586                     g.drawLine( w - 1, 0, w - 1, 0 );
 587                 }
 588             } else {
 589                 if (  model.isArmed() || ( c instanceof JMenu && model.isSelected() ) ) {
 590                     g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
 591                     g.drawLine( 0, 0, w - 1, 0 );
 592 
 593                     g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
 594                     g.drawLine( 0, h - 1, w - 1, h - 1 );
 595                 } else {
 596                     g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
 597                     g.drawLine( 0, 0, 0, h - 1 );
 598                 }
 599             }
 600 
 601             g.translate( -x, -y );
 602         }
 603 
 604         public Insets getBorderInsets(Component c, Insets newInsets) {
 605             newInsets.set(2, 2, 2, 2);
 606             return newInsets;
 607         }
 608     }
 609 
 610     public static class PopupMenuBorder extends AbstractBorder implements UIResource {
 611         protected static Insets borderInsets = new Insets( 3, 1, 2, 1 );
 612 
 613         public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) {
 614             g.translate( x, y );
 615 
 616             g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
 617             g.drawRect( 0, 0, w - 1, h - 1 );
 618 
 619             g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
 620             g.drawLine( 1, 1, w - 2, 1 );
 621             g.drawLine( 1, 2, 1, 2 );
 622             g.drawLine( 1, h - 2, 1, h - 2 );
 623 
 624             g.translate( -x, -y );
 625 
 626         }
 627 
 628         public Insets getBorderInsets(Component c, Insets newInsets) {
 629             newInsets.set(3, 1, 2, 1);
 630             return newInsets;
 631         }
 632     }
 633 
 634 
 635     public static class RolloverButtonBorder extends ButtonBorder {
 636 
 637         public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) {
 638             AbstractButton b = (AbstractButton) c;
 639             ButtonModel model = b.getModel();
 640 
 641             if ( model.isRollover() && !( model.isPressed() && !model.isArmed() ) ) {
 642                 super.paintBorder( c, g, x, y, w, h );
 643             }
 644         }
 645 
 646     }
 647 
 648     /**
 649      * A border which is like a Margin border but it will only honor the margin
 650      * if the margin has been explicitly set by the developer.
 651      *
 652      * Note: This is identical to the package private class
 653      * BasicBorders.RolloverMarginBorder and should probably be consolidated.
 654      */
 655     static class RolloverMarginBorder extends EmptyBorder {
 656 
 657         public RolloverMarginBorder() {
 658             super(3,3,3,3); // hardcoded margin for JLF requirements.
 659         }
 660 
 661         public Insets getBorderInsets(Component c, Insets insets) {
 662             Insets margin = null;
 663 
 664             if (c instanceof AbstractButton) {
 665                 margin = ((AbstractButton)c).getMargin();
 666             }
 667             if (margin == null || margin instanceof UIResource) {
 668                 // default margin so replace
 669                 insets.left = left;
 670                 insets.top = top;
 671                 insets.right = right;
 672                 insets.bottom = bottom;
 673             } else {
 674                 // Margin which has been explicitly set by the user.
 675                 insets.left = margin.left;
 676                 insets.top = margin.top;
 677                 insets.right = margin.right;
 678                 insets.bottom = margin.bottom;
 679             }
 680             return insets;
 681         }
 682     }
 683 
 684     public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants
 685     {
 686         protected MetalBumps bumps = new MetalBumps( 10, 10,
 687                                       MetalLookAndFeel.getControlHighlight(),
 688                                       MetalLookAndFeel.getControlDarkShadow(),
 689                                      UIManager.getColor("ToolBar.background"));
 690 
 691         public void paintBorder( Component c, Graphics g, int x, int y, int w, int h )
 692         {
 693             if (!(c instanceof JToolBar)) {
 694                 return;
 695             }
 696             g.translate( x, y );
 697 
 698             if ( ((JToolBar) c).isFloatable() )
 699             {
 700                 if ( ((JToolBar) c).getOrientation() == HORIZONTAL )
 701                 {
 702                     int shift = MetalLookAndFeel.usingOcean() ? -1 : 0;
 703                     bumps.setBumpArea( 10, h - 4 );
 704                     if( MetalUtils.isLeftToRight(c) ) {
 705                         bumps.paintIcon( c, g, 2, 2 + shift );
 706                     } else {
 707                         bumps.paintIcon( c, g, w-12,
 708                                          2 + shift );
 709                     }
 710                 }
 711                 else // vertical
 712                 {
 713                     bumps.setBumpArea( w - 4, 10 );
 714                     bumps.paintIcon( c, g, 2, 2 );
 715                 }
 716 
 717             }
 718 
 719             if (((JToolBar) c).getOrientation() == HORIZONTAL &&
 720                                MetalLookAndFeel.usingOcean()) {
 721                 g.setColor(MetalLookAndFeel.getControl());
 722                 g.drawLine(0, h - 2, w, h - 2);
 723                 g.setColor(UIManager.getColor("ToolBar.borderColor"));
 724                 g.drawLine(0, h - 1, w, h - 1);
 725             }
 726 
 727             g.translate( -x, -y );
 728         }
 729 
 730         public Insets getBorderInsets(Component c, Insets newInsets) {
 731             if (MetalLookAndFeel.usingOcean()) {
 732                 newInsets.set(1, 2, 3, 2);
 733             }
 734             else {
 735                 newInsets.top = newInsets.left = newInsets.bottom = newInsets.right = 2;
 736             }
 737 
 738             if (!(c instanceof JToolBar)) {
 739                 return newInsets;
 740             }
 741             if ( ((JToolBar) c).isFloatable() ) {
 742                 if ( ((JToolBar) c).getOrientation() == HORIZONTAL ) {
 743                     if (c.getComponentOrientation().isLeftToRight()) {
 744                         newInsets.left = 16;
 745                     } else {
 746                         newInsets.right = 16;
 747                     }
 748                 } else {// vertical
 749                     newInsets.top = 16;
 750                 }
 751             }
 752 
 753             Insets margin = ((JToolBar) c).getMargin();
 754 
 755             if ( margin != null ) {
 756                 newInsets.left   += margin.left;
 757                 newInsets.top    += margin.top;
 758                 newInsets.right  += margin.right;
 759                 newInsets.bottom += margin.bottom;
 760             }
 761 
 762             return newInsets;
 763         }
 764     }
 765 
 766     private static Border buttonBorder;
 767 
 768     /**
 769      * Returns a border instance for a JButton
 770      * @since 1.3
 771      */
 772     public static Border getButtonBorder() {
 773         if (buttonBorder == null) {
 774             buttonBorder = new BorderUIResource.CompoundBorderUIResource(
 775                                                    new MetalBorders.ButtonBorder(),
 776                                                    new BasicBorders.MarginBorder());
 777         }
 778         return buttonBorder;
 779     }
 780 
 781     private static Border textBorder;
 782 
 783     /**
 784      * Returns a border instance for a text component
 785      * @since 1.3
 786      */
 787     public static Border getTextBorder() {
 788         if (textBorder == null) {
 789             textBorder = new BorderUIResource.CompoundBorderUIResource(
 790                                                    new MetalBorders.Flush3DBorder(),
 791                                                    new BasicBorders.MarginBorder());
 792         }
 793         return textBorder;
 794     }
 795 
 796     private static Border textFieldBorder;
 797 
 798     /**
 799      * Returns a border instance for a JTextField
 800      * @since 1.3
 801      */
 802     public static Border getTextFieldBorder() {
 803         if (textFieldBorder == null) {
 804             textFieldBorder = new BorderUIResource.CompoundBorderUIResource(
 805                                                    new MetalBorders.TextFieldBorder(),
 806                                                    new BasicBorders.MarginBorder());
 807         }
 808         return textFieldBorder;
 809     }
 810 
 811     public static class TextFieldBorder extends Flush3DBorder {
 812 
 813         public void paintBorder(Component c, Graphics g, int x, int y,
 814                                 int w, int h) {
 815 
 816           if (!(c instanceof JTextComponent)) {
 817                 // special case for non-text components (bug ID 4144840)
 818                 if (c.isEnabled()) {
 819                     MetalUtils.drawFlush3DBorder(g, x, y, w, h);
 820                 } else {
 821                     MetalUtils.drawDisabledBorder(g, x, y, w, h);
 822                 }
 823                 return;
 824             }
 825 
 826             if (c.isEnabled() && ((JTextComponent)c).isEditable()) {
 827                 MetalUtils.drawFlush3DBorder(g, x, y, w, h);
 828             } else {
 829                 MetalUtils.drawDisabledBorder(g, x, y, w, h);
 830             }
 831 
 832         }
 833     }
 834 
 835     public static class ScrollPaneBorder extends AbstractBorder implements UIResource {
 836         public void paintBorder(Component c, Graphics g, int x, int y,
 837                           int w, int h) {
 838 
 839             if (!(c instanceof JScrollPane)) {
 840                 return;
 841             }
 842             JScrollPane scroll = (JScrollPane)c;
 843             JComponent colHeader = scroll.getColumnHeader();
 844             int colHeaderHeight = 0;
 845             if (colHeader != null)
 846                colHeaderHeight = colHeader.getHeight();
 847 
 848             JComponent rowHeader = scroll.getRowHeader();
 849             int rowHeaderWidth = 0;
 850             if (rowHeader != null)
 851                rowHeaderWidth = rowHeader.getWidth();
 852 
 853 
 854             g.translate( x, y);
 855 
 856             g.setColor( MetalLookAndFeel.getControlDarkShadow() );
 857             g.drawRect( 0, 0, w-2, h-2 );
 858             g.setColor( MetalLookAndFeel.getControlHighlight() );
 859 
 860             g.drawLine( w-1, 1, w-1, h-1);
 861             g.drawLine( 1, h-1, w-1, h-1);
 862 
 863             g.setColor( MetalLookAndFeel.getControl() );
 864             g.drawLine( w-2, 2+colHeaderHeight, w-2, 2+colHeaderHeight );
 865             g.drawLine( 1+rowHeaderWidth, h-2, 1+rowHeaderWidth, h-2 );
 866 
 867             g.translate( -x, -y);
 868 
 869         }
 870 
 871         public Insets getBorderInsets(Component c, Insets insets) {
 872             insets.set(1, 1, 2, 2);
 873             return insets;
 874         }
 875     }
 876 
 877     private static Border toggleButtonBorder;
 878 
 879     /**
 880      * Returns a border instance for a JToggleButton
 881      * @since 1.3
 882      */
 883     public static Border getToggleButtonBorder() {
 884         if (toggleButtonBorder == null) {
 885             toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
 886                                                    new MetalBorders.ToggleButtonBorder(),
 887                                                    new BasicBorders.MarginBorder());
 888         }
 889         return toggleButtonBorder;
 890     }
 891 
 892     /**
 893      * @since 1.3
 894      */
 895     public static class ToggleButtonBorder extends ButtonBorder {
 896         public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
 897             AbstractButton button = (AbstractButton)c;
 898             ButtonModel model = button.getModel();
 899             if (MetalLookAndFeel.usingOcean()) {
 900                 if(model.isArmed() || !button.isEnabled()) {
 901                     super.paintBorder(c, g, x, y, w, h);
 902                 }
 903                 else {
 904                  g.setColor(MetalLookAndFeel.getControlDarkShadow());
 905                  g.drawRect(0, 0, w - 1, h - 1);
 906             }
 907             return;
 908         }
 909             if (! c.isEnabled() ) {
 910                 MetalUtils.drawDisabledBorder( g, x, y, w-1, h-1 );
 911             } else {
 912                 if ( model.isPressed() && model.isArmed() ) {
 913                    MetalUtils.drawPressed3DBorder( g, x, y, w, h );
 914                 } else if ( model.isSelected() ) {
 915                     MetalUtils.drawDark3DBorder( g, x, y, w, h );
 916                 } else {
 917                     MetalUtils.drawFlush3DBorder( g, x, y, w, h );
 918                 }
 919             }
 920         }
 921     }
 922 
 923     /**
 924      * Border for a Table Header
 925      * @since 1.3
 926      */
 927     public static class TableHeaderBorder extends javax.swing.border.AbstractBorder {
 928         protected Insets editorBorderInsets = new Insets( 2, 2, 2, 0 );
 929 
 930         public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
 931             g.translate( x, y );
 932 
 933             g.setColor( MetalLookAndFeel.getControlDarkShadow() );
 934             g.drawLine( w-1, 0, w-1, h-1 );
 935             g.drawLine( 1, h-1, w-1, h-1 );
 936             g.setColor( MetalLookAndFeel.getControlHighlight() );
 937             g.drawLine( 0, 0, w-2, 0 );
 938             g.drawLine( 0, 0, 0, h-2 );
 939 
 940             g.translate( -x, -y );
 941         }
 942 
 943         public Insets getBorderInsets(Component c, Insets insets) {
 944             insets.set(2, 2, 2, 0);
 945             return insets;
 946         }
 947     }
 948 
 949     /**
 950      * Returns a border instance for a Desktop Icon
 951      * @since 1.3
 952      */
 953     public static Border getDesktopIconBorder() {
 954         return new BorderUIResource.CompoundBorderUIResource(
 955                                           new LineBorder(MetalLookAndFeel.getControlDarkShadow(), 1),
 956                                           new MatteBorder (2,2,1,2, MetalLookAndFeel.getControl()));
 957     }
 958 
 959     static Border getToolBarRolloverBorder() {
 960         if (MetalLookAndFeel.usingOcean()) {
 961             return new CompoundBorder(
 962                 new MetalBorders.ButtonBorder(),
 963                 new MetalBorders.RolloverMarginBorder());
 964         }
 965         return new CompoundBorder(new MetalBorders.RolloverButtonBorder(),
 966                                   new MetalBorders.RolloverMarginBorder());
 967     }
 968 
 969     static Border getToolBarNonrolloverBorder() {
 970         if (MetalLookAndFeel.usingOcean()) {
 971             new CompoundBorder(
 972                 new MetalBorders.ButtonBorder(),
 973                 new MetalBorders.RolloverMarginBorder());
 974         }
 975         return new CompoundBorder(new MetalBorders.ButtonBorder(),
 976                                   new MetalBorders.RolloverMarginBorder());
 977     }
 978 }