1 /*
   2  * Copyright (c) 1998, 2004, 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.plaf.UIResource;
  30 import java.awt.*;
  31 import java.awt.image.BufferedImage;
  32 import java.io.Serializable;
  33 import java.util.Enumeration;
  34 import java.util.Vector;
  35 import sun.swing.CachedPainter;
  36 
  37 /**
  38  * Factory object that vends <code>Icon</code>s for
  39  * the Java<sup><font size="-2">TM</font></sup> look and feel (Metal).
  40  * These icons are used extensively in Metal via the defaults mechanism.
  41  * While other look and feels often use GIFs for icons, creating icons
  42  * in code facilitates switching to other themes.
  43  *
  44  * <p>
  45  * Each method in this class returns
  46  * either an <code>Icon</code> or <code>null</code>,
  47  * where <code>null</code> implies that there is no default icon.
  48  *
  49  * <p>
  50  * <strong>Warning:</strong>
  51  * Serialized objects of this class will not be compatible with
  52  * future Swing releases. The current serialization support is
  53  * appropriate for short term storage or RMI between applications running
  54  * the same version of Swing.  As of 1.4, support for long term storage
  55  * of all JavaBeans<sup><font size="-2">TM</font></sup>
  56  * has been added to the <code>java.beans</code> package.
  57  * Please see {@link java.beans.XMLEncoder}.
  58  *
  59  * @author Michael C. Albers
  60  */
  61 public class MetalIconFactory implements Serializable {
  62 
  63     // List of code-drawn Icons
  64     private static Icon fileChooserDetailViewIcon;
  65     private static Icon fileChooserHomeFolderIcon;
  66     private static Icon fileChooserListViewIcon;
  67     private static Icon fileChooserNewFolderIcon;
  68     private static Icon fileChooserUpFolderIcon;
  69     private static Icon internalFrameAltMaximizeIcon;
  70     private static Icon internalFrameCloseIcon;
  71     private static Icon internalFrameDefaultMenuIcon;
  72     private static Icon internalFrameMaximizeIcon;
  73     private static Icon internalFrameMinimizeIcon;
  74     private static Icon radioButtonIcon;
  75     private static Icon treeComputerIcon;
  76     private static Icon treeFloppyDriveIcon;
  77     private static Icon treeHardDriveIcon;
  78 
  79 
  80     private static Icon menuArrowIcon;
  81     private static Icon menuItemArrowIcon;
  82     private static Icon checkBoxMenuItemIcon;
  83     private static Icon radioButtonMenuItemIcon;
  84     private static Icon checkBoxIcon;
  85 
  86 
  87     // Ocean icons
  88     private static Icon oceanHorizontalSliderThumb;
  89     private static Icon oceanVerticalSliderThumb;
  90 
  91     // Constants
  92     public static final boolean DARK = false;
  93     public static final boolean LIGHT = true;
  94 
  95     // Accessor functions for Icons. Does the caching work.
  96     public static Icon getFileChooserDetailViewIcon() {
  97         if (fileChooserDetailViewIcon == null) {
  98             fileChooserDetailViewIcon = new FileChooserDetailViewIcon();
  99         }
 100         return fileChooserDetailViewIcon;
 101     }
 102 
 103     public static Icon getFileChooserHomeFolderIcon() {
 104         if (fileChooserHomeFolderIcon == null) {
 105             fileChooserHomeFolderIcon = new FileChooserHomeFolderIcon();
 106         }
 107         return fileChooserHomeFolderIcon;
 108     }
 109 
 110     public static Icon getFileChooserListViewIcon() {
 111         if (fileChooserListViewIcon == null) {
 112             fileChooserListViewIcon = new FileChooserListViewIcon();
 113         }
 114         return fileChooserListViewIcon;
 115     }
 116 
 117     public static Icon getFileChooserNewFolderIcon() {
 118         if (fileChooserNewFolderIcon == null) {
 119             fileChooserNewFolderIcon = new FileChooserNewFolderIcon();
 120         }
 121         return fileChooserNewFolderIcon;
 122     }
 123 
 124     public static Icon getFileChooserUpFolderIcon() {
 125         if (fileChooserUpFolderIcon == null) {
 126             fileChooserUpFolderIcon = new FileChooserUpFolderIcon();
 127         }
 128         return fileChooserUpFolderIcon;
 129     }
 130 
 131     public static Icon getInternalFrameAltMaximizeIcon(int size) {
 132         return new InternalFrameAltMaximizeIcon(size);
 133     }
 134 
 135     public static Icon getInternalFrameCloseIcon(int size) {
 136         return new InternalFrameCloseIcon(size);
 137     }
 138 
 139     public static Icon getInternalFrameDefaultMenuIcon() {
 140         if (internalFrameDefaultMenuIcon == null) {
 141             internalFrameDefaultMenuIcon = new InternalFrameDefaultMenuIcon();
 142         }
 143         return internalFrameDefaultMenuIcon;
 144     }
 145 
 146     public static Icon getInternalFrameMaximizeIcon(int size) {
 147         return new InternalFrameMaximizeIcon(size);
 148     }
 149 
 150     public static Icon getInternalFrameMinimizeIcon(int size) {
 151         return new InternalFrameMinimizeIcon(size);
 152     }
 153 
 154     public static Icon getRadioButtonIcon() {
 155         if (radioButtonIcon == null) {
 156             radioButtonIcon = new RadioButtonIcon();
 157         }
 158         return radioButtonIcon;
 159     }
 160 
 161     /**
 162      * Returns a checkbox icon.
 163      * @since 1.3
 164      */
 165     public static Icon getCheckBoxIcon() {
 166         if (checkBoxIcon == null) {
 167             checkBoxIcon = new CheckBoxIcon();
 168         }
 169         return checkBoxIcon;
 170     }
 171 
 172     public static Icon getTreeComputerIcon() {
 173         if ( treeComputerIcon == null ) {
 174             treeComputerIcon = new TreeComputerIcon();
 175         }
 176         return treeComputerIcon;
 177     }
 178 
 179     public static Icon getTreeFloppyDriveIcon() {
 180         if ( treeFloppyDriveIcon == null ) {
 181             treeFloppyDriveIcon = new TreeFloppyDriveIcon();
 182         }
 183         return treeFloppyDriveIcon;
 184     }
 185 
 186     public static Icon getTreeFolderIcon() {
 187         return new TreeFolderIcon();
 188     }
 189 
 190     public static Icon getTreeHardDriveIcon() {
 191         if ( treeHardDriveIcon == null ) {
 192             treeHardDriveIcon = new TreeHardDriveIcon();
 193         }
 194         return treeHardDriveIcon;
 195     }
 196 
 197     public static Icon getTreeLeafIcon() {
 198         return new TreeLeafIcon();
 199     }
 200 
 201     public static Icon getTreeControlIcon( boolean isCollapsed ) {
 202             return new TreeControlIcon( isCollapsed );
 203     }
 204 
 205     public static Icon getMenuArrowIcon() {
 206         if (menuArrowIcon == null) {
 207             menuArrowIcon = new MenuArrowIcon();
 208         }
 209         return menuArrowIcon;
 210     }
 211 
 212     /**
 213      * Returns an icon to be used by <code>JCheckBoxMenuItem</code>.
 214      *
 215      * @return the default icon for check box menu items,
 216      *         or <code>null</code> if no default exists
 217      */
 218     public static Icon getMenuItemCheckIcon() {
 219         return null;
 220     }
 221 
 222     public static Icon getMenuItemArrowIcon() {
 223         if (menuItemArrowIcon == null) {
 224             menuItemArrowIcon = new MenuItemArrowIcon();
 225         }
 226         return menuItemArrowIcon;
 227     }
 228 
 229     public static Icon getCheckBoxMenuItemIcon() {
 230         if (checkBoxMenuItemIcon == null) {
 231             checkBoxMenuItemIcon = new CheckBoxMenuItemIcon();
 232         }
 233         return checkBoxMenuItemIcon;
 234     }
 235 
 236     public static Icon getRadioButtonMenuItemIcon() {
 237         if (radioButtonMenuItemIcon == null) {
 238             radioButtonMenuItemIcon = new RadioButtonMenuItemIcon();
 239         }
 240         return radioButtonMenuItemIcon;
 241     }
 242 
 243     public static Icon getHorizontalSliderThumbIcon() {
 244         if (MetalLookAndFeel.usingOcean()) {
 245             if (oceanHorizontalSliderThumb == null) {
 246                 oceanHorizontalSliderThumb =
 247                                new OceanHorizontalSliderThumbIcon();
 248             }
 249             return oceanHorizontalSliderThumb;
 250         }
 251       // don't cache these, bumps don't get updated otherwise
 252         return new HorizontalSliderThumbIcon();
 253     }
 254 
 255     public static Icon getVerticalSliderThumbIcon() {
 256         if (MetalLookAndFeel.usingOcean()) {
 257             if (oceanVerticalSliderThumb == null) {
 258                 oceanVerticalSliderThumb = new OceanVerticalSliderThumbIcon();
 259             }
 260             return oceanVerticalSliderThumb;
 261         }
 262         // don't cache these, bumps don't get updated otherwise
 263         return new VerticalSliderThumbIcon();
 264     }
 265 
 266     // File Chooser Detail View code
 267     private static class FileChooserDetailViewIcon implements Icon, UIResource, Serializable {
 268         public void paintIcon(Component c, Graphics g, int x, int y) {
 269             g.translate(x, y);
 270 
 271             // Draw outside edge of each of the documents
 272             g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
 273             //     top
 274             g.drawLine(2,2, 5,2); // top
 275             g.drawLine(2,3, 2,7); // left
 276             g.drawLine(3,7, 6,7); // bottom
 277             g.drawLine(6,6, 6,3); // right
 278             //     bottom
 279             g.drawLine(2,10, 5,10); // top
 280             g.drawLine(2,11, 2,15); // left
 281             g.drawLine(3,15, 6,15); // bottom
 282             g.drawLine(6,14, 6,11); // right
 283 
 284             // Draw little dots next to documents
 285             //     Same color as outside edge
 286             g.drawLine(8,5, 15,5);     // top
 287             g.drawLine(8,13, 15,13);   // bottom
 288 
 289             // Draw inner highlight on documents
 290             g.setColor(MetalLookAndFeel.getPrimaryControl());
 291             g.drawRect(3,3, 2,3);   // top
 292             g.drawRect(3,11, 2,3);  // bottom
 293 
 294             // Draw inner inner highlight on documents
 295             g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
 296             g.drawLine(4,4, 4,5);     // top
 297             g.drawLine(4,12, 4,13);   // bottom
 298 
 299             g.translate(-x, -y);
 300         }
 301 
 302         public int getIconWidth() {
 303             return 18;
 304         }
 305 
 306         public int getIconHeight() {
 307             return 18;
 308         }
 309     }  // End class FileChooserDetailViewIcon
 310 
 311     // File Chooser Home Folder code
 312     private static class FileChooserHomeFolderIcon implements Icon, UIResource, Serializable {
 313         public void paintIcon(Component c, Graphics g, int x, int y) {
 314             g.translate(x, y);
 315 
 316             // Draw outside edge of house
 317             g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
 318             g.drawLine(8,1, 1,8);  // left edge of roof
 319             g.drawLine(8,1, 15,8); // right edge of roof
 320             g.drawLine(11,2, 11,3); // left edge of chimney
 321             g.drawLine(12,2, 12,4); // right edge of chimney
 322             g.drawLine(3,7, 3,15); // left edge of house
 323             g.drawLine(13,7, 13,15); // right edge of house
 324             g.drawLine(4,15, 12,15); // bottom edge of house
 325             // Draw door frame
 326             //     same color as edge of house
 327             g.drawLine( 6,9,  6,14); // left
 328             g.drawLine(10,9, 10,14); // right
 329             g.drawLine( 7,9,  9, 9); // top
 330 
 331             // Draw roof body
 332             g.setColor(MetalLookAndFeel.getControlDarkShadow());
 333             g.fillRect(8,2, 1,1); //top toward bottom
 334             g.fillRect(7,3, 3,1);
 335             g.fillRect(6,4, 5,1);
 336             g.fillRect(5,5, 7,1);
 337             g.fillRect(4,6, 9,2);
 338             // Draw doornob
 339             //     same color as roof body
 340             g.drawLine(9,12, 9,12);
 341 
 342             // Paint the house
 343             g.setColor(MetalLookAndFeel.getPrimaryControl());
 344             g.drawLine(4,8, 12,8); // above door
 345             g.fillRect(4,9, 2,6); // left of door
 346             g.fillRect(11,9, 2,6); // right of door
 347 
 348             g.translate(-x, -y);
 349         }
 350 
 351         public int getIconWidth() {
 352             return 18;
 353         }
 354 
 355         public int getIconHeight() {
 356             return 18;
 357         }
 358     }  // End class FileChooserHomeFolderIcon
 359 
 360     // File Chooser List View code
 361     private static class FileChooserListViewIcon implements Icon, UIResource, Serializable {
 362         public void paintIcon(Component c, Graphics g, int x, int y) {
 363             g.translate(x, y);
 364 
 365             // Draw outside edge of each of the documents
 366             g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
 367             //     top left
 368             g.drawLine(2,2, 5,2); // top
 369             g.drawLine(2,3, 2,7); // left
 370             g.drawLine(3,7, 6,7); // bottom
 371             g.drawLine(6,6, 6,3); // right
 372             //     top right
 373             g.drawLine(10,2, 13,2); // top
 374             g.drawLine(10,3, 10,7); // left
 375             g.drawLine(11,7, 14,7); // bottom
 376             g.drawLine(14,6, 14,3); // right
 377             //     bottom left
 378             g.drawLine(2,10, 5,10); // top
 379             g.drawLine(2,11, 2,15); // left
 380             g.drawLine(3,15, 6,15); // bottom
 381             g.drawLine(6,14, 6,11); // right
 382             //     bottom right
 383             g.drawLine(10,10, 13,10); // top
 384             g.drawLine(10,11, 10,15); // left
 385             g.drawLine(11,15, 14,15); // bottom
 386             g.drawLine(14,14, 14,11); // right
 387 
 388             // Draw little dots next to documents
 389             //     Same color as outside edge
 390             g.drawLine(8,5, 8,5);     // top left
 391             g.drawLine(16,5, 16,5);   // top right
 392             g.drawLine(8,13, 8,13);   // bottom left
 393             g.drawLine(16,13, 16,13); // bottom right
 394 
 395             // Draw inner highlight on documents
 396             g.setColor(MetalLookAndFeel.getPrimaryControl());
 397             g.drawRect(3,3, 2,3);   // top left
 398             g.drawRect(11,3, 2,3);  // top right
 399             g.drawRect(3,11, 2,3);  // bottom left
 400             g.drawRect(11,11, 2,3); // bottom right
 401 
 402             // Draw inner inner highlight on documents
 403             g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
 404             g.drawLine(4,4, 4,5);     // top left
 405             g.drawLine(12,4, 12,5);   // top right
 406             g.drawLine(4,12, 4,13);   // bottom left
 407             g.drawLine(12,12, 12,13); // bottom right
 408 
 409             g.translate(-x, -y);
 410         }
 411 
 412         public int getIconWidth() {
 413             return 18;
 414         }
 415 
 416         public int getIconHeight() {
 417             return 18;
 418         }
 419     }  // End class FileChooserListViewIcon
 420 
 421     // File Chooser New Folder code
 422     private static class FileChooserNewFolderIcon implements Icon, UIResource, Serializable {
 423         public void paintIcon(Component c, Graphics g, int x, int y) {
 424             g.translate(x, y);
 425 
 426             // Fill background
 427             g.setColor(MetalLookAndFeel.getPrimaryControl());
 428             g.fillRect(3,5, 12,9);
 429 
 430             // Draw outside edge of folder
 431             g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
 432             g.drawLine(1,6,    1,14); // left
 433             g.drawLine(2,14,  15,14); // bottom
 434             g.drawLine(15,13, 15,5);  // right
 435             g.drawLine(2,5,    9,5);  // top left
 436             g.drawLine(10,6,  14,6);  // top right
 437 
 438             // Draw inner folder highlight
 439             g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
 440             g.drawLine( 2,6,  2,13); // left
 441             g.drawLine( 3,6,  9,6);  // top left
 442             g.drawLine(10,7, 14,7);  // top right
 443 
 444             // Draw tab on folder
 445             g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
 446             g.drawLine(11,3, 15,3); // top
 447             g.drawLine(10,4, 15,4); // bottom
 448 
 449             g.translate(-x, -y);
 450         }
 451 
 452         public int getIconWidth() {
 453             return 18;
 454         }
 455 
 456         public int getIconHeight() {
 457             return 18;
 458         }
 459     }  // End class FileChooserNewFolderIcon
 460 
 461     // File Chooser Up Folder code
 462     private static class FileChooserUpFolderIcon implements Icon, UIResource, Serializable {
 463         public void paintIcon(Component c, Graphics g, int x, int y) {
 464             g.translate(x, y);
 465 
 466             // Fill background
 467             g.setColor(MetalLookAndFeel.getPrimaryControl());
 468             g.fillRect(3,5, 12,9);
 469 
 470             // Draw outside edge of folder
 471             g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
 472             g.drawLine(1,6,    1,14); // left
 473             g.drawLine(2,14,  15,14); // bottom
 474             g.drawLine(15,13, 15,5);  // right
 475             g.drawLine(2,5,    9,5);  // top left
 476             g.drawLine(10,6,  14,6);  // top right
 477             // Draw the UP arrow
 478             //     same color as edge
 479             g.drawLine(8,13,  8,16); // arrow shaft
 480             g.drawLine(8, 9,  8, 9); // arrowhead top
 481             g.drawLine(7,10,  9,10);
 482             g.drawLine(6,11, 10,11);
 483             g.drawLine(5,12, 11,12);
 484 
 485             // Draw inner folder highlight
 486             g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
 487             g.drawLine( 2,6,  2,13); // left
 488             g.drawLine( 3,6,  9,6);  // top left
 489             g.drawLine(10,7, 14,7);  // top right
 490 
 491             // Draw tab on folder
 492             g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
 493             g.drawLine(11,3, 15,3); // top
 494             g.drawLine(10,4, 15,4); // bottom
 495 
 496             g.translate(-x, -y);
 497         }
 498 
 499         public int getIconWidth() {
 500             return 18;
 501         }
 502 
 503         public int getIconHeight() {
 504             return 18;
 505         }
 506     }  // End class FileChooserUpFolderIcon
 507 
 508 
 509     /**
 510      * Defines an icon for Palette close
 511      * @since 1.3
 512      */
 513     public static class PaletteCloseIcon implements Icon, UIResource, Serializable{
 514         int iconSize = 7;
 515 
 516         public void paintIcon(Component c, Graphics g, int x, int y) {
 517             JButton parentButton = (JButton)c;
 518             ButtonModel buttonModel = parentButton.getModel();
 519 
 520             Color back;
 521             Color highlight = MetalLookAndFeel.getPrimaryControlHighlight();
 522             Color shadow = MetalLookAndFeel.getPrimaryControlInfo();
 523             if (buttonModel.isPressed() && buttonModel.isArmed()) {
 524                 back = shadow;
 525             } else {
 526                 back = MetalLookAndFeel.getPrimaryControlDarkShadow();
 527             }
 528 
 529             g.translate(x, y);
 530             g.setColor(back);
 531             g.drawLine( 0, 1, 5, 6);
 532             g.drawLine( 1, 0, 6, 5);
 533             g.drawLine( 1, 1, 6, 6);
 534             g.drawLine( 6, 1, 1, 6);
 535             g.drawLine( 5,0, 0,5);
 536             g.drawLine(5,1, 1,5);
 537 
 538             g.setColor(highlight);
 539             g.drawLine(6,2, 5,3);
 540             g.drawLine(2,6, 3, 5);
 541             g.drawLine(6,6,6,6);
 542 
 543 
 544             g.translate(-x, -y);
 545         }
 546 
 547         public int getIconWidth() {
 548             return iconSize;
 549         }
 550 
 551         public int getIconHeight() {
 552             return iconSize;
 553         }
 554     }
 555 
 556     // Internal Frame Close code
 557     private static class InternalFrameCloseIcon implements Icon, UIResource, Serializable {
 558         int iconSize = 16;
 559 
 560         public InternalFrameCloseIcon(int size) {
 561             iconSize = size;
 562         }
 563 
 564         public void paintIcon(Component c, Graphics g, int x, int y) {
 565             JButton parentButton = (JButton)c;
 566             ButtonModel buttonModel = parentButton.getModel();
 567 
 568             Color backgroundColor = MetalLookAndFeel.getPrimaryControl();
 569             Color internalBackgroundColor =
 570                 MetalLookAndFeel.getPrimaryControl();
 571             Color mainItemColor =
 572                 MetalLookAndFeel.getPrimaryControlDarkShadow();
 573             Color darkHighlightColor = MetalLookAndFeel.getBlack();
 574             Color xLightHighlightColor = MetalLookAndFeel.getWhite();
 575             Color boxLightHighlightColor = MetalLookAndFeel.getWhite();
 576 
 577             // if the inactive window
 578             if (parentButton.getClientProperty("paintActive") != Boolean.TRUE)
 579             {
 580                 backgroundColor = MetalLookAndFeel.getControl();
 581                 internalBackgroundColor = backgroundColor;
 582                 mainItemColor = MetalLookAndFeel.getControlDarkShadow();
 583                 // if inactive and pressed
 584                 if (buttonModel.isPressed() && buttonModel.isArmed()) {
 585                     internalBackgroundColor =
 586                         MetalLookAndFeel.getControlShadow();
 587                     xLightHighlightColor = internalBackgroundColor;
 588                     mainItemColor = darkHighlightColor;
 589                 }
 590             }
 591             // if pressed
 592             else if (buttonModel.isPressed() && buttonModel.isArmed()) {
 593                 internalBackgroundColor =
 594                     MetalLookAndFeel.getPrimaryControlShadow();
 595                 xLightHighlightColor = internalBackgroundColor;
 596                 mainItemColor = darkHighlightColor;
 597                 // darkHighlightColor is still "getBlack()"
 598             }
 599 
 600             // Some calculations that are needed more than once later on.
 601             int oneHalf = (int)(iconSize / 2); // 16 -> 8
 602 
 603             g.translate(x, y);
 604 
 605             // fill background
 606             g.setColor(backgroundColor);
 607             g.fillRect(0,0, iconSize,iconSize);
 608 
 609             // fill inside of box area
 610             g.setColor(internalBackgroundColor);
 611             g.fillRect(3,3, iconSize-6,iconSize-6);
 612 
 613             // THE BOX
 614             // the top/left dark higlight - some of this will get overwritten
 615             g.setColor(darkHighlightColor);
 616             g.drawRect(1,1, iconSize-3,iconSize-3);
 617             // draw the inside bottom/right highlight
 618             g.drawRect(2,2, iconSize-5,iconSize-5);
 619             // draw the light/outside, bottom/right highlight
 620             g.setColor(boxLightHighlightColor);
 621             g.drawRect(2,2, iconSize-3,iconSize-3);
 622             // draw the "normal" box
 623             g.setColor(mainItemColor);
 624             g.drawRect(2,2, iconSize-4,iconSize-4);
 625             g.drawLine(3,iconSize-3, 3,iconSize-3); // lower left
 626             g.drawLine(iconSize-3,3, iconSize-3,3); // up right
 627 
 628             // THE "X"
 629             // Dark highlight
 630             g.setColor(darkHighlightColor);
 631             g.drawLine(4,5, 5,4); // far up left
 632             g.drawLine(4,iconSize-6, iconSize-6,4); // against body of "X"
 633             // Light highlight
 634             g.setColor(xLightHighlightColor);
 635             g.drawLine(6,iconSize-5, iconSize-5,6); // against body of "X"
 636               // one pixel over from the body
 637             g.drawLine(oneHalf,oneHalf+2, oneHalf+2,oneHalf);
 638               // bottom right
 639             g.drawLine(iconSize-5,iconSize-5, iconSize-4,iconSize-5);
 640             g.drawLine(iconSize-5,iconSize-4, iconSize-5,iconSize-4);
 641             // Main color
 642             g.setColor(mainItemColor);
 643               // Upper left to lower right
 644             g.drawLine(5,5, iconSize-6,iconSize-6); // g.drawLine(5,5, 10,10);
 645             g.drawLine(6,5, iconSize-5,iconSize-6); // g.drawLine(6,5, 11,10);
 646             g.drawLine(5,6, iconSize-6,iconSize-5); // g.drawLine(5,6, 10,11);
 647               // Lower left to upper right
 648             g.drawLine(5,iconSize-5, iconSize-5,5); // g.drawLine(5,11, 11,5);
 649             g.drawLine(5,iconSize-6, iconSize-6,5); // g.drawLine(5,10, 10,5);
 650 
 651             g.translate(-x, -y);
 652         }
 653 
 654         public int getIconWidth() {
 655             return iconSize;
 656         }
 657 
 658         public int getIconHeight() {
 659             return iconSize;
 660         }
 661     }  // End class InternalFrameCloseIcon
 662 
 663     // Internal Frame Alternate Maximize code (actually, the un-maximize icon)
 664     private static class InternalFrameAltMaximizeIcon implements Icon, UIResource, Serializable {
 665         int iconSize = 16;
 666 
 667         public InternalFrameAltMaximizeIcon(int size) {
 668             iconSize = size;
 669         }
 670 
 671         public void paintIcon(Component c, Graphics g, int x, int y) {
 672             JButton parentButton = (JButton)c;
 673             ButtonModel buttonModel = parentButton.getModel();
 674 
 675             Color backgroundColor = MetalLookAndFeel.getPrimaryControl();
 676             Color internalBackgroundColor =
 677                 MetalLookAndFeel.getPrimaryControl();
 678             Color mainItemColor =
 679                 MetalLookAndFeel.getPrimaryControlDarkShadow();
 680             Color darkHighlightColor = MetalLookAndFeel.getBlack();
 681             // ul = Upper Left and lr = Lower Right
 682             Color ulLightHighlightColor = MetalLookAndFeel.getWhite();
 683             Color lrLightHighlightColor = MetalLookAndFeel.getWhite();
 684 
 685             // if the internal frame is inactive
 686             if (parentButton.getClientProperty("paintActive") != Boolean.TRUE)
 687             {
 688                 backgroundColor = MetalLookAndFeel.getControl();
 689                 internalBackgroundColor = backgroundColor;
 690                 mainItemColor = MetalLookAndFeel.getControlDarkShadow();
 691                 // if inactive and pressed
 692                 if (buttonModel.isPressed() && buttonModel.isArmed()) {
 693                     internalBackgroundColor =
 694                         MetalLookAndFeel.getControlShadow();
 695                     ulLightHighlightColor = internalBackgroundColor;
 696                     mainItemColor = darkHighlightColor;
 697                 }
 698             }
 699             // if the button is pressed and the mouse is over it
 700             else if (buttonModel.isPressed() && buttonModel.isArmed()) {
 701                 internalBackgroundColor =
 702                     MetalLookAndFeel.getPrimaryControlShadow();
 703                 ulLightHighlightColor = internalBackgroundColor;
 704                 mainItemColor = darkHighlightColor;
 705                 // darkHighlightColor is still "getBlack()"
 706             }
 707 
 708             g.translate(x, y);
 709 
 710             // fill background
 711             g.setColor(backgroundColor);
 712             g.fillRect(0,0, iconSize,iconSize);
 713 
 714             // BOX
 715             // fill inside the box
 716             g.setColor(internalBackgroundColor);
 717             g.fillRect(3,6, iconSize-9,iconSize-9);
 718 
 719             // draw dark highlight color
 720             g.setColor(darkHighlightColor);
 721             g.drawRect(1,5, iconSize-8,iconSize-8);
 722             g.drawLine(1,iconSize-2, 1,iconSize-2); // extra pixel on bottom
 723 
 724             // draw lower right light highlight
 725             g.setColor(lrLightHighlightColor);
 726             g.drawRect(2,6, iconSize-7,iconSize-7);
 727             // draw upper left light highlight
 728             g.setColor(ulLightHighlightColor);
 729             g.drawRect(3,7, iconSize-9,iconSize-9);
 730 
 731             // draw the main box
 732             g.setColor(mainItemColor);
 733             g.drawRect(2,6, iconSize-8,iconSize-8);
 734 
 735             // Six extraneous pixels to deal with
 736             g.setColor(ulLightHighlightColor);
 737             g.drawLine(iconSize-6,8,iconSize-6,8);
 738             g.drawLine(iconSize-9,6, iconSize-7,8);
 739             g.setColor(mainItemColor);
 740             g.drawLine(3,iconSize-3,3,iconSize-3);
 741             g.setColor(darkHighlightColor);
 742             g.drawLine(iconSize-6,9,iconSize-6,9);
 743             g.setColor(backgroundColor);
 744             g.drawLine(iconSize-9,5,iconSize-9,5);
 745 
 746             // ARROW
 747             // do the shaft first
 748             g.setColor(mainItemColor);
 749             g.fillRect(iconSize-7,3, 3,5); // do a big block
 750             g.drawLine(iconSize-6,5, iconSize-3,2); // top shaft
 751             g.drawLine(iconSize-6,6, iconSize-2,2); // bottom shaft
 752             g.drawLine(iconSize-6,7, iconSize-3,7); // bottom arrow head
 753 
 754             // draw the dark highlight
 755             g.setColor(darkHighlightColor);
 756             g.drawLine(iconSize-8,2, iconSize-7,2); // top of arrowhead
 757             g.drawLine(iconSize-8,3, iconSize-8,7); // left of arrowhead
 758             g.drawLine(iconSize-6,4, iconSize-3,1); // top of shaft
 759             g.drawLine(iconSize-4,6, iconSize-3,6); // top,right of arrowhead
 760 
 761             // draw the light highlight
 762             g.setColor(lrLightHighlightColor);
 763             g.drawLine(iconSize-6,3, iconSize-6,3); // top
 764             g.drawLine(iconSize-4,5, iconSize-2,3); // under shaft
 765             g.drawLine(iconSize-4,8, iconSize-3,8); // under arrowhead
 766             g.drawLine(iconSize-2,8, iconSize-2,7); // right of arrowhead
 767 
 768             g.translate(-x, -y);
 769         }
 770 
 771         public int getIconWidth() {
 772             return iconSize;
 773         }
 774 
 775         public int getIconHeight() {
 776             return iconSize;
 777         }
 778     }  // End class InternalFrameAltMaximizeIcon
 779 
 780     // Code for the default icons that goes in the upper left corner
 781     private static class InternalFrameDefaultMenuIcon implements Icon, UIResource, Serializable {
 782         public void paintIcon(Component c, Graphics g, int x, int y) {
 783 
 784             Color windowBodyColor = MetalLookAndFeel.getWindowBackground();
 785             Color titleColor = MetalLookAndFeel.getPrimaryControl();
 786             Color edgeColor = MetalLookAndFeel.getPrimaryControlDarkShadow();
 787 
 788             g.translate(x, y);
 789 
 790             // draw background color for title area
 791             // catch four corners and title area
 792             g.setColor(titleColor);
 793             g.fillRect(0,0, 16,16);
 794 
 795             // fill body of window
 796             g.setColor(windowBodyColor);
 797             g.fillRect(2,6, 13,9);
 798             // draw light parts of two "bumps"
 799             g.drawLine(2,2, 2,2);
 800             g.drawLine(5,2, 5,2);
 801             g.drawLine(8,2, 8,2);
 802             g.drawLine(11,2, 11,2);
 803 
 804             // draw line around edge of title and icon
 805             g.setColor(edgeColor);
 806             g.drawRect(1,1, 13,13); // entire inner edge
 807             g.drawLine(1,0, 14,0); // top outter edge
 808             g.drawLine(15,1, 15,14); // right outter edge
 809             g.drawLine(1,15, 14,15); // bottom outter edge
 810             g.drawLine(0,1, 0,14); // left outter edge
 811             g.drawLine(2,5, 13,5); // bottom of title bar area
 812             // draw dark part of four "bumps" (same color)
 813             g.drawLine(3,3, 3,3);
 814             g.drawLine(6,3, 6,3);
 815             g.drawLine(9,3, 9,3);
 816             g.drawLine(12,3, 12,3);
 817 
 818             g.translate(-x, -y);
 819         }
 820 
 821         public int getIconWidth() {
 822             return 16;
 823         }
 824 
 825         public int getIconHeight() {
 826             return 16;
 827         }
 828     }  // End class InternalFrameDefaultMenuIcon
 829 
 830     // Internal Frame Maximize code
 831     private static class InternalFrameMaximizeIcon implements Icon, UIResource, Serializable {
 832         protected int iconSize = 16;
 833 
 834         public InternalFrameMaximizeIcon(int size) {
 835             iconSize = size;
 836         }
 837 
 838         public void paintIcon(Component c, Graphics g, int x, int y) {
 839             JButton parentButton = (JButton)c;
 840             ButtonModel buttonModel = parentButton.getModel();
 841 
 842             Color backgroundColor = MetalLookAndFeel.getPrimaryControl();
 843             Color internalBackgroundColor =
 844                 MetalLookAndFeel.getPrimaryControl();
 845             Color mainItemColor =
 846                 MetalLookAndFeel.getPrimaryControlDarkShadow();
 847             Color darkHighlightColor = MetalLookAndFeel.getBlack();
 848             // ul = Upper Left and lr = Lower Right
 849             Color ulLightHighlightColor = MetalLookAndFeel.getWhite();
 850             Color lrLightHighlightColor = MetalLookAndFeel.getWhite();
 851 
 852             // if the internal frame is inactive
 853             if (parentButton.getClientProperty("paintActive") != Boolean.TRUE)
 854             {
 855                 backgroundColor = MetalLookAndFeel.getControl();
 856                 internalBackgroundColor = backgroundColor;
 857                 mainItemColor = MetalLookAndFeel.getControlDarkShadow();
 858                 // if inactive and pressed
 859                 if (buttonModel.isPressed() && buttonModel.isArmed()) {
 860                     internalBackgroundColor =
 861                         MetalLookAndFeel.getControlShadow();
 862                     ulLightHighlightColor = internalBackgroundColor;
 863                     mainItemColor = darkHighlightColor;
 864                 }
 865             }
 866             // if the button is pressed and the mouse is over it
 867             else if (buttonModel.isPressed() && buttonModel.isArmed()) {
 868                 internalBackgroundColor =
 869                     MetalLookAndFeel.getPrimaryControlShadow();
 870                 ulLightHighlightColor = internalBackgroundColor;
 871                 mainItemColor = darkHighlightColor;
 872                 // darkHighlightColor is still "getBlack()"
 873             }
 874 
 875             g.translate(x, y);
 876 
 877             // fill background
 878             g.setColor(backgroundColor);
 879             g.fillRect(0,0, iconSize,iconSize);
 880 
 881             // BOX drawing
 882             // fill inside the box
 883             g.setColor(internalBackgroundColor);
 884             g.fillRect(3,7, iconSize-10,iconSize-10);
 885 
 886             // light highlight
 887             g.setColor(ulLightHighlightColor);
 888             g.drawRect(3,7, iconSize-10,iconSize-10); // up,left
 889             g.setColor(lrLightHighlightColor);
 890             g.drawRect(2,6, iconSize-7,iconSize-7); // low,right
 891             // dark highlight
 892             g.setColor(darkHighlightColor);
 893             g.drawRect(1,5, iconSize-7,iconSize-7); // outer
 894             g.drawRect(2,6, iconSize-9,iconSize-9); // inner
 895             // main box
 896             g.setColor(mainItemColor);
 897             g.drawRect(2,6, iconSize-8,iconSize-8); // g.drawRect(2,6, 8,8);
 898 
 899             // ARROW drawing
 900             // dark highlight
 901             g.setColor(darkHighlightColor);
 902               // down,left to up,right - inside box
 903             g.drawLine(3,iconSize-5, iconSize-9,7);
 904               // down,left to up,right - outside box
 905             g.drawLine(iconSize-6,4, iconSize-5,3);
 906               // outside edge of arrow head
 907             g.drawLine(iconSize-7,1, iconSize-7,2);
 908               // outside edge of arrow head
 909             g.drawLine(iconSize-6,1, iconSize-2,1);
 910             // light highlight
 911             g.setColor(ulLightHighlightColor);
 912               // down,left to up,right - inside box
 913             g.drawLine(5,iconSize-4, iconSize-8,9);
 914             g.setColor(lrLightHighlightColor);
 915             g.drawLine(iconSize-6,3, iconSize-4,5); // outside box
 916             g.drawLine(iconSize-4,5, iconSize-4,6); // one down from this
 917             g.drawLine(iconSize-2,7, iconSize-1,7); // outside edge arrow head
 918             g.drawLine(iconSize-1,2, iconSize-1,6); // outside edge arrow head
 919             // main part of arrow
 920             g.setColor(mainItemColor);
 921             g.drawLine(3,iconSize-4, iconSize-3,2); // top edge of staff
 922             g.drawLine(3,iconSize-3, iconSize-2,2); // bottom edge of staff
 923             g.drawLine(4,iconSize-3, 5,iconSize-3); // highlights inside of box
 924             g.drawLine(iconSize-7,8, iconSize-7,9); // highlights inside of box
 925             g.drawLine(iconSize-6,2, iconSize-4,2); // top of arrow head
 926             g.drawRect(iconSize-3,3, 1,3); // right of arrow head
 927 
 928             g.translate(-x, -y);
 929         }
 930 
 931         public int getIconWidth() {
 932             return iconSize;
 933         }
 934 
 935         public int getIconHeight() {
 936             return iconSize;
 937         }
 938     }  // End class InternalFrameMaximizeIcon
 939 
 940     // Internal Frame Minimize code
 941     private static class InternalFrameMinimizeIcon implements Icon, UIResource, Serializable {
 942         int iconSize = 16;
 943 
 944         public InternalFrameMinimizeIcon(int size) {
 945             iconSize = size;
 946         }
 947 
 948         public void paintIcon(Component c, Graphics g, int x, int y) {
 949             JButton parentButton = (JButton)c;
 950             ButtonModel buttonModel = parentButton.getModel();
 951 
 952 
 953             Color backgroundColor = MetalLookAndFeel.getPrimaryControl();
 954             Color internalBackgroundColor =
 955                 MetalLookAndFeel.getPrimaryControl();
 956             Color mainItemColor =
 957                 MetalLookAndFeel.getPrimaryControlDarkShadow();
 958             Color darkHighlightColor = MetalLookAndFeel.getBlack();
 959             // ul = Upper Left and lr = Lower Right
 960             Color ulLightHighlightColor = MetalLookAndFeel.getWhite();
 961             Color lrLightHighlightColor = MetalLookAndFeel.getWhite();
 962 
 963             // if the internal frame is inactive
 964             if (parentButton.getClientProperty("paintActive") != Boolean.TRUE)
 965             {
 966                 backgroundColor = MetalLookAndFeel.getControl();
 967                 internalBackgroundColor = backgroundColor;
 968                 mainItemColor = MetalLookAndFeel.getControlDarkShadow();
 969                 // if inactive and pressed
 970                 if (buttonModel.isPressed() && buttonModel.isArmed()) {
 971                     internalBackgroundColor =
 972                         MetalLookAndFeel.getControlShadow();
 973                     ulLightHighlightColor = internalBackgroundColor;
 974                     mainItemColor = darkHighlightColor;
 975                 }
 976             }
 977             // if the button is pressed and the mouse is over it
 978             else if (buttonModel.isPressed() && buttonModel.isArmed()) {
 979                 internalBackgroundColor =
 980                     MetalLookAndFeel.getPrimaryControlShadow();
 981                 ulLightHighlightColor = internalBackgroundColor;
 982                 mainItemColor = darkHighlightColor;
 983                 // darkHighlightColor is still "getBlack()"
 984             }
 985 
 986             g.translate(x, y);
 987 
 988             // fill background
 989             g.setColor(backgroundColor);
 990             g.fillRect(0,0, iconSize,iconSize);
 991 
 992             // BOX drawing
 993             // fill inside the box
 994             g.setColor(internalBackgroundColor);
 995             g.fillRect(4,11, iconSize-13,iconSize-13);
 996             // light highlight
 997             g.setColor(lrLightHighlightColor);
 998             g.drawRect(2,10, iconSize-10,iconSize-11); // low,right
 999             g.setColor(ulLightHighlightColor);
1000             g.drawRect(3,10, iconSize-12,iconSize-12); // up,left
1001             // dark highlight
1002             g.setColor(darkHighlightColor);
1003             g.drawRect(1,8, iconSize-10,iconSize-10); // outer
1004             g.drawRect(2,9, iconSize-12,iconSize-12); // inner
1005             // main box
1006             g.setColor(mainItemColor);
1007             g.drawRect(2,9, iconSize-11,iconSize-11);
1008             g.drawLine(iconSize-10,10, iconSize-10,10); // up right highlight
1009             g.drawLine(3,iconSize-3, 3,iconSize-3); // low left highlight
1010 
1011             // ARROW
1012             // do the shaft first
1013             g.setColor(mainItemColor);
1014             g.fillRect(iconSize-7,3, 3,5); // do a big block
1015             g.drawLine(iconSize-6,5, iconSize-3,2); // top shaft
1016             g.drawLine(iconSize-6,6, iconSize-2,2); // bottom shaft
1017             g.drawLine(iconSize-6,7, iconSize-3,7); // bottom arrow head
1018 
1019             // draw the dark highlight
1020             g.setColor(darkHighlightColor);
1021             g.drawLine(iconSize-8,2, iconSize-7,2); // top of arrowhead
1022             g.drawLine(iconSize-8,3, iconSize-8,7); // left of arrowhead
1023             g.drawLine(iconSize-6,4, iconSize-3,1); // top of shaft
1024             g.drawLine(iconSize-4,6, iconSize-3,6); // top,right of arrowhead
1025 
1026             // draw the light highlight
1027             g.setColor(lrLightHighlightColor);
1028             g.drawLine(iconSize-6,3, iconSize-6,3); // top
1029             g.drawLine(iconSize-4,5, iconSize-2,3); // under shaft
1030             g.drawLine(iconSize-7,8, iconSize-3,8); // under arrowhead
1031             g.drawLine(iconSize-2,8, iconSize-2,7); // right of arrowhead
1032 
1033             g.translate(-x, -y);
1034         }
1035 
1036         public int getIconWidth() {
1037             return iconSize;
1038         }
1039 
1040         public int getIconHeight() {
1041             return iconSize;
1042         }
1043     }  // End class InternalFrameMinimizeIcon
1044 
1045     private static class CheckBoxIcon implements Icon, UIResource, Serializable {
1046 
1047         protected int getControlSize() { return 13; }
1048 
1049         private void paintOceanIcon(Component c, Graphics g, int x, int y) {
1050             ButtonModel model = ((JCheckBox)c).getModel();
1051 
1052             g.translate(x, y);
1053             int w = getIconWidth();
1054             int h = getIconHeight();
1055             if ( model.isEnabled() ) {
1056                 if (model.isPressed() && model.isArmed()) {
1057                     g.setColor(MetalLookAndFeel.getControlShadow());
1058                     g.fillRect(0, 0, w, h);
1059                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
1060                     g.fillRect(0, 0, w, 2);
1061                     g.fillRect(0, 2, 2, h - 2);
1062                     g.fillRect(w - 1, 1, 1, h - 1);
1063                     g.fillRect(1, h - 1, w - 2, 1);
1064                 } else if (model.isRollover()) {
1065                     MetalUtils.drawGradient(c, g, "CheckBox.gradient", 0, 0,
1066                                             w, h, true);
1067                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
1068                     g.drawRect(0, 0, w - 1, h - 1);
1069                     g.setColor(MetalLookAndFeel.getPrimaryControl());
1070                     g.drawRect(1, 1, w - 3, h - 3);
1071                     g.drawRect(2, 2, w - 5, h - 5);
1072                 }
1073                 else {
1074                     MetalUtils.drawGradient(c, g, "CheckBox.gradient", 0, 0,
1075                                             w, h, true);
1076                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
1077                     g.drawRect(0, 0, w - 1, h - 1);
1078                 }
1079                 g.setColor( MetalLookAndFeel.getControlInfo() );
1080             } else {
1081                 g.setColor(MetalLookAndFeel.getControlDarkShadow());
1082                 g.drawRect(0, 0, w - 1, h - 1);
1083             }
1084             g.translate(-x, -y);
1085             if (model.isSelected()) {
1086                 drawCheck(c,g,x,y);
1087             }
1088         }
1089 
1090         public void paintIcon(Component c, Graphics g, int x, int y) {
1091             if (MetalLookAndFeel.usingOcean()) {
1092                 paintOceanIcon(c, g, x, y);
1093                 return;
1094             }
1095             ButtonModel model = ((JCheckBox)c).getModel();
1096             int controlSize = getControlSize();
1097 
1098             if ( model.isEnabled() ) {
1099                 if (model.isPressed() && model.isArmed()) {
1100                     g.setColor( MetalLookAndFeel.getControlShadow() );
1101                     g.fillRect( x, y, controlSize-1, controlSize-1);
1102                     MetalUtils.drawPressed3DBorder(g, x, y, controlSize, controlSize);
1103                 } else {
1104                     MetalUtils.drawFlush3DBorder(g, x, y, controlSize, controlSize);
1105                 }
1106                 g.setColor(c.getForeground());
1107             } else {
1108                 g.setColor( MetalLookAndFeel.getControlShadow() );
1109                 g.drawRect( x, y, controlSize-2, controlSize-2);
1110             }
1111 
1112             if (model.isSelected()) {
1113                 drawCheck(c,g,x,y);
1114             }
1115 
1116         }
1117 
1118         protected void drawCheck(Component c, Graphics g, int x, int y) {
1119             int controlSize = getControlSize();
1120             g.fillRect( x+3, y+5, 2, controlSize-8 );
1121             g.drawLine( x+(controlSize-4), y+3, x+5, y+(controlSize-6) );
1122             g.drawLine( x+(controlSize-4), y+4, x+5, y+(controlSize-5) );
1123         }
1124 
1125         public int getIconWidth() {
1126             return getControlSize();
1127         }
1128 
1129         public int getIconHeight() {
1130             return getControlSize();
1131         }
1132     } // End class CheckBoxIcon
1133 
1134     // Radio button code
1135     private static class RadioButtonIcon implements Icon, UIResource, Serializable {
1136         public void paintOceanIcon(Component c, Graphics g, int x, int y) {
1137             ButtonModel model = ((JRadioButton)c).getModel();
1138             boolean enabled = model.isEnabled();
1139             boolean pressed = (enabled && model.isPressed() &&
1140                                model.isArmed());
1141             boolean rollover = (enabled && model.isRollover());
1142 
1143             g.translate(x, y);
1144             if (enabled && !pressed) {
1145                 // PENDING: this isn't quite right, when we're sure it won't
1146                 // change it needs to be cleaned.
1147                 MetalUtils.drawGradient(c, g, "RadioButton.gradient",
1148                                         1, 1, 10, 10, true);
1149                 g.setColor(c.getBackground());
1150                 g.fillRect(1, 1, 1, 1);
1151                 g.fillRect(10, 1, 1, 1);
1152                 g.fillRect(1, 10, 1, 1);
1153                 g.fillRect(10, 10, 1, 1);
1154             }
1155             else if (pressed || !enabled) {
1156                 if (pressed) {
1157                     g.setColor(MetalLookAndFeel.getPrimaryControl());
1158                 }
1159                 else {
1160                     g.setColor(MetalLookAndFeel.getControl());
1161                 }
1162                 g.fillRect(2, 2, 8, 8);
1163                 g.fillRect(4, 1, 4, 1);
1164                 g.fillRect(4, 10, 4, 1);
1165                 g.fillRect(1, 4, 1, 4);
1166                 g.fillRect(10, 4, 1, 4);
1167             }
1168 
1169             // draw Dark Circle (start at top, go clockwise)
1170             if (!enabled) {
1171                 g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
1172             }
1173             else {
1174                 g.setColor(MetalLookAndFeel.getControlDarkShadow());
1175             }
1176             g.drawLine( 4, 0,  7, 0);
1177             g.drawLine( 8, 1,  9, 1);
1178             g.drawLine(10, 2, 10, 3);
1179             g.drawLine(11, 4, 11, 7);
1180             g.drawLine(10, 8, 10, 9);
1181             g.drawLine( 9,10,  8,10);
1182             g.drawLine( 7,11,  4,11);
1183             g.drawLine( 3,10,  2,10);
1184             g.drawLine( 1, 9,  1, 8);
1185             g.drawLine( 0, 7,  0, 4);
1186             g.drawLine( 1, 3,  1, 2);
1187             g.drawLine( 2, 1,  3, 1);
1188 
1189             if (pressed) {
1190                 g.fillRect(1, 4, 1, 4);
1191                 g.fillRect(2, 2, 1, 2);
1192                 g.fillRect(3, 2, 1, 1);
1193                 g.fillRect(4, 1, 4, 1);
1194             }
1195             else if (rollover) {
1196                 g.setColor(MetalLookAndFeel.getPrimaryControl());
1197                 g.fillRect(4, 1, 4, 2);
1198                 g.fillRect(8, 2, 2, 2);
1199                 g.fillRect(9, 4, 2, 4);
1200                 g.fillRect(8, 8, 2, 2);
1201                 g.fillRect(4, 9, 4, 2);
1202                 g.fillRect(2, 8, 2, 2);
1203                 g.fillRect(1, 4, 2, 4);
1204                 g.fillRect(2, 2, 2, 2);
1205             }
1206 
1207             // selected dot
1208             if (model.isSelected()) {
1209                 if (enabled) {
1210                     g.setColor(MetalLookAndFeel.getControlInfo());
1211                 } else {
1212                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
1213                 }
1214                 g.fillRect( 4, 4,  4, 4);
1215                 g.drawLine( 4, 3,  7, 3);
1216                 g.drawLine( 8, 4,  8, 7);
1217                 g.drawLine( 7, 8,  4, 8);
1218                 g.drawLine( 3, 7,  3, 4);
1219             }
1220 
1221             g.translate(-x, -y);
1222         }
1223 
1224         public void paintIcon(Component c, Graphics g, int x, int y) {
1225             if (MetalLookAndFeel.usingOcean()) {
1226                 paintOceanIcon(c, g, x, y);
1227                 return;
1228             }
1229             JRadioButton rb = (JRadioButton)c;
1230             ButtonModel model = rb.getModel();
1231             boolean drawDot = model.isSelected();
1232 
1233             Color background = c.getBackground();
1234             Color dotColor = c.getForeground();
1235             Color shadow = MetalLookAndFeel.getControlShadow();
1236             Color darkCircle = MetalLookAndFeel.getControlDarkShadow();
1237             Color whiteInnerLeftArc = MetalLookAndFeel.getControlHighlight();
1238             Color whiteOuterRightArc = MetalLookAndFeel.getControlHighlight();
1239             Color interiorColor = background;
1240 
1241             // Set up colors per RadioButtonModel condition
1242             if ( !model.isEnabled() ) {
1243                 whiteInnerLeftArc = whiteOuterRightArc = background;
1244                 darkCircle = dotColor = shadow;
1245             }
1246             else if (model.isPressed() && model.isArmed() ) {
1247                 whiteInnerLeftArc = interiorColor = shadow;
1248             }
1249 
1250             g.translate(x, y);
1251 
1252             // fill interior
1253             g.setColor(interiorColor);
1254             g.fillRect(2,2, 9,9);
1255 
1256             // draw Dark Circle (start at top, go clockwise)
1257             g.setColor(darkCircle);
1258             g.drawLine( 4, 0,  7, 0);
1259             g.drawLine( 8, 1,  9, 1);
1260             g.drawLine(10, 2, 10, 3);
1261             g.drawLine(11, 4, 11, 7);
1262             g.drawLine(10, 8, 10, 9);
1263             g.drawLine( 9,10,  8,10);
1264             g.drawLine( 7,11,  4,11);
1265             g.drawLine( 3,10,  2,10);
1266             g.drawLine( 1, 9,  1, 8);
1267             g.drawLine( 0, 7,  0, 4);
1268             g.drawLine( 1, 3,  1, 2);
1269             g.drawLine( 2, 1,  3, 1);
1270 
1271             // draw Inner Left (usually) White Arc
1272             //  start at lower left corner, go clockwise
1273             g.setColor(whiteInnerLeftArc);
1274             g.drawLine( 2, 9,  2, 8);
1275             g.drawLine( 1, 7,  1, 4);
1276             g.drawLine( 2, 2,  2, 3);
1277             g.drawLine( 2, 2,  3, 2);
1278             g.drawLine( 4, 1,  7, 1);
1279             g.drawLine( 8, 2,  9, 2);
1280             // draw Outer Right White Arc
1281             //  start at upper right corner, go clockwise
1282             g.setColor(whiteOuterRightArc);
1283             g.drawLine(10, 1, 10, 1);
1284             g.drawLine(11, 2, 11, 3);
1285             g.drawLine(12, 4, 12, 7);
1286             g.drawLine(11, 8, 11, 9);
1287             g.drawLine(10,10, 10,10);
1288             g.drawLine( 9,11,  8,11);
1289             g.drawLine( 7,12,  4,12);
1290             g.drawLine( 3,11,  2,11);
1291 
1292             // selected dot
1293             if ( drawDot ) {
1294                 g.setColor(dotColor);
1295                 g.fillRect( 4, 4,  4, 4);
1296                 g.drawLine( 4, 3,  7, 3);
1297                 g.drawLine( 8, 4,  8, 7);
1298                 g.drawLine( 7, 8,  4, 8);
1299                 g.drawLine( 3, 7,  3, 4);
1300             }
1301 
1302             g.translate(-x, -y);
1303         }
1304 
1305         public int getIconWidth() {
1306             return 13;
1307         }
1308 
1309         public int getIconHeight() {
1310             return 13;
1311         }
1312     }  // End class RadioButtonIcon
1313 
1314     // Tree Computer Icon code
1315     private static class TreeComputerIcon implements Icon, UIResource, Serializable {
1316         public void paintIcon(Component c, Graphics g, int x, int y) {
1317             g.translate(x, y);
1318 
1319             // Fill glass portion of monitor
1320             g.setColor(MetalLookAndFeel.getPrimaryControl());
1321             g.fillRect(5,4, 6,4);
1322 
1323             // Draw outside edge of monitor
1324             g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
1325             g.drawLine( 2,2,  2,8); // left
1326             g.drawLine(13,2, 13,8); // right
1327             g.drawLine( 3,1, 12,1); // top
1328             g.drawLine(12,9, 12,9); // bottom right base
1329             g.drawLine( 3,9,  3,9); // bottom left base
1330             // Draw the edge of the glass
1331             g.drawLine( 4,4,  4,7); // left
1332             g.drawLine( 5,3, 10,3); // top
1333             g.drawLine(11,4, 11,7); // right
1334             g.drawLine( 5,8, 10,8); // bottom
1335             // Draw the edge of the CPU
1336             g.drawLine( 1,10, 14,10); // top
1337             g.drawLine(14,10, 14,14); // right
1338             g.drawLine( 1,14, 14,14); // bottom
1339             g.drawLine( 1,10,  1,14); // left
1340 
1341             // Draw the disk drives
1342             g.setColor(MetalLookAndFeel.getControlDarkShadow());
1343             g.drawLine( 6,12,  8,12); // left
1344             g.drawLine(10,12, 12,12); // right
1345 
1346             g.translate(-x, -y);
1347         }
1348 
1349         public int getIconWidth() {
1350             return 16;
1351         }
1352 
1353         public int getIconHeight() {
1354             return 16;
1355         }
1356     }  // End class TreeComputerIcon
1357 
1358     // Tree HardDrive Icon code
1359     private static class TreeHardDriveIcon implements Icon, UIResource, Serializable {
1360         public void paintIcon(Component c, Graphics g, int x, int y) {
1361             g.translate(x, y);
1362 
1363             // Draw edges of the disks
1364             g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
1365             //     top disk
1366             g.drawLine(1,4, 1,5); // left
1367             g.drawLine(2,3, 3,3);
1368             g.drawLine(4,2, 11,2); // top
1369             g.drawLine(12,3, 13,3);
1370             g.drawLine(14,4, 14,5); // right
1371             g.drawLine(12,6, 13,6);
1372             g.drawLine(4,7, 11,7); // bottom
1373             g.drawLine(2,6, 3,6);
1374             //     middle disk
1375             g.drawLine(1,7, 1,8); // left
1376             g.drawLine(2,9, 3,9);
1377             g.drawLine(4,10, 11,10); // bottom
1378             g.drawLine(12,9, 13,9);
1379             g.drawLine(14,7, 14, 8); // right
1380             //     bottom disk
1381             g.drawLine(1,10, 1,11); // left
1382             g.drawLine(2,12, 3,12);
1383             g.drawLine(4,13, 11,13); // bottom
1384             g.drawLine(12,12, 13,12);
1385             g.drawLine(14,10, 14,11); // right
1386 
1387             // Draw the down right shadows
1388             g.setColor(MetalLookAndFeel.getControlShadow());
1389             //     top disk
1390             g.drawLine(7,6, 7,6);
1391             g.drawLine(9,6, 9,6);
1392             g.drawLine(10,5, 10,5);
1393             g.drawLine(11,6, 11,6);
1394             g.drawLine(12,5, 13,5);
1395             g.drawLine(13,4, 13,4);
1396             //     middle disk
1397             g.drawLine(7,9, 7,9);
1398             g.drawLine(9,9, 9,9);
1399             g.drawLine(10,8, 10,8);
1400             g.drawLine(11,9, 11,9);
1401             g.drawLine(12,8, 13,8);
1402             g.drawLine(13,7, 13,7);
1403             //     bottom disk
1404             g.drawLine(7,12, 7,12);
1405             g.drawLine(9,12, 9,12);
1406             g.drawLine(10,11, 10,11);
1407             g.drawLine(11,12, 11,12);
1408             g.drawLine(12,11, 13,11);
1409             g.drawLine(13,10, 13,10);
1410 
1411             // Draw the up left highlight
1412             g.setColor(MetalLookAndFeel.getControlHighlight());
1413             //     top disk
1414             g.drawLine(4,3, 5,3);
1415             g.drawLine(7,3, 9,3);
1416             g.drawLine(11,3, 11,3);
1417             g.drawLine(2,4, 6,4);
1418             g.drawLine(8,4, 8,4);
1419             g.drawLine(2,5, 3,5);
1420             g.drawLine(4,6, 4,6);
1421             //     middle disk
1422             g.drawLine(2,7, 3,7);
1423             g.drawLine(2,8, 3,8);
1424             g.drawLine(4,9, 4,9);
1425             //     bottom disk
1426             g.drawLine(2,10, 3,10);
1427             g.drawLine(2,11, 3,11);
1428             g.drawLine(4,12, 4,12);
1429 
1430             g.translate(-x, -y);
1431         }
1432 
1433         public int getIconWidth() {
1434             return 16;
1435         }
1436 
1437         public int getIconHeight() {
1438             return 16;
1439         }
1440     }  // End class TreeHardDriveIcon
1441 
1442     // Tree FloppyDrive Icon code
1443     private static class TreeFloppyDriveIcon implements Icon, UIResource, Serializable {
1444         public void paintIcon(Component c, Graphics g, int x, int y) {
1445             g.translate(x, y);
1446 
1447             // Fill body of floppy
1448             g.setColor(MetalLookAndFeel.getPrimaryControl());
1449             g.fillRect(2,2, 12,12);
1450 
1451             // Draw outside edge of floppy
1452             g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
1453             g.drawLine( 1, 1, 13, 1); // top
1454             g.drawLine(14, 2, 14,14); // right
1455             g.drawLine( 1,14, 14,14); // bottom
1456             g.drawLine( 1, 1,  1,14); // left
1457 
1458             // Draw grey-ish highlights
1459             g.setColor(MetalLookAndFeel.getControlDarkShadow());
1460             g.fillRect(5,2, 6,5); // metal disk protector part
1461             g.drawLine(4,8, 11,8); // top of label
1462             g.drawLine(3,9, 3,13); // left of label
1463             g.drawLine(12,9, 12,13); // right of label
1464 
1465             // Draw label and exposed disk
1466             g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
1467             g.fillRect(8,3, 2,3); // exposed disk
1468             g.fillRect(4,9, 8,5); // label
1469 
1470             // Draw text on label
1471             g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
1472             g.drawLine(5,10, 9,10);
1473             g.drawLine(5,12, 8,12);
1474 
1475             g.translate(-x, -y);
1476         }
1477 
1478         public int getIconWidth() {
1479             return 16;
1480         }
1481 
1482         public int getIconHeight() {
1483             return 16;
1484         }
1485     }  // End class TreeFloppyDriveIcon
1486 
1487 
1488     static private final Dimension folderIcon16Size = new Dimension( 16, 16 );
1489 
1490     /**
1491      * Utility class for caching icon images.  This is necessary because
1492      * we need a new image whenever we are rendering into a new
1493      * GraphicsConfiguration, but we do not want to keep recreating icon
1494      * images for GC's that we have already seen (for example,
1495      * dragging a window back and forth between monitors on a multimon
1496      * system, or drawing an icon to different Components that have different
1497      * GC's).
1498      * So now whenever we create a new icon image for a given GC, we
1499      * cache that image with the GC for later retrieval.
1500      */
1501     static class ImageCacher {
1502 
1503         // PENDING: Replace this class with CachedPainter.
1504 
1505         Vector images = new Vector(1, 1);
1506         ImageGcPair currentImageGcPair;
1507 
1508         class ImageGcPair {
1509             Image image;
1510             GraphicsConfiguration gc;
1511             ImageGcPair(Image image, GraphicsConfiguration gc) {
1512                 this.image = image;
1513                 this.gc = gc;
1514             }
1515 
1516             boolean hasSameConfiguration(GraphicsConfiguration newGC) {
1517                 if (((newGC != null) && (newGC.equals(gc))) ||
1518                     ((newGC == null) && (gc == null)))
1519                 {
1520                     return true;
1521                 }
1522                 return false;
1523             }
1524 
1525         }
1526 
1527         Image getImage(GraphicsConfiguration newGC) {
1528             if ((currentImageGcPair == null) ||
1529                 !(currentImageGcPair.hasSameConfiguration(newGC)))
1530             {
1531                 Enumeration elements = images.elements();
1532                 while (elements.hasMoreElements()) {
1533                     ImageGcPair imgGcPair = (ImageGcPair)elements.nextElement();
1534                     if (imgGcPair.hasSameConfiguration(newGC)) {
1535                         currentImageGcPair = imgGcPair;
1536                         return imgGcPair.image;
1537                     }
1538                 }
1539                 return null;
1540             }
1541             return currentImageGcPair.image;
1542         }
1543 
1544         void cacheImage(Image image, GraphicsConfiguration gc) {
1545             ImageGcPair imgGcPair = new ImageGcPair(image, gc);
1546             images.addElement(imgGcPair);
1547             currentImageGcPair = imgGcPair;
1548         }
1549 
1550     }
1551 
1552     /**
1553      * <p>
1554      * <strong>Warning:</strong>
1555      * Serialized objects of this class will not be compatible with
1556      * future Swing releases. The current serialization support is
1557      * appropriate for short term storage or RMI between applications running
1558      * the same version of Swing.  As of 1.4, support for long term storage
1559      * of all JavaBeans<sup><font size="-2">TM</font></sup>
1560      * has been added to the <code>java.beans</code> package.
1561      * Please see {@link java.beans.XMLEncoder}.
1562      */
1563     public static class FolderIcon16 implements Icon, Serializable {
1564 
1565         ImageCacher imageCacher;
1566 
1567         public void paintIcon(Component c, Graphics g, int x, int y) {
1568             GraphicsConfiguration gc = c.getGraphicsConfiguration();
1569             if (imageCacher == null) {
1570                 imageCacher = new ImageCacher();
1571             }
1572             Image image = imageCacher.getImage(gc);
1573             if (image == null) {
1574                 if (gc != null) {
1575                     image = gc.createCompatibleImage(getIconWidth(),
1576                                                      getIconHeight(),
1577                                                      Transparency.BITMASK);
1578                 } else {
1579                     image = new BufferedImage(getIconWidth(),
1580                                               getIconHeight(),
1581                                               BufferedImage.TYPE_INT_ARGB);
1582                 }
1583                 Graphics imageG = image.getGraphics();
1584                 paintMe(c,imageG);
1585                 imageG.dispose();
1586                 imageCacher.cacheImage(image, gc);
1587             }
1588             g.drawImage(image, x, y+getShift(), null);
1589         }
1590 
1591 
1592         private void paintMe(Component c, Graphics g) {
1593 
1594             int right = folderIcon16Size.width - 1;
1595             int bottom = folderIcon16Size.height - 1;
1596 
1597             // Draw tab top
1598             g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
1599             g.drawLine( right - 5, 3, right, 3 );
1600             g.drawLine( right - 6, 4, right, 4 );
1601 
1602             // Draw folder front
1603             g.setColor( MetalLookAndFeel.getPrimaryControl() );
1604             g.fillRect( 2, 7, 13, 8 );
1605 
1606             // Draw tab bottom
1607             g.setColor( MetalLookAndFeel.getPrimaryControlShadow() );
1608             g.drawLine( right - 6, 5, right - 1, 5 );
1609 
1610             // Draw outline
1611             g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
1612             g.drawLine( 0, 6, 0, bottom );            // left side
1613             g.drawLine( 1, 5, right - 7, 5 );         // first part of top
1614             g.drawLine( right - 6, 6, right - 1, 6 ); // second part of top
1615             g.drawLine( right, 5, right, bottom );    // right side
1616             g.drawLine( 0, bottom, right, bottom );   // bottom
1617 
1618             // Draw highlight
1619             g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
1620             g.drawLine( 1, 6, 1, bottom - 1 );
1621             g.drawLine( 1, 6, right - 7, 6 );
1622             g.drawLine( right - 6, 7, right - 1, 7 );
1623 
1624         }
1625 
1626         public int getShift() { return 0; }
1627         public int getAdditionalHeight() { return 0; }
1628 
1629         public int getIconWidth() { return folderIcon16Size.width; }
1630         public int getIconHeight() { return folderIcon16Size.height + getAdditionalHeight(); }
1631     }
1632 
1633 
1634     /**
1635      * <p>
1636      * <strong>Warning:</strong>
1637      * Serialized objects of this class will not be compatible with
1638      * future Swing releases. The current serialization support is
1639      * appropriate for short term storage or RMI between applications running
1640      * the same version of Swing.  As of 1.4, support for long term storage
1641      * of all JavaBeans<sup><font size="-2">TM</font></sup>
1642      * has been added to the <code>java.beans</code> package.
1643      * Please see {@link java.beans.XMLEncoder}.
1644      */
1645     public static class TreeFolderIcon extends FolderIcon16 {
1646         public int getShift() { return -1; }
1647         public int getAdditionalHeight() { return 2; }
1648     }
1649 
1650 
1651     static private final Dimension fileIcon16Size = new Dimension( 16, 16 );
1652 
1653     /**
1654      * <p>
1655      * <strong>Warning:</strong>
1656      * Serialized objects of this class will not be compatible with
1657      * future Swing releases. The current serialization support is
1658      * appropriate for short term storage or RMI between applications running
1659      * the same version of Swing.  As of 1.4, support for long term storage
1660      * of all JavaBeans<sup><font size="-2">TM</font></sup>
1661      * has been added to the <code>java.beans</code> package.
1662      * Please see {@link java.beans.XMLEncoder}.
1663      */
1664     public static class FileIcon16 implements Icon, Serializable {
1665 
1666         ImageCacher imageCacher;
1667 
1668         public void paintIcon(Component c, Graphics g, int x, int y) {
1669             GraphicsConfiguration gc = c.getGraphicsConfiguration();
1670             if (imageCacher == null) {
1671                 imageCacher = new ImageCacher();
1672             }
1673             Image image = imageCacher.getImage(gc);
1674             if (image == null) {
1675                 if (gc != null) {
1676                     image = gc.createCompatibleImage(getIconWidth(),
1677                                                      getIconHeight(),
1678                                                      Transparency.BITMASK);
1679                 } else {
1680                     image = new BufferedImage(getIconWidth(),
1681                                               getIconHeight(),
1682                                               BufferedImage.TYPE_INT_ARGB);
1683                 }
1684                 Graphics imageG = image.getGraphics();
1685                 paintMe(c,imageG);
1686                 imageG.dispose();
1687                 imageCacher.cacheImage(image, gc);
1688             }
1689             g.drawImage(image, x, y+getShift(), null);
1690         }
1691 
1692         private void paintMe(Component c, Graphics g) {
1693 
1694                 int right = fileIcon16Size.width - 1;
1695                 int bottom = fileIcon16Size.height - 1;
1696 
1697                 // Draw fill
1698                 g.setColor( MetalLookAndFeel.getWindowBackground() );
1699                 g.fillRect( 4, 2, 9, 12 );
1700 
1701                 // Draw frame
1702                 g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
1703                 g.drawLine( 2, 0, 2, bottom );                 // left
1704                 g.drawLine( 2, 0, right - 4, 0 );              // top
1705                 g.drawLine( 2, bottom, right - 1, bottom );    // bottom
1706                 g.drawLine( right - 1, 6, right - 1, bottom ); // right
1707                 g.drawLine( right - 6, 2, right - 2, 6 );      // slant 1
1708                 g.drawLine( right - 5, 1, right - 4, 1 );      // part of slant 2
1709                 g.drawLine( right - 3, 2, right - 3, 3 );      // part of slant 2
1710                 g.drawLine( right - 2, 4, right - 2, 5 );      // part of slant 2
1711 
1712                 // Draw highlight
1713                 g.setColor( MetalLookAndFeel.getPrimaryControl() );
1714                 g.drawLine( 3, 1, 3, bottom - 1 );                  // left
1715                 g.drawLine( 3, 1, right - 6, 1 );                   // top
1716                 g.drawLine( right - 2, 7, right - 2, bottom - 1 );  // right
1717                 g.drawLine( right - 5, 2, right - 3, 4 );           // slant
1718                 g.drawLine( 3, bottom - 1, right - 2, bottom - 1 ); // bottom
1719 
1720         }
1721 
1722         public int getShift() { return 0; }
1723         public int getAdditionalHeight() { return 0; }
1724 
1725         public int getIconWidth() { return fileIcon16Size.width; }
1726         public int getIconHeight() { return fileIcon16Size.height + getAdditionalHeight(); }
1727     }
1728 
1729 
1730     public static class TreeLeafIcon extends FileIcon16 {
1731         public int getShift() { return 2; }
1732         public int getAdditionalHeight() { return 4; }
1733     }
1734 
1735 
1736     static private final Dimension treeControlSize = new Dimension( 18, 18 );
1737 
1738     /**
1739      * <p>
1740      * <strong>Warning:</strong>
1741      * Serialized objects of this class will not be compatible with
1742      * future Swing releases. The current serialization support is
1743      * appropriate for short term storage or RMI between applications running
1744      * the same version of Swing.  As of 1.4, support for long term storage
1745      * of all JavaBeans<sup><font size="-2">TM</font></sup>
1746      * has been added to the <code>java.beans</code> package.
1747      * Please see {@link java.beans.XMLEncoder}.
1748      */
1749     public static class TreeControlIcon implements Icon, Serializable {
1750         // This data member should not have been exposed.  It's called
1751         // isLight, but now it really means isCollapsed.  Since we can't change
1752         // any APIs... that's life.
1753         protected boolean isLight;
1754 
1755 
1756         public TreeControlIcon( boolean isCollapsed ) {
1757             isLight = isCollapsed;
1758         }
1759 
1760         ImageCacher imageCacher;
1761 
1762         transient boolean cachedOrientation = true;
1763 
1764         public void paintIcon(Component c, Graphics g, int x, int y) {
1765 
1766             GraphicsConfiguration gc = c.getGraphicsConfiguration();
1767 
1768             if (imageCacher == null) {
1769                 imageCacher = new ImageCacher();
1770             }
1771             Image image = imageCacher.getImage(gc);
1772 
1773             if (image == null || cachedOrientation != MetalUtils.isLeftToRight(c)) {
1774                 cachedOrientation = MetalUtils.isLeftToRight(c);
1775                 if (gc != null) {
1776                     image = gc.createCompatibleImage(getIconWidth(),
1777                                                      getIconHeight(),
1778                                                      Transparency.BITMASK);
1779                 } else {
1780                     image = new BufferedImage(getIconWidth(),
1781                                               getIconHeight(),
1782                                               BufferedImage.TYPE_INT_ARGB);
1783                 }
1784                 Graphics imageG = image.getGraphics();
1785                 paintMe(c,imageG,x,y);
1786                 imageG.dispose();
1787                 imageCacher.cacheImage(image, gc);
1788 
1789             }
1790 
1791             if (MetalUtils.isLeftToRight(c)) {
1792                 if (isLight) {    // isCollapsed
1793                     g.drawImage(image, x+5, y+3, x+18, y+13,
1794                                        4,3, 17, 13, null);
1795                 }
1796                 else {
1797                     g.drawImage(image, x+5, y+3, x+18, y+17,
1798                                        4,3, 17, 17, null);
1799                 }
1800             }
1801             else {
1802                 if (isLight) {    // isCollapsed
1803                     g.drawImage(image, x+3, y+3, x+16, y+13,
1804                                        4, 3, 17, 13, null);
1805                 }
1806                 else {
1807                     g.drawImage(image, x+3, y+3, x+16, y+17,
1808                                        4, 3, 17, 17, null);
1809                 }
1810             }
1811         }
1812 
1813         public void paintMe(Component c, Graphics g, int x, int y) {
1814 
1815             g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
1816 
1817             int xoff = (MetalUtils.isLeftToRight(c)) ? 0 : 4;
1818 
1819             // Draw circle
1820             g.drawLine( xoff + 4, 6, xoff + 4, 9 );     // left
1821             g.drawLine( xoff + 5, 5, xoff + 5, 5 );     // top left dot
1822             g.drawLine( xoff + 6, 4, xoff + 9, 4 );     // top
1823             g.drawLine( xoff + 10, 5, xoff + 10, 5 );   // top right dot
1824             g.drawLine( xoff + 11, 6, xoff + 11, 9 );   // right
1825             g.drawLine( xoff + 10, 10, xoff + 10, 10 ); // botom right dot
1826             g.drawLine( xoff + 6, 11, xoff + 9, 11 );   // bottom
1827             g.drawLine( xoff + 5, 10, xoff + 5, 10 );   // bottom left dot
1828 
1829             // Draw Center Dot
1830             g.drawLine( xoff + 7, 7, xoff + 8, 7 );
1831             g.drawLine( xoff + 7, 8, xoff + 8, 8 );
1832 
1833             // Draw Handle
1834             if ( isLight ) {    // isCollapsed
1835                 if( MetalUtils.isLeftToRight(c) ) {
1836                     g.drawLine( 12, 7, 15, 7 );
1837                     g.drawLine( 12, 8, 15, 8 );
1838                     //  g.setColor( c.getBackground() );
1839                     //  g.drawLine( 16, 7, 16, 8 );
1840                 }
1841                 else {
1842                     g.drawLine(4, 7, 7, 7);
1843                     g.drawLine(4, 8, 7, 8);
1844                 }
1845             }
1846             else {
1847                 g.drawLine( xoff + 7, 12, xoff + 7, 15 );
1848                 g.drawLine( xoff + 8, 12, xoff + 8, 15 );
1849                 //      g.setColor( c.getBackground() );
1850                 //      g.drawLine( xoff + 7, 16, xoff + 8, 16 );
1851             }
1852 
1853             // Draw Fill
1854             g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
1855             g.drawLine( xoff + 5, 6, xoff + 5, 9 );      // left shadow
1856             g.drawLine( xoff + 6, 5, xoff + 9, 5 );      // top shadow
1857 
1858             g.setColor( MetalLookAndFeel.getPrimaryControlShadow() );
1859             g.drawLine( xoff + 6, 6, xoff + 6, 6 );      // top left fill
1860             g.drawLine( xoff + 9, 6, xoff + 9, 6 );      // top right fill
1861             g.drawLine( xoff + 6, 9, xoff + 6, 9 );      // bottom left fill
1862             g.drawLine( xoff + 10, 6, xoff + 10, 9 );    // right fill
1863             g.drawLine( xoff + 6, 10, xoff + 9, 10 );    // bottom fill
1864 
1865             g.setColor( MetalLookAndFeel.getPrimaryControl() );
1866             g.drawLine( xoff + 6, 7, xoff + 6, 8 );      // left highlight
1867             g.drawLine( xoff + 7, 6, xoff + 8, 6 );      // top highlight
1868             g.drawLine( xoff + 9, 7, xoff + 9, 7 );      // right highlight
1869             g.drawLine( xoff + 7, 9, xoff + 7, 9 );      // bottom highlight
1870 
1871             g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
1872             g.drawLine( xoff + 8, 9, xoff + 9, 9 );
1873             g.drawLine( xoff + 9, 8, xoff + 9, 8 );
1874         }
1875 
1876         public int getIconWidth() { return treeControlSize.width; }
1877         public int getIconHeight() { return treeControlSize.height; }
1878     }
1879 
1880   //
1881   // Menu Icons
1882   //
1883 
1884     static private final Dimension menuArrowIconSize = new Dimension( 4, 8 );
1885     static private final Dimension menuCheckIconSize = new Dimension( 10, 10 );
1886     static private final int xOff = 4;
1887 
1888     private static class MenuArrowIcon implements Icon, UIResource, Serializable
1889     {
1890         public void paintIcon( Component c, Graphics g, int x, int y )
1891         {
1892             JMenuItem b = (JMenuItem) c;
1893             ButtonModel model = b.getModel();
1894 
1895             g.translate( x, y );
1896 
1897             if ( !model.isEnabled() )
1898             {
1899                 g.setColor( MetalLookAndFeel.getMenuDisabledForeground() );
1900             }
1901             else
1902             {
1903                 if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
1904                 {
1905                     g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
1906                 }
1907                 else
1908                 {
1909                     g.setColor( b.getForeground() );
1910                 }
1911             }
1912             if( MetalUtils.isLeftToRight(b) ) {
1913                 g.drawLine( 0, 0, 0, 7 );
1914                 g.drawLine( 1, 1, 1, 6 );
1915                 g.drawLine( 2, 2, 2, 5 );
1916                 g.drawLine( 3, 3, 3, 4 );
1917             } else {
1918                 g.drawLine( 4, 0, 4, 7 );
1919                 g.drawLine( 3, 1, 3, 6 );
1920                 g.drawLine( 2, 2, 2, 5 );
1921                 g.drawLine( 1, 3, 1, 4 );
1922             }
1923 
1924             g.translate( -x, -y );
1925         }
1926 
1927         public int getIconWidth() { return menuArrowIconSize.width; }
1928 
1929         public int getIconHeight() { return menuArrowIconSize.height; }
1930 
1931     } // End class MenuArrowIcon
1932 
1933     private static class MenuItemArrowIcon implements Icon, UIResource, Serializable
1934     {
1935         public void paintIcon( Component c, Graphics g, int x, int y )
1936         {
1937         }
1938 
1939         public int getIconWidth() { return menuArrowIconSize.width; }
1940 
1941         public int getIconHeight() { return menuArrowIconSize.height; }
1942 
1943     } // End class MenuItemArrowIcon
1944 
1945     private static class CheckBoxMenuItemIcon implements Icon, UIResource, Serializable
1946     {
1947         public void paintOceanIcon(Component c, Graphics g, int x, int y) {
1948             ButtonModel model = ((JMenuItem)c).getModel();
1949             boolean isSelected = model.isSelected();
1950             boolean isEnabled = model.isEnabled();
1951             boolean isPressed = model.isPressed();
1952             boolean isArmed = model.isArmed();
1953 
1954             g.translate(x, y);
1955             if (isEnabled) {
1956                 MetalUtils.drawGradient(c, g, "CheckBoxMenuItem.gradient",
1957                                         1, 1, 7, 7, true);
1958                 if (isPressed || isArmed) {
1959                     g.setColor(MetalLookAndFeel.getControlInfo());
1960                     g.drawLine( 0, 0, 8, 0 );
1961                     g.drawLine( 0, 0, 0, 8 );
1962                     g.drawLine( 8, 2, 8, 8 );
1963                     g.drawLine( 2, 8, 8, 8 );
1964 
1965                     g.setColor(MetalLookAndFeel.getPrimaryControl());
1966                     g.drawLine( 9, 1, 9, 9 );
1967                     g.drawLine( 1, 9, 9, 9 );
1968                 }
1969                 else {
1970                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
1971                     g.drawLine( 0, 0, 8, 0 );
1972                     g.drawLine( 0, 0, 0, 8 );
1973                     g.drawLine( 8, 2, 8, 8 );
1974                     g.drawLine( 2, 8, 8, 8 );
1975 
1976                     g.setColor(MetalLookAndFeel.getControlHighlight());
1977                     g.drawLine( 9, 1, 9, 9 );
1978                     g.drawLine( 1, 9, 9, 9 );
1979                 }
1980             }
1981             else {
1982                 g.setColor(MetalLookAndFeel.getMenuDisabledForeground());
1983                 g.drawRect( 0, 0, 8, 8 );
1984             }
1985             if (isSelected) {
1986                 if (isEnabled) {
1987                     if (isArmed || ( c instanceof JMenu && isSelected)) {
1988                         g.setColor(
1989                             MetalLookAndFeel.getMenuSelectedForeground() );
1990                     }
1991                     else {
1992                          g.setColor(MetalLookAndFeel.getControlInfo());
1993                     }
1994                 }
1995                 else {
1996                     g.setColor( MetalLookAndFeel.getMenuDisabledForeground());
1997                 }
1998 
1999                 g.drawLine( 2, 2, 2, 6 );
2000                 g.drawLine( 3, 2, 3, 6 );
2001                 g.drawLine( 4, 4, 8, 0 );
2002                 g.drawLine( 4, 5, 9, 0 );
2003             }
2004             g.translate( -x, -y );
2005         }
2006 
2007         public void paintIcon( Component c, Graphics g, int x, int y )
2008         {
2009             if (MetalLookAndFeel.usingOcean()) {
2010                 paintOceanIcon(c, g, x, y);
2011                 return;
2012             }
2013             JMenuItem b = (JMenuItem) c;
2014             ButtonModel model = b.getModel();
2015 
2016             boolean isSelected = model.isSelected();
2017             boolean isEnabled = model.isEnabled();
2018             boolean isPressed = model.isPressed();
2019             boolean isArmed = model.isArmed();
2020 
2021             g.translate( x, y );
2022 
2023             if ( isEnabled )
2024             {
2025                 if ( isPressed || isArmed )
2026                 {
2027                     g.setColor( MetalLookAndFeel.getControlInfo()  );
2028                     g.drawLine( 0, 0, 8, 0 );
2029                     g.drawLine( 0, 0, 0, 8 );
2030                     g.drawLine( 8, 2, 8, 8 );
2031                     g.drawLine( 2, 8, 8, 8 );
2032 
2033                     g.setColor( MetalLookAndFeel.getPrimaryControl()  );
2034                     g.drawLine( 1, 1, 7, 1 );
2035                     g.drawLine( 1, 1, 1, 7 );
2036                     g.drawLine( 9, 1, 9, 9 );
2037                     g.drawLine( 1, 9, 9, 9 );
2038                 }
2039                 else
2040                 {
2041                     g.setColor( MetalLookAndFeel.getControlDarkShadow()  );
2042                     g.drawLine( 0, 0, 8, 0 );
2043                     g.drawLine( 0, 0, 0, 8 );
2044                     g.drawLine( 8, 2, 8, 8 );
2045                     g.drawLine( 2, 8, 8, 8 );
2046 
2047                     g.setColor( MetalLookAndFeel.getControlHighlight()  );
2048                     g.drawLine( 1, 1, 7, 1 );
2049                     g.drawLine( 1, 1, 1, 7 );
2050                     g.drawLine( 9, 1, 9, 9 );
2051                     g.drawLine( 1, 9, 9, 9 );
2052                 }
2053             }
2054             else
2055             {
2056                 g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2057                 g.drawRect( 0, 0, 8, 8 );
2058             }
2059 
2060             if ( isSelected )
2061             {
2062                 if ( isEnabled )
2063                 {
2064                     if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
2065                     {
2066                         g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
2067                     }
2068                     else
2069                     {
2070                         g.setColor( b.getForeground() );
2071                     }
2072                 }
2073                 else
2074                 {
2075                     g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2076                 }
2077 
2078                 g.drawLine( 2, 2, 2, 6 );
2079                 g.drawLine( 3, 2, 3, 6 );
2080                 g.drawLine( 4, 4, 8, 0 );
2081                 g.drawLine( 4, 5, 9, 0 );
2082             }
2083 
2084             g.translate( -x, -y );
2085         }
2086 
2087         public int getIconWidth() { return menuCheckIconSize.width; }
2088 
2089         public int getIconHeight() { return menuCheckIconSize.height; }
2090 
2091     }  // End class CheckBoxMenuItemIcon
2092 
2093     private static class RadioButtonMenuItemIcon implements Icon, UIResource, Serializable
2094     {
2095         public void paintOceanIcon(Component c, Graphics g, int x, int y) {
2096             ButtonModel model = ((JMenuItem)c).getModel();
2097             boolean isSelected = model.isSelected();
2098             boolean isEnabled = model.isEnabled();
2099             boolean isPressed = model.isPressed();
2100             boolean isArmed = model.isArmed();
2101 
2102             g.translate( x, y );
2103 
2104             if (isEnabled) {
2105                 MetalUtils.drawGradient(c, g, "RadioButtonMenuItem.gradient",
2106                                         1, 1, 7, 7, true);
2107                 if (isPressed || isArmed) {
2108                     g.setColor(MetalLookAndFeel.getPrimaryControl());
2109                 }
2110                 else {
2111                     g.setColor(MetalLookAndFeel.getControlHighlight());
2112                 }
2113                 g.drawLine( 2, 9, 7, 9 );
2114                 g.drawLine( 9, 2, 9, 7 );
2115                 g.drawLine( 8, 8, 8, 8 );
2116 
2117                 if (isPressed || isArmed) {
2118                     g.setColor(MetalLookAndFeel.getControlInfo());
2119                 }
2120                 else {
2121                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
2122                 }
2123             }
2124             else {
2125                 g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2126             }
2127             g.drawLine( 2, 0, 6, 0 );
2128             g.drawLine( 2, 8, 6, 8 );
2129             g.drawLine( 0, 2, 0, 6 );
2130             g.drawLine( 8, 2, 8, 6 );
2131             g.drawLine( 1, 1, 1, 1 );
2132             g.drawLine( 7, 1, 7, 1 );
2133             g.drawLine( 1, 7, 1, 7 );
2134             g.drawLine( 7, 7, 7, 7 );
2135 
2136             if (isSelected) {
2137                 if (isEnabled) {
2138                     if (isArmed || (c instanceof JMenu && model.isSelected())){
2139                         g.setColor(MetalLookAndFeel.
2140                                    getMenuSelectedForeground() );
2141                     }
2142                     else {
2143                         g.setColor(MetalLookAndFeel.getControlInfo());
2144                     }
2145                 }
2146                 else {
2147                     g.setColor(MetalLookAndFeel.getMenuDisabledForeground());
2148                 }
2149                 g.drawLine( 3, 2, 5, 2 );
2150                 g.drawLine( 2, 3, 6, 3 );
2151                 g.drawLine( 2, 4, 6, 4 );
2152                 g.drawLine( 2, 5, 6, 5 );
2153                 g.drawLine( 3, 6, 5, 6 );
2154             }
2155 
2156             g.translate( -x, -y );
2157         }
2158 
2159         public void paintIcon( Component c, Graphics g, int x, int y )
2160         {
2161             if (MetalLookAndFeel.usingOcean()) {
2162                 paintOceanIcon(c, g, x, y);
2163                 return;
2164             }
2165             JMenuItem b = (JMenuItem) c;
2166             ButtonModel model = b.getModel();
2167 
2168             boolean isSelected = model.isSelected();
2169             boolean isEnabled = model.isEnabled();
2170             boolean isPressed = model.isPressed();
2171             boolean isArmed = model.isArmed();
2172 
2173             g.translate( x, y );
2174 
2175             if ( isEnabled )
2176             {
2177                 if ( isPressed || isArmed )
2178                 {
2179                     g.setColor( MetalLookAndFeel.getPrimaryControl()  );
2180                     g.drawLine( 3, 1, 8, 1 );
2181                     g.drawLine( 2, 9, 7, 9 );
2182                     g.drawLine( 1, 3, 1, 8 );
2183                     g.drawLine( 9, 2, 9, 7 );
2184                     g.drawLine( 2, 2, 2, 2 );
2185                     g.drawLine( 8, 8, 8, 8 );
2186 
2187                     g.setColor( MetalLookAndFeel.getControlInfo()  );
2188                     g.drawLine( 2, 0, 6, 0 );
2189                     g.drawLine( 2, 8, 6, 8 );
2190                     g.drawLine( 0, 2, 0, 6 );
2191                     g.drawLine( 8, 2, 8, 6 );
2192                     g.drawLine( 1, 1, 1, 1 );
2193                     g.drawLine( 7, 1, 7, 1 );
2194                     g.drawLine( 1, 7, 1, 7 );
2195                     g.drawLine( 7, 7, 7, 7 );
2196                 }
2197                 else
2198                 {
2199                     g.setColor( MetalLookAndFeel.getControlHighlight()  );
2200                     g.drawLine( 3, 1, 8, 1 );
2201                     g.drawLine( 2, 9, 7, 9 );
2202                     g.drawLine( 1, 3, 1, 8 );
2203                     g.drawLine( 9, 2, 9, 7 );
2204                     g.drawLine( 2, 2, 2, 2 );
2205                     g.drawLine( 8, 8, 8, 8 );
2206 
2207                     g.setColor( MetalLookAndFeel.getControlDarkShadow()  );
2208                     g.drawLine( 2, 0, 6, 0 );
2209                     g.drawLine( 2, 8, 6, 8 );
2210                     g.drawLine( 0, 2, 0, 6 );
2211                     g.drawLine( 8, 2, 8, 6 );
2212                     g.drawLine( 1, 1, 1, 1 );
2213                     g.drawLine( 7, 1, 7, 1 );
2214                     g.drawLine( 1, 7, 1, 7 );
2215                     g.drawLine( 7, 7, 7, 7 );
2216                 }
2217             }
2218             else
2219             {
2220                 g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2221                 g.drawLine( 2, 0, 6, 0 );
2222                 g.drawLine( 2, 8, 6, 8 );
2223                 g.drawLine( 0, 2, 0, 6 );
2224                 g.drawLine( 8, 2, 8, 6 );
2225                 g.drawLine( 1, 1, 1, 1 );
2226                 g.drawLine( 7, 1, 7, 1 );
2227                 g.drawLine( 1, 7, 1, 7 );
2228                 g.drawLine( 7, 7, 7, 7 );
2229             }
2230 
2231             if ( isSelected )
2232             {
2233                 if ( isEnabled )
2234                 {
2235                     if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
2236                     {
2237                         g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
2238                     }
2239                     else
2240                     {
2241                         g.setColor( b.getForeground() );
2242                     }
2243                 }
2244                 else
2245                 {
2246                     g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2247                 }
2248 
2249                 g.drawLine( 3, 2, 5, 2 );
2250                 g.drawLine( 2, 3, 6, 3 );
2251                 g.drawLine( 2, 4, 6, 4 );
2252                 g.drawLine( 2, 5, 6, 5 );
2253                 g.drawLine( 3, 6, 5, 6 );
2254             }
2255 
2256             g.translate( -x, -y );
2257         }
2258 
2259         public int getIconWidth() { return menuCheckIconSize.width; }
2260 
2261         public int getIconHeight() { return menuCheckIconSize.height; }
2262 
2263     }  // End class RadioButtonMenuItemIcon
2264 
2265 private static class VerticalSliderThumbIcon implements Icon, Serializable, UIResource {
2266     protected static MetalBumps controlBumps;
2267     protected static MetalBumps primaryBumps;
2268 
2269     public VerticalSliderThumbIcon() {
2270         controlBumps = new MetalBumps( 6, 10,
2271                                 MetalLookAndFeel.getControlHighlight(),
2272                                 MetalLookAndFeel.getControlInfo(),
2273                                 MetalLookAndFeel.getControl() );
2274         primaryBumps = new MetalBumps( 6, 10,
2275                                 MetalLookAndFeel.getPrimaryControl(),
2276                                 MetalLookAndFeel.getPrimaryControlDarkShadow(),
2277                                 MetalLookAndFeel.getPrimaryControlShadow() );
2278     }
2279 
2280     public void paintIcon( Component c, Graphics g, int x, int y ) {
2281         JSlider slider = (JSlider)c;
2282 
2283         boolean leftToRight = MetalUtils.isLeftToRight(slider);
2284 
2285         g.translate( x, y );
2286 
2287         // Draw the frame
2288         if ( slider.hasFocus() ) {
2289             g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
2290         }
2291         else {
2292             g.setColor( slider.isEnabled() ? MetalLookAndFeel.getPrimaryControlInfo() :
2293                                              MetalLookAndFeel.getControlDarkShadow() );
2294         }
2295 
2296         if (leftToRight) {
2297             g.drawLine(  1,0  ,  8,0  ); // top
2298             g.drawLine(  0,1  ,  0,13 ); // left
2299             g.drawLine(  1,14 ,  8,14 ); // bottom
2300             g.drawLine(  9,1  , 15,7  ); // top slant
2301             g.drawLine(  9,13 , 15,7  ); // bottom slant
2302         }
2303         else {
2304             g.drawLine(  7,0  , 14,0  ); // top
2305             g.drawLine( 15,1  , 15,13 ); // right
2306             g.drawLine(  7,14 , 14,14 ); // bottom
2307             g.drawLine(  0,7  ,  6,1  ); // top slant
2308             g.drawLine(  0,7  ,  6,13 ); // bottom slant
2309         }
2310 
2311         // Fill in the background
2312         if ( slider.hasFocus() ) {
2313             g.setColor( c.getForeground() );
2314         }
2315         else {
2316             g.setColor( MetalLookAndFeel.getControl() );
2317         }
2318 
2319         if (leftToRight) {
2320             g.fillRect(  1,1 ,  8,13 );
2321 
2322             g.drawLine(  9,2 ,  9,12 );
2323             g.drawLine( 10,3 , 10,11 );
2324             g.drawLine( 11,4 , 11,10 );
2325             g.drawLine( 12,5 , 12,9 );
2326             g.drawLine( 13,6 , 13,8 );
2327             g.drawLine( 14,7 , 14,7 );
2328         }
2329         else {
2330             g.fillRect(  7,1,   8,13 );
2331 
2332             g.drawLine(  6,3 ,  6,12 );
2333             g.drawLine(  5,4 ,  5,11 );
2334             g.drawLine(  4,5 ,  4,10 );
2335             g.drawLine(  3,6 ,  3,9 );
2336             g.drawLine(  2,7 ,  2,8 );
2337         }
2338 
2339         // Draw the bumps
2340         int offset = (leftToRight) ? 2 : 8;
2341         if ( slider.isEnabled() ) {
2342             if ( slider.hasFocus() ) {
2343                 primaryBumps.paintIcon( c, g, offset, 2 );
2344             }
2345             else {
2346                 controlBumps.paintIcon( c, g, offset, 2 );
2347             }
2348         }
2349 
2350         // Draw the highlight
2351         if ( slider.isEnabled() ) {
2352             g.setColor( slider.hasFocus() ? MetalLookAndFeel.getPrimaryControl()
2353                         : MetalLookAndFeel.getControlHighlight() );
2354             if (leftToRight) {
2355                 g.drawLine( 1, 1, 8, 1 );
2356                 g.drawLine( 1, 1, 1, 13 );
2357             }
2358             else {
2359                 g.drawLine(  8,1  , 14,1  ); // top
2360                 g.drawLine(  1,7  ,  7,1  ); // top slant
2361             }
2362         }
2363 
2364         g.translate( -x, -y );
2365     }
2366 
2367     public int getIconWidth() {
2368         return 16;
2369     }
2370 
2371     public int getIconHeight() {
2372         return 15;
2373     }
2374 }
2375 
2376 private static class HorizontalSliderThumbIcon implements Icon, Serializable, UIResource {
2377     protected static MetalBumps controlBumps;
2378     protected static MetalBumps primaryBumps;
2379 
2380     public HorizontalSliderThumbIcon() {
2381         controlBumps = new MetalBumps( 10, 6,
2382                                 MetalLookAndFeel.getControlHighlight(),
2383                                 MetalLookAndFeel.getControlInfo(),
2384                                 MetalLookAndFeel.getControl() );
2385         primaryBumps = new MetalBumps( 10, 6,
2386                                 MetalLookAndFeel.getPrimaryControl(),
2387                                 MetalLookAndFeel.getPrimaryControlDarkShadow(),
2388                                 MetalLookAndFeel.getPrimaryControlShadow() );
2389     }
2390 
2391     public void paintIcon( Component c, Graphics g, int x, int y ) {
2392         JSlider slider = (JSlider)c;
2393 
2394         g.translate( x, y );
2395 
2396         // Draw the frame
2397         if ( slider.hasFocus() ) {
2398             g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
2399         }
2400         else {
2401             g.setColor( slider.isEnabled() ? MetalLookAndFeel.getPrimaryControlInfo() :
2402                                              MetalLookAndFeel.getControlDarkShadow() );
2403         }
2404 
2405         g.drawLine(  1,0  , 13,0 );  // top
2406         g.drawLine(  0,1  ,  0,8 );  // left
2407         g.drawLine( 14,1  , 14,8 );  // right
2408         g.drawLine(  1,9  ,  7,15 ); // left slant
2409         g.drawLine(  7,15 , 14,8 );  // right slant
2410 
2411         // Fill in the background
2412         if ( slider.hasFocus() ) {
2413             g.setColor( c.getForeground() );
2414         }
2415         else {
2416             g.setColor( MetalLookAndFeel.getControl() );
2417         }
2418         g.fillRect( 1,1, 13, 8 );
2419 
2420         g.drawLine( 2,9  , 12,9 );
2421         g.drawLine( 3,10 , 11,10 );
2422         g.drawLine( 4,11 , 10,11 );
2423         g.drawLine( 5,12 ,  9,12 );
2424         g.drawLine( 6,13 ,  8,13 );
2425         g.drawLine( 7,14 ,  7,14 );
2426 
2427         // Draw the bumps
2428         if ( slider.isEnabled() ) {
2429             if ( slider.hasFocus() ) {
2430                 primaryBumps.paintIcon( c, g, 2, 2 );
2431             }
2432             else {
2433                 controlBumps.paintIcon( c, g, 2, 2 );
2434             }
2435         }
2436 
2437         // Draw the highlight
2438         if ( slider.isEnabled() ) {
2439             g.setColor( slider.hasFocus() ? MetalLookAndFeel.getPrimaryControl()
2440                         : MetalLookAndFeel.getControlHighlight() );
2441             g.drawLine( 1, 1, 13, 1 );
2442             g.drawLine( 1, 1, 1, 8 );
2443         }
2444 
2445         g.translate( -x, -y );
2446     }
2447 
2448     public int getIconWidth() {
2449         return 15;
2450     }
2451 
2452     public int getIconHeight() {
2453         return 16;
2454     }
2455 }
2456 
2457     private static class OceanVerticalSliderThumbIcon extends CachedPainter
2458                               implements Icon, Serializable, UIResource {
2459         // Used for clipping when the orientation is left to right
2460         private static Polygon LTR_THUMB_SHAPE;
2461         // Used for clipping when the orientation is right to left
2462         private static Polygon RTL_THUMB_SHAPE;
2463 
2464         static {
2465             LTR_THUMB_SHAPE = new Polygon(new int[] { 0,  8, 15,  8,  0},
2466                                           new int[] { 0,  0,  7, 14, 14 }, 5);
2467             RTL_THUMB_SHAPE = new Polygon(new int[] { 15, 15,  7,  0,  7},
2468                                           new int[] {  0, 14, 14,  7,  0}, 5);
2469         }
2470 
2471         OceanVerticalSliderThumbIcon() {
2472             super(3);
2473         }
2474 
2475         public void paintIcon(Component c, Graphics g, int x, int y) {
2476             if (!(g instanceof Graphics2D)) {
2477                 return;
2478             }
2479             paint(c, g, x, y, getIconWidth(), getIconHeight(),
2480                   MetalUtils.isLeftToRight(c), c.hasFocus(), c.isEnabled(),
2481                   MetalLookAndFeel.getCurrentTheme());
2482         }
2483 
2484         protected void paintToImage(Component c, Image image, Graphics g2,
2485                                     int w, int h, Object[] args) {
2486             Graphics2D g = (Graphics2D)g2;
2487             boolean leftToRight = ((Boolean)args[0]).booleanValue();
2488             boolean hasFocus = ((Boolean)args[1]).booleanValue();
2489             boolean enabled = ((Boolean)args[2]).booleanValue();
2490 
2491             Rectangle clip = g.getClipBounds();
2492             if (leftToRight) {
2493                 g.clip(LTR_THUMB_SHAPE);
2494             }
2495             else {
2496                 g.clip(RTL_THUMB_SHAPE);
2497             }
2498             if (!enabled) {
2499                 g.setColor(MetalLookAndFeel.getControl());
2500                 g.fillRect(1, 1, 14, 14);
2501             }
2502             else if (hasFocus) {
2503                 MetalUtils.drawGradient(c, g, "Slider.focusGradient",
2504                                         1, 1, 14, 14, false);
2505             }
2506             else {
2507                 MetalUtils.drawGradient(c, g, "Slider.gradient",
2508                                         1, 1, 14, 14, false);
2509             }
2510             g.setClip(clip);
2511 
2512             // Draw the frame
2513             if (hasFocus) {
2514                 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
2515             }
2516             else {
2517                 g.setColor(enabled ? MetalLookAndFeel.getPrimaryControlInfo() :
2518                            MetalLookAndFeel.getControlDarkShadow());
2519             }
2520 
2521             if (leftToRight) {
2522                 g.drawLine(  1,0  ,  8,0  ); // top
2523                 g.drawLine(  0,1  ,  0,13 ); // left
2524                 g.drawLine(  1,14 ,  8,14 ); // bottom
2525                 g.drawLine(  9,1  , 15,7  ); // top slant
2526                 g.drawLine(  9,13 , 15,7  ); // bottom slant
2527             }
2528             else {
2529                 g.drawLine(  7,0  , 14,0  ); // top
2530                 g.drawLine( 15,1  , 15,13 ); // right
2531                 g.drawLine(  7,14 , 14,14 ); // bottom
2532                 g.drawLine(  0,7  ,  6,1  ); // top slant
2533                 g.drawLine(  0,7  ,  6,13 ); // bottom slant
2534             }
2535 
2536             if (hasFocus && enabled) {
2537                 // Inner line.
2538                 g.setColor(MetalLookAndFeel.getPrimaryControl());
2539                 if (leftToRight) {
2540                     g.drawLine(  1,1  ,  8,1  ); // top
2541                     g.drawLine(  1,1  ,  1,13 ); // left
2542                     g.drawLine(  1,13 ,  8,13 ); // bottom
2543                     g.drawLine(  9,2  , 14,7  ); // top slant
2544                     g.drawLine(  9,12 , 14,7  ); // bottom slant
2545                 }
2546                 else {
2547                     g.drawLine(  7,1  , 14,1  ); // top
2548                     g.drawLine( 14,1  , 14,13 ); // right
2549                     g.drawLine(  7,13 , 14,13 ); // bottom
2550                     g.drawLine(  1,7  ,  7,1  ); // top slant
2551                     g.drawLine(  1,7  ,  7,13 ); // bottom slant
2552                 }
2553             }
2554         }
2555 
2556         public int getIconWidth() {
2557             return 16;
2558         }
2559 
2560         public int getIconHeight() {
2561             return 15;
2562         }
2563 
2564         protected Image createImage(Component c, int w, int h,
2565                                     GraphicsConfiguration config,
2566                                     Object[] args) {
2567             if (config == null) {
2568                 return new BufferedImage(w, h,BufferedImage.TYPE_INT_ARGB);
2569             }
2570             return config.createCompatibleImage(
2571                                 w, h, Transparency.BITMASK);
2572         }
2573     }
2574 
2575 
2576     private static class OceanHorizontalSliderThumbIcon extends CachedPainter
2577                               implements Icon, Serializable, UIResource {
2578         // Used for clipping
2579         private static Polygon THUMB_SHAPE;
2580 
2581         static {
2582             THUMB_SHAPE = new Polygon(new int[] { 0, 14, 14,  7,  0 },
2583                                       new int[] { 0,  0,  8, 15,  8 }, 5);
2584         }
2585 
2586         OceanHorizontalSliderThumbIcon() {
2587             super(3);
2588         }
2589 
2590         public void paintIcon(Component c, Graphics g, int x, int y) {
2591             if (!(g instanceof Graphics2D)) {
2592                 return;
2593             }
2594             paint(c, g, x, y, getIconWidth(), getIconHeight(),
2595                   c.hasFocus(), c.isEnabled(),
2596                   MetalLookAndFeel.getCurrentTheme());
2597         }
2598 
2599 
2600         protected Image createImage(Component c, int w, int h,
2601                                     GraphicsConfiguration config,
2602                                     Object[] args) {
2603             if (config == null) {
2604                 return new BufferedImage(w, h,BufferedImage.TYPE_INT_ARGB);
2605             }
2606             return config.createCompatibleImage(
2607                                 w, h, Transparency.BITMASK);
2608         }
2609 
2610         protected void paintToImage(Component c, Image image, Graphics g2,
2611                                     int w, int h, Object[] args) {
2612             Graphics2D g = (Graphics2D)g2;
2613             boolean hasFocus = ((Boolean)args[0]).booleanValue();
2614             boolean enabled = ((Boolean)args[1]).booleanValue();
2615 
2616             // Fill in the background
2617             Rectangle clip = g.getClipBounds();
2618             g.clip(THUMB_SHAPE);
2619             if (!enabled) {
2620                 g.setColor(MetalLookAndFeel.getControl());
2621                 g.fillRect(1, 1, 13, 14);
2622             }
2623             else if (hasFocus) {
2624                 MetalUtils.drawGradient(c, g, "Slider.focusGradient",
2625                                         1, 1, 13, 14, true);
2626             }
2627             else {
2628                 MetalUtils.drawGradient(c, g, "Slider.gradient",
2629                                         1, 1, 13, 14, true);
2630             }
2631             g.setClip(clip);
2632 
2633             // Draw the frame
2634             if (hasFocus) {
2635                 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
2636             }
2637             else {
2638                 g.setColor(enabled ? MetalLookAndFeel.getPrimaryControlInfo() :
2639                            MetalLookAndFeel.getControlDarkShadow());
2640             }
2641 
2642             g.drawLine(  1,0  , 13,0 );  // top
2643             g.drawLine(  0,1  ,  0,8 );  // left
2644             g.drawLine( 14,1  , 14,8 );  // right
2645             g.drawLine(  1,9  ,  7,15 ); // left slant
2646             g.drawLine(  7,15 , 14,8 );  // right slant
2647 
2648             if (hasFocus && enabled) {
2649                 // Inner line.
2650                 g.setColor(MetalLookAndFeel.getPrimaryControl());
2651                 g.fillRect(1, 1, 13, 1);
2652                 g.fillRect(1, 2, 1, 7);
2653                 g.fillRect(13, 2, 1, 7);
2654                 g.drawLine(2, 9, 7, 14);
2655                 g.drawLine(8, 13, 12, 9);
2656             }
2657         }
2658 
2659         public int getIconWidth() {
2660             return 15;
2661         }
2662 
2663         public int getIconHeight() {
2664             return 16;
2665         }
2666     }
2667 }