1 /*
   2  * Copyright (c) 1998, 2008, 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&trade; 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&trade;
  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 = 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<ImageGcPair> images = new Vector<ImageGcPair>(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                 return ((newGC != null) && (newGC.equals(gc))) ||
1518                         ((newGC == null) && (gc == null));
1519             }
1520 
1521         }
1522 
1523         Image getImage(GraphicsConfiguration newGC) {
1524             if ((currentImageGcPair == null) ||
1525                 !(currentImageGcPair.hasSameConfiguration(newGC)))
1526             {
1527                 for (ImageGcPair imgGcPair : images) {
1528                     if (imgGcPair.hasSameConfiguration(newGC)) {
1529                         currentImageGcPair = imgGcPair;
1530                         return imgGcPair.image;
1531                     }
1532                 }
1533                 return null;
1534             }
1535             return currentImageGcPair.image;
1536         }
1537 
1538         void cacheImage(Image image, GraphicsConfiguration gc) {
1539             ImageGcPair imgGcPair = new ImageGcPair(image, gc);
1540             images.addElement(imgGcPair);
1541             currentImageGcPair = imgGcPair;
1542         }
1543 
1544     }
1545 
1546     /**
1547      * <p>
1548      * <strong>Warning:</strong>
1549      * Serialized objects of this class will not be compatible with
1550      * future Swing releases. The current serialization support is
1551      * appropriate for short term storage or RMI between applications running
1552      * the same version of Swing.  As of 1.4, support for long term storage
1553      * of all JavaBeans&trade;
1554      * has been added to the <code>java.beans</code> package.
1555      * Please see {@link java.beans.XMLEncoder}.
1556      */
1557     public static class FolderIcon16 implements Icon, Serializable {
1558 
1559         ImageCacher imageCacher;
1560 
1561         public void paintIcon(Component c, Graphics g, int x, int y) {
1562             GraphicsConfiguration gc = c.getGraphicsConfiguration();
1563             if (imageCacher == null) {
1564                 imageCacher = new ImageCacher();
1565             }
1566             Image image = imageCacher.getImage(gc);
1567             if (image == null) {
1568                 if (gc != null) {
1569                     image = gc.createCompatibleImage(getIconWidth(),
1570                                                      getIconHeight(),
1571                                                      Transparency.BITMASK);
1572                 } else {
1573                     image = new BufferedImage(getIconWidth(),
1574                                               getIconHeight(),
1575                                               BufferedImage.TYPE_INT_ARGB);
1576                 }
1577                 Graphics imageG = image.getGraphics();
1578                 paintMe(c,imageG);
1579                 imageG.dispose();
1580                 imageCacher.cacheImage(image, gc);
1581             }
1582             g.drawImage(image, x, y+getShift(), null);
1583         }
1584 
1585 
1586         private void paintMe(Component c, Graphics g) {
1587 
1588             int right = folderIcon16Size.width - 1;
1589             int bottom = folderIcon16Size.height - 1;
1590 
1591             // Draw tab top
1592             g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
1593             g.drawLine( right - 5, 3, right, 3 );
1594             g.drawLine( right - 6, 4, right, 4 );
1595 
1596             // Draw folder front
1597             g.setColor( MetalLookAndFeel.getPrimaryControl() );
1598             g.fillRect( 2, 7, 13, 8 );
1599 
1600             // Draw tab bottom
1601             g.setColor( MetalLookAndFeel.getPrimaryControlShadow() );
1602             g.drawLine( right - 6, 5, right - 1, 5 );
1603 
1604             // Draw outline
1605             g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
1606             g.drawLine( 0, 6, 0, bottom );            // left side
1607             g.drawLine( 1, 5, right - 7, 5 );         // first part of top
1608             g.drawLine( right - 6, 6, right - 1, 6 ); // second part of top
1609             g.drawLine( right, 5, right, bottom );    // right side
1610             g.drawLine( 0, bottom, right, bottom );   // bottom
1611 
1612             // Draw highlight
1613             g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
1614             g.drawLine( 1, 6, 1, bottom - 1 );
1615             g.drawLine( 1, 6, right - 7, 6 );
1616             g.drawLine( right - 6, 7, right - 1, 7 );
1617 
1618         }
1619 
1620         public int getShift() { return 0; }
1621         public int getAdditionalHeight() { return 0; }
1622 
1623         public int getIconWidth() { return folderIcon16Size.width; }
1624         public int getIconHeight() { return folderIcon16Size.height + getAdditionalHeight(); }
1625     }
1626 
1627 
1628     /**
1629      * <p>
1630      * <strong>Warning:</strong>
1631      * Serialized objects of this class will not be compatible with
1632      * future Swing releases. The current serialization support is
1633      * appropriate for short term storage or RMI between applications running
1634      * the same version of Swing.  As of 1.4, support for long term storage
1635      * of all JavaBeans&trade;
1636      * has been added to the <code>java.beans</code> package.
1637      * Please see {@link java.beans.XMLEncoder}.
1638      */
1639     public static class TreeFolderIcon extends FolderIcon16 {
1640         public int getShift() { return -1; }
1641         public int getAdditionalHeight() { return 2; }
1642     }
1643 
1644 
1645     static private final Dimension fileIcon16Size = new Dimension( 16, 16 );
1646 
1647     /**
1648      * <p>
1649      * <strong>Warning:</strong>
1650      * Serialized objects of this class will not be compatible with
1651      * future Swing releases. The current serialization support is
1652      * appropriate for short term storage or RMI between applications running
1653      * the same version of Swing.  As of 1.4, support for long term storage
1654      * of all JavaBeans&trade;
1655      * has been added to the <code>java.beans</code> package.
1656      * Please see {@link java.beans.XMLEncoder}.
1657      */
1658     public static class FileIcon16 implements Icon, Serializable {
1659 
1660         ImageCacher imageCacher;
1661 
1662         public void paintIcon(Component c, Graphics g, int x, int y) {
1663             GraphicsConfiguration gc = c.getGraphicsConfiguration();
1664             if (imageCacher == null) {
1665                 imageCacher = new ImageCacher();
1666             }
1667             Image image = imageCacher.getImage(gc);
1668             if (image == null) {
1669                 if (gc != null) {
1670                     image = gc.createCompatibleImage(getIconWidth(),
1671                                                      getIconHeight(),
1672                                                      Transparency.BITMASK);
1673                 } else {
1674                     image = new BufferedImage(getIconWidth(),
1675                                               getIconHeight(),
1676                                               BufferedImage.TYPE_INT_ARGB);
1677                 }
1678                 Graphics imageG = image.getGraphics();
1679                 paintMe(c,imageG);
1680                 imageG.dispose();
1681                 imageCacher.cacheImage(image, gc);
1682             }
1683             g.drawImage(image, x, y+getShift(), null);
1684         }
1685 
1686         private void paintMe(Component c, Graphics g) {
1687 
1688                 int right = fileIcon16Size.width - 1;
1689                 int bottom = fileIcon16Size.height - 1;
1690 
1691                 // Draw fill
1692                 g.setColor( MetalLookAndFeel.getWindowBackground() );
1693                 g.fillRect( 4, 2, 9, 12 );
1694 
1695                 // Draw frame
1696                 g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
1697                 g.drawLine( 2, 0, 2, bottom );                 // left
1698                 g.drawLine( 2, 0, right - 4, 0 );              // top
1699                 g.drawLine( 2, bottom, right - 1, bottom );    // bottom
1700                 g.drawLine( right - 1, 6, right - 1, bottom ); // right
1701                 g.drawLine( right - 6, 2, right - 2, 6 );      // slant 1
1702                 g.drawLine( right - 5, 1, right - 4, 1 );      // part of slant 2
1703                 g.drawLine( right - 3, 2, right - 3, 3 );      // part of slant 2
1704                 g.drawLine( right - 2, 4, right - 2, 5 );      // part of slant 2
1705 
1706                 // Draw highlight
1707                 g.setColor( MetalLookAndFeel.getPrimaryControl() );
1708                 g.drawLine( 3, 1, 3, bottom - 1 );                  // left
1709                 g.drawLine( 3, 1, right - 6, 1 );                   // top
1710                 g.drawLine( right - 2, 7, right - 2, bottom - 1 );  // right
1711                 g.drawLine( right - 5, 2, right - 3, 4 );           // slant
1712                 g.drawLine( 3, bottom - 1, right - 2, bottom - 1 ); // bottom
1713 
1714         }
1715 
1716         public int getShift() { return 0; }
1717         public int getAdditionalHeight() { return 0; }
1718 
1719         public int getIconWidth() { return fileIcon16Size.width; }
1720         public int getIconHeight() { return fileIcon16Size.height + getAdditionalHeight(); }
1721     }
1722 
1723 
1724     public static class TreeLeafIcon extends FileIcon16 {
1725         public int getShift() { return 2; }
1726         public int getAdditionalHeight() { return 4; }
1727     }
1728 
1729 
1730     static private final Dimension treeControlSize = new Dimension( 18, 18 );
1731 
1732     /**
1733      * <p>
1734      * <strong>Warning:</strong>
1735      * Serialized objects of this class will not be compatible with
1736      * future Swing releases. The current serialization support is
1737      * appropriate for short term storage or RMI between applications running
1738      * the same version of Swing.  As of 1.4, support for long term storage
1739      * of all JavaBeans&trade;
1740      * has been added to the <code>java.beans</code> package.
1741      * Please see {@link java.beans.XMLEncoder}.
1742      */
1743     public static class TreeControlIcon implements Icon, Serializable {
1744         // This data member should not have been exposed.  It's called
1745         // isLight, but now it really means isCollapsed.  Since we can't change
1746         // any APIs... that's life.
1747         protected boolean isLight;
1748 
1749 
1750         public TreeControlIcon( boolean isCollapsed ) {
1751             isLight = isCollapsed;
1752         }
1753 
1754         ImageCacher imageCacher;
1755 
1756         transient boolean cachedOrientation = true;
1757 
1758         public void paintIcon(Component c, Graphics g, int x, int y) {
1759 
1760             GraphicsConfiguration gc = c.getGraphicsConfiguration();
1761 
1762             if (imageCacher == null) {
1763                 imageCacher = new ImageCacher();
1764             }
1765             Image image = imageCacher.getImage(gc);
1766 
1767             if (image == null || cachedOrientation != MetalUtils.isLeftToRight(c)) {
1768                 cachedOrientation = MetalUtils.isLeftToRight(c);
1769                 if (gc != null) {
1770                     image = gc.createCompatibleImage(getIconWidth(),
1771                                                      getIconHeight(),
1772                                                      Transparency.BITMASK);
1773                 } else {
1774                     image = new BufferedImage(getIconWidth(),
1775                                               getIconHeight(),
1776                                               BufferedImage.TYPE_INT_ARGB);
1777                 }
1778                 Graphics imageG = image.getGraphics();
1779                 paintMe(c,imageG,x,y);
1780                 imageG.dispose();
1781                 imageCacher.cacheImage(image, gc);
1782 
1783             }
1784 
1785             if (MetalUtils.isLeftToRight(c)) {
1786                 if (isLight) {    // isCollapsed
1787                     g.drawImage(image, x+5, y+3, x+18, y+13,
1788                                        4,3, 17, 13, null);
1789                 }
1790                 else {
1791                     g.drawImage(image, x+5, y+3, x+18, y+17,
1792                                        4,3, 17, 17, null);
1793                 }
1794             }
1795             else {
1796                 if (isLight) {    // isCollapsed
1797                     g.drawImage(image, x+3, y+3, x+16, y+13,
1798                                        4, 3, 17, 13, null);
1799                 }
1800                 else {
1801                     g.drawImage(image, x+3, y+3, x+16, y+17,
1802                                        4, 3, 17, 17, null);
1803                 }
1804             }
1805         }
1806 
1807         public void paintMe(Component c, Graphics g, int x, int y) {
1808 
1809             g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
1810 
1811             int xoff = (MetalUtils.isLeftToRight(c)) ? 0 : 4;
1812 
1813             // Draw circle
1814             g.drawLine( xoff + 4, 6, xoff + 4, 9 );     // left
1815             g.drawLine( xoff + 5, 5, xoff + 5, 5 );     // top left dot
1816             g.drawLine( xoff + 6, 4, xoff + 9, 4 );     // top
1817             g.drawLine( xoff + 10, 5, xoff + 10, 5 );   // top right dot
1818             g.drawLine( xoff + 11, 6, xoff + 11, 9 );   // right
1819             g.drawLine( xoff + 10, 10, xoff + 10, 10 ); // botom right dot
1820             g.drawLine( xoff + 6, 11, xoff + 9, 11 );   // bottom
1821             g.drawLine( xoff + 5, 10, xoff + 5, 10 );   // bottom left dot
1822 
1823             // Draw Center Dot
1824             g.drawLine( xoff + 7, 7, xoff + 8, 7 );
1825             g.drawLine( xoff + 7, 8, xoff + 8, 8 );
1826 
1827             // Draw Handle
1828             if ( isLight ) {    // isCollapsed
1829                 if( MetalUtils.isLeftToRight(c) ) {
1830                     g.drawLine( 12, 7, 15, 7 );
1831                     g.drawLine( 12, 8, 15, 8 );
1832                     //  g.setColor( c.getBackground() );
1833                     //  g.drawLine( 16, 7, 16, 8 );
1834                 }
1835                 else {
1836                     g.drawLine(4, 7, 7, 7);
1837                     g.drawLine(4, 8, 7, 8);
1838                 }
1839             }
1840             else {
1841                 g.drawLine( xoff + 7, 12, xoff + 7, 15 );
1842                 g.drawLine( xoff + 8, 12, xoff + 8, 15 );
1843                 //      g.setColor( c.getBackground() );
1844                 //      g.drawLine( xoff + 7, 16, xoff + 8, 16 );
1845             }
1846 
1847             // Draw Fill
1848             g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
1849             g.drawLine( xoff + 5, 6, xoff + 5, 9 );      // left shadow
1850             g.drawLine( xoff + 6, 5, xoff + 9, 5 );      // top shadow
1851 
1852             g.setColor( MetalLookAndFeel.getPrimaryControlShadow() );
1853             g.drawLine( xoff + 6, 6, xoff + 6, 6 );      // top left fill
1854             g.drawLine( xoff + 9, 6, xoff + 9, 6 );      // top right fill
1855             g.drawLine( xoff + 6, 9, xoff + 6, 9 );      // bottom left fill
1856             g.drawLine( xoff + 10, 6, xoff + 10, 9 );    // right fill
1857             g.drawLine( xoff + 6, 10, xoff + 9, 10 );    // bottom fill
1858 
1859             g.setColor( MetalLookAndFeel.getPrimaryControl() );
1860             g.drawLine( xoff + 6, 7, xoff + 6, 8 );      // left highlight
1861             g.drawLine( xoff + 7, 6, xoff + 8, 6 );      // top highlight
1862             g.drawLine( xoff + 9, 7, xoff + 9, 7 );      // right highlight
1863             g.drawLine( xoff + 7, 9, xoff + 7, 9 );      // bottom highlight
1864 
1865             g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
1866             g.drawLine( xoff + 8, 9, xoff + 9, 9 );
1867             g.drawLine( xoff + 9, 8, xoff + 9, 8 );
1868         }
1869 
1870         public int getIconWidth() { return treeControlSize.width; }
1871         public int getIconHeight() { return treeControlSize.height; }
1872     }
1873 
1874   //
1875   // Menu Icons
1876   //
1877 
1878     static private final Dimension menuArrowIconSize = new Dimension( 4, 8 );
1879     static private final Dimension menuCheckIconSize = new Dimension( 10, 10 );
1880     static private final int xOff = 4;
1881 
1882     private static class MenuArrowIcon implements Icon, UIResource, Serializable
1883     {
1884         public void paintIcon( Component c, Graphics g, int x, int y )
1885         {
1886             JMenuItem b = (JMenuItem) c;
1887             ButtonModel model = b.getModel();
1888 
1889             g.translate( x, y );
1890 
1891             if ( !model.isEnabled() )
1892             {
1893                 g.setColor( MetalLookAndFeel.getMenuDisabledForeground() );
1894             }
1895             else
1896             {
1897                 if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
1898                 {
1899                     g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
1900                 }
1901                 else
1902                 {
1903                     g.setColor( b.getForeground() );
1904                 }
1905             }
1906             if( MetalUtils.isLeftToRight(b) ) {
1907                 g.drawLine( 0, 0, 0, 7 );
1908                 g.drawLine( 1, 1, 1, 6 );
1909                 g.drawLine( 2, 2, 2, 5 );
1910                 g.drawLine( 3, 3, 3, 4 );
1911             } else {
1912                 g.drawLine( 4, 0, 4, 7 );
1913                 g.drawLine( 3, 1, 3, 6 );
1914                 g.drawLine( 2, 2, 2, 5 );
1915                 g.drawLine( 1, 3, 1, 4 );
1916             }
1917 
1918             g.translate( -x, -y );
1919         }
1920 
1921         public int getIconWidth() { return menuArrowIconSize.width; }
1922 
1923         public int getIconHeight() { return menuArrowIconSize.height; }
1924 
1925     } // End class MenuArrowIcon
1926 
1927     private static class MenuItemArrowIcon implements Icon, UIResource, Serializable
1928     {
1929         public void paintIcon( Component c, Graphics g, int x, int y )
1930         {
1931         }
1932 
1933         public int getIconWidth() { return menuArrowIconSize.width; }
1934 
1935         public int getIconHeight() { return menuArrowIconSize.height; }
1936 
1937     } // End class MenuItemArrowIcon
1938 
1939     private static class CheckBoxMenuItemIcon implements Icon, UIResource, Serializable
1940     {
1941         public void paintOceanIcon(Component c, Graphics g, int x, int y) {
1942             ButtonModel model = ((JMenuItem)c).getModel();
1943             boolean isSelected = model.isSelected();
1944             boolean isEnabled = model.isEnabled();
1945             boolean isPressed = model.isPressed();
1946             boolean isArmed = model.isArmed();
1947 
1948             g.translate(x, y);
1949             if (isEnabled) {
1950                 MetalUtils.drawGradient(c, g, "CheckBoxMenuItem.gradient",
1951                                         1, 1, 7, 7, true);
1952                 if (isPressed || isArmed) {
1953                     g.setColor(MetalLookAndFeel.getControlInfo());
1954                     g.drawLine( 0, 0, 8, 0 );
1955                     g.drawLine( 0, 0, 0, 8 );
1956                     g.drawLine( 8, 2, 8, 8 );
1957                     g.drawLine( 2, 8, 8, 8 );
1958 
1959                     g.setColor(MetalLookAndFeel.getPrimaryControl());
1960                     g.drawLine( 9, 1, 9, 9 );
1961                     g.drawLine( 1, 9, 9, 9 );
1962                 }
1963                 else {
1964                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
1965                     g.drawLine( 0, 0, 8, 0 );
1966                     g.drawLine( 0, 0, 0, 8 );
1967                     g.drawLine( 8, 2, 8, 8 );
1968                     g.drawLine( 2, 8, 8, 8 );
1969 
1970                     g.setColor(MetalLookAndFeel.getControlHighlight());
1971                     g.drawLine( 9, 1, 9, 9 );
1972                     g.drawLine( 1, 9, 9, 9 );
1973                 }
1974             }
1975             else {
1976                 g.setColor(MetalLookAndFeel.getMenuDisabledForeground());
1977                 g.drawRect( 0, 0, 8, 8 );
1978             }
1979             if (isSelected) {
1980                 if (isEnabled) {
1981                     if (isArmed || ( c instanceof JMenu && isSelected)) {
1982                         g.setColor(
1983                             MetalLookAndFeel.getMenuSelectedForeground() );
1984                     }
1985                     else {
1986                          g.setColor(MetalLookAndFeel.getControlInfo());
1987                     }
1988                 }
1989                 else {
1990                     g.setColor( MetalLookAndFeel.getMenuDisabledForeground());
1991                 }
1992 
1993                 g.drawLine( 2, 2, 2, 6 );
1994                 g.drawLine( 3, 2, 3, 6 );
1995                 g.drawLine( 4, 4, 8, 0 );
1996                 g.drawLine( 4, 5, 9, 0 );
1997             }
1998             g.translate( -x, -y );
1999         }
2000 
2001         public void paintIcon( Component c, Graphics g, int x, int y )
2002         {
2003             if (MetalLookAndFeel.usingOcean()) {
2004                 paintOceanIcon(c, g, x, y);
2005                 return;
2006             }
2007             JMenuItem b = (JMenuItem) c;
2008             ButtonModel model = b.getModel();
2009 
2010             boolean isSelected = model.isSelected();
2011             boolean isEnabled = model.isEnabled();
2012             boolean isPressed = model.isPressed();
2013             boolean isArmed = model.isArmed();
2014 
2015             g.translate( x, y );
2016 
2017             if ( isEnabled )
2018             {
2019                 if ( isPressed || isArmed )
2020                 {
2021                     g.setColor( MetalLookAndFeel.getControlInfo()  );
2022                     g.drawLine( 0, 0, 8, 0 );
2023                     g.drawLine( 0, 0, 0, 8 );
2024                     g.drawLine( 8, 2, 8, 8 );
2025                     g.drawLine( 2, 8, 8, 8 );
2026 
2027                     g.setColor( MetalLookAndFeel.getPrimaryControl()  );
2028                     g.drawLine( 1, 1, 7, 1 );
2029                     g.drawLine( 1, 1, 1, 7 );
2030                     g.drawLine( 9, 1, 9, 9 );
2031                     g.drawLine( 1, 9, 9, 9 );
2032                 }
2033                 else
2034                 {
2035                     g.setColor( MetalLookAndFeel.getControlDarkShadow()  );
2036                     g.drawLine( 0, 0, 8, 0 );
2037                     g.drawLine( 0, 0, 0, 8 );
2038                     g.drawLine( 8, 2, 8, 8 );
2039                     g.drawLine( 2, 8, 8, 8 );
2040 
2041                     g.setColor( MetalLookAndFeel.getControlHighlight()  );
2042                     g.drawLine( 1, 1, 7, 1 );
2043                     g.drawLine( 1, 1, 1, 7 );
2044                     g.drawLine( 9, 1, 9, 9 );
2045                     g.drawLine( 1, 9, 9, 9 );
2046                 }
2047             }
2048             else
2049             {
2050                 g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2051                 g.drawRect( 0, 0, 8, 8 );
2052             }
2053 
2054             if ( isSelected )
2055             {
2056                 if ( isEnabled )
2057                 {
2058                     if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
2059                     {
2060                         g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
2061                     }
2062                     else
2063                     {
2064                         g.setColor( b.getForeground() );
2065                     }
2066                 }
2067                 else
2068                 {
2069                     g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2070                 }
2071 
2072                 g.drawLine( 2, 2, 2, 6 );
2073                 g.drawLine( 3, 2, 3, 6 );
2074                 g.drawLine( 4, 4, 8, 0 );
2075                 g.drawLine( 4, 5, 9, 0 );
2076             }
2077 
2078             g.translate( -x, -y );
2079         }
2080 
2081         public int getIconWidth() { return menuCheckIconSize.width; }
2082 
2083         public int getIconHeight() { return menuCheckIconSize.height; }
2084 
2085     }  // End class CheckBoxMenuItemIcon
2086 
2087     private static class RadioButtonMenuItemIcon implements Icon, UIResource, Serializable
2088     {
2089         public void paintOceanIcon(Component c, Graphics g, int x, int y) {
2090             ButtonModel model = ((JMenuItem)c).getModel();
2091             boolean isSelected = model.isSelected();
2092             boolean isEnabled = model.isEnabled();
2093             boolean isPressed = model.isPressed();
2094             boolean isArmed = model.isArmed();
2095 
2096             g.translate( x, y );
2097 
2098             if (isEnabled) {
2099                 MetalUtils.drawGradient(c, g, "RadioButtonMenuItem.gradient",
2100                                         1, 1, 7, 7, true);
2101                 if (isPressed || isArmed) {
2102                     g.setColor(MetalLookAndFeel.getPrimaryControl());
2103                 }
2104                 else {
2105                     g.setColor(MetalLookAndFeel.getControlHighlight());
2106                 }
2107                 g.drawLine( 2, 9, 7, 9 );
2108                 g.drawLine( 9, 2, 9, 7 );
2109                 g.drawLine( 8, 8, 8, 8 );
2110 
2111                 if (isPressed || isArmed) {
2112                     g.setColor(MetalLookAndFeel.getControlInfo());
2113                 }
2114                 else {
2115                     g.setColor(MetalLookAndFeel.getControlDarkShadow());
2116                 }
2117             }
2118             else {
2119                 g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2120             }
2121             g.drawLine( 2, 0, 6, 0 );
2122             g.drawLine( 2, 8, 6, 8 );
2123             g.drawLine( 0, 2, 0, 6 );
2124             g.drawLine( 8, 2, 8, 6 );
2125             g.drawLine( 1, 1, 1, 1 );
2126             g.drawLine( 7, 1, 7, 1 );
2127             g.drawLine( 1, 7, 1, 7 );
2128             g.drawLine( 7, 7, 7, 7 );
2129 
2130             if (isSelected) {
2131                 if (isEnabled) {
2132                     if (isArmed || (c instanceof JMenu && model.isSelected())){
2133                         g.setColor(MetalLookAndFeel.
2134                                    getMenuSelectedForeground() );
2135                     }
2136                     else {
2137                         g.setColor(MetalLookAndFeel.getControlInfo());
2138                     }
2139                 }
2140                 else {
2141                     g.setColor(MetalLookAndFeel.getMenuDisabledForeground());
2142                 }
2143                 g.drawLine( 3, 2, 5, 2 );
2144                 g.drawLine( 2, 3, 6, 3 );
2145                 g.drawLine( 2, 4, 6, 4 );
2146                 g.drawLine( 2, 5, 6, 5 );
2147                 g.drawLine( 3, 6, 5, 6 );
2148             }
2149 
2150             g.translate( -x, -y );
2151         }
2152 
2153         public void paintIcon( Component c, Graphics g, int x, int y )
2154         {
2155             if (MetalLookAndFeel.usingOcean()) {
2156                 paintOceanIcon(c, g, x, y);
2157                 return;
2158             }
2159             JMenuItem b = (JMenuItem) c;
2160             ButtonModel model = b.getModel();
2161 
2162             boolean isSelected = model.isSelected();
2163             boolean isEnabled = model.isEnabled();
2164             boolean isPressed = model.isPressed();
2165             boolean isArmed = model.isArmed();
2166 
2167             g.translate( x, y );
2168 
2169             if ( isEnabled )
2170             {
2171                 if ( isPressed || isArmed )
2172                 {
2173                     g.setColor( MetalLookAndFeel.getPrimaryControl()  );
2174                     g.drawLine( 3, 1, 8, 1 );
2175                     g.drawLine( 2, 9, 7, 9 );
2176                     g.drawLine( 1, 3, 1, 8 );
2177                     g.drawLine( 9, 2, 9, 7 );
2178                     g.drawLine( 2, 2, 2, 2 );
2179                     g.drawLine( 8, 8, 8, 8 );
2180 
2181                     g.setColor( MetalLookAndFeel.getControlInfo()  );
2182                     g.drawLine( 2, 0, 6, 0 );
2183                     g.drawLine( 2, 8, 6, 8 );
2184                     g.drawLine( 0, 2, 0, 6 );
2185                     g.drawLine( 8, 2, 8, 6 );
2186                     g.drawLine( 1, 1, 1, 1 );
2187                     g.drawLine( 7, 1, 7, 1 );
2188                     g.drawLine( 1, 7, 1, 7 );
2189                     g.drawLine( 7, 7, 7, 7 );
2190                 }
2191                 else
2192                 {
2193                     g.setColor( MetalLookAndFeel.getControlHighlight()  );
2194                     g.drawLine( 3, 1, 8, 1 );
2195                     g.drawLine( 2, 9, 7, 9 );
2196                     g.drawLine( 1, 3, 1, 8 );
2197                     g.drawLine( 9, 2, 9, 7 );
2198                     g.drawLine( 2, 2, 2, 2 );
2199                     g.drawLine( 8, 8, 8, 8 );
2200 
2201                     g.setColor( MetalLookAndFeel.getControlDarkShadow()  );
2202                     g.drawLine( 2, 0, 6, 0 );
2203                     g.drawLine( 2, 8, 6, 8 );
2204                     g.drawLine( 0, 2, 0, 6 );
2205                     g.drawLine( 8, 2, 8, 6 );
2206                     g.drawLine( 1, 1, 1, 1 );
2207                     g.drawLine( 7, 1, 7, 1 );
2208                     g.drawLine( 1, 7, 1, 7 );
2209                     g.drawLine( 7, 7, 7, 7 );
2210                 }
2211             }
2212             else
2213             {
2214                 g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2215                 g.drawLine( 2, 0, 6, 0 );
2216                 g.drawLine( 2, 8, 6, 8 );
2217                 g.drawLine( 0, 2, 0, 6 );
2218                 g.drawLine( 8, 2, 8, 6 );
2219                 g.drawLine( 1, 1, 1, 1 );
2220                 g.drawLine( 7, 1, 7, 1 );
2221                 g.drawLine( 1, 7, 1, 7 );
2222                 g.drawLine( 7, 7, 7, 7 );
2223             }
2224 
2225             if ( isSelected )
2226             {
2227                 if ( isEnabled )
2228                 {
2229                     if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
2230                     {
2231                         g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
2232                     }
2233                     else
2234                     {
2235                         g.setColor( b.getForeground() );
2236                     }
2237                 }
2238                 else
2239                 {
2240                     g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
2241                 }
2242 
2243                 g.drawLine( 3, 2, 5, 2 );
2244                 g.drawLine( 2, 3, 6, 3 );
2245                 g.drawLine( 2, 4, 6, 4 );
2246                 g.drawLine( 2, 5, 6, 5 );
2247                 g.drawLine( 3, 6, 5, 6 );
2248             }
2249 
2250             g.translate( -x, -y );
2251         }
2252 
2253         public int getIconWidth() { return menuCheckIconSize.width; }
2254 
2255         public int getIconHeight() { return menuCheckIconSize.height; }
2256 
2257     }  // End class RadioButtonMenuItemIcon
2258 
2259 private static class VerticalSliderThumbIcon implements Icon, Serializable, UIResource {
2260     protected static MetalBumps controlBumps;
2261     protected static MetalBumps primaryBumps;
2262 
2263     public VerticalSliderThumbIcon() {
2264         controlBumps = new MetalBumps( 6, 10,
2265                                 MetalLookAndFeel.getControlHighlight(),
2266                                 MetalLookAndFeel.getControlInfo(),
2267                                 MetalLookAndFeel.getControl() );
2268         primaryBumps = new MetalBumps( 6, 10,
2269                                 MetalLookAndFeel.getPrimaryControl(),
2270                                 MetalLookAndFeel.getPrimaryControlDarkShadow(),
2271                                 MetalLookAndFeel.getPrimaryControlShadow() );
2272     }
2273 
2274     public void paintIcon( Component c, Graphics g, int x, int y ) {
2275         boolean leftToRight = MetalUtils.isLeftToRight(c);
2276 
2277         g.translate( x, y );
2278 
2279         // Draw the frame
2280         if ( c.hasFocus() ) {
2281             g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
2282         }
2283         else {
2284             g.setColor( c.isEnabled() ? MetalLookAndFeel.getPrimaryControlInfo() :
2285                                              MetalLookAndFeel.getControlDarkShadow() );
2286         }
2287 
2288         if (leftToRight) {
2289             g.drawLine(  1,0  ,  8,0  ); // top
2290             g.drawLine(  0,1  ,  0,13 ); // left
2291             g.drawLine(  1,14 ,  8,14 ); // bottom
2292             g.drawLine(  9,1  , 15,7  ); // top slant
2293             g.drawLine(  9,13 , 15,7  ); // bottom slant
2294         }
2295         else {
2296             g.drawLine(  7,0  , 14,0  ); // top
2297             g.drawLine( 15,1  , 15,13 ); // right
2298             g.drawLine(  7,14 , 14,14 ); // bottom
2299             g.drawLine(  0,7  ,  6,1  ); // top slant
2300             g.drawLine(  0,7  ,  6,13 ); // bottom slant
2301         }
2302 
2303         // Fill in the background
2304         if ( c.hasFocus() ) {
2305             g.setColor( c.getForeground() );
2306         }
2307         else {
2308             g.setColor( MetalLookAndFeel.getControl() );
2309         }
2310 
2311         if (leftToRight) {
2312             g.fillRect(  1,1 ,  8,13 );
2313 
2314             g.drawLine(  9,2 ,  9,12 );
2315             g.drawLine( 10,3 , 10,11 );
2316             g.drawLine( 11,4 , 11,10 );
2317             g.drawLine( 12,5 , 12,9 );
2318             g.drawLine( 13,6 , 13,8 );
2319             g.drawLine( 14,7 , 14,7 );
2320         }
2321         else {
2322             g.fillRect(  7,1,   8,13 );
2323 
2324             g.drawLine(  6,3 ,  6,12 );
2325             g.drawLine(  5,4 ,  5,11 );
2326             g.drawLine(  4,5 ,  4,10 );
2327             g.drawLine(  3,6 ,  3,9 );
2328             g.drawLine(  2,7 ,  2,8 );
2329         }
2330 
2331         // Draw the bumps
2332         int offset = (leftToRight) ? 2 : 8;
2333         if ( c.isEnabled() ) {
2334             if ( c.hasFocus() ) {
2335                 primaryBumps.paintIcon( c, g, offset, 2 );
2336             }
2337             else {
2338                 controlBumps.paintIcon( c, g, offset, 2 );
2339             }
2340         }
2341 
2342         // Draw the highlight
2343         if ( c.isEnabled() ) {
2344             g.setColor( c.hasFocus() ? MetalLookAndFeel.getPrimaryControl()
2345                         : MetalLookAndFeel.getControlHighlight() );
2346             if (leftToRight) {
2347                 g.drawLine( 1, 1, 8, 1 );
2348                 g.drawLine( 1, 1, 1, 13 );
2349             }
2350             else {
2351                 g.drawLine(  8,1  , 14,1  ); // top
2352                 g.drawLine(  1,7  ,  7,1  ); // top slant
2353             }
2354         }
2355 
2356         g.translate( -x, -y );
2357     }
2358 
2359     public int getIconWidth() {
2360         return 16;
2361     }
2362 
2363     public int getIconHeight() {
2364         return 15;
2365     }
2366 }
2367 
2368 private static class HorizontalSliderThumbIcon implements Icon, Serializable, UIResource {
2369     protected static MetalBumps controlBumps;
2370     protected static MetalBumps primaryBumps;
2371 
2372     public HorizontalSliderThumbIcon() {
2373         controlBumps = new MetalBumps( 10, 6,
2374                                 MetalLookAndFeel.getControlHighlight(),
2375                                 MetalLookAndFeel.getControlInfo(),
2376                                 MetalLookAndFeel.getControl() );
2377         primaryBumps = new MetalBumps( 10, 6,
2378                                 MetalLookAndFeel.getPrimaryControl(),
2379                                 MetalLookAndFeel.getPrimaryControlDarkShadow(),
2380                                 MetalLookAndFeel.getPrimaryControlShadow() );
2381     }
2382 
2383     public void paintIcon( Component c, Graphics g, int x, int y ) {
2384         g.translate( x, y );
2385 
2386         // Draw the frame
2387         if ( c.hasFocus() ) {
2388             g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
2389         }
2390         else {
2391             g.setColor( c.isEnabled() ? MetalLookAndFeel.getPrimaryControlInfo() :
2392                                              MetalLookAndFeel.getControlDarkShadow() );
2393         }
2394 
2395         g.drawLine(  1,0  , 13,0 );  // top
2396         g.drawLine(  0,1  ,  0,8 );  // left
2397         g.drawLine( 14,1  , 14,8 );  // right
2398         g.drawLine(  1,9  ,  7,15 ); // left slant
2399         g.drawLine(  7,15 , 14,8 );  // right slant
2400 
2401         // Fill in the background
2402         if ( c.hasFocus() ) {
2403             g.setColor( c.getForeground() );
2404         }
2405         else {
2406             g.setColor( MetalLookAndFeel.getControl() );
2407         }
2408         g.fillRect( 1,1, 13, 8 );
2409 
2410         g.drawLine( 2,9  , 12,9 );
2411         g.drawLine( 3,10 , 11,10 );
2412         g.drawLine( 4,11 , 10,11 );
2413         g.drawLine( 5,12 ,  9,12 );
2414         g.drawLine( 6,13 ,  8,13 );
2415         g.drawLine( 7,14 ,  7,14 );
2416 
2417         // Draw the bumps
2418         if ( c.isEnabled() ) {
2419             if ( c.hasFocus() ) {
2420                 primaryBumps.paintIcon( c, g, 2, 2 );
2421             }
2422             else {
2423                 controlBumps.paintIcon( c, g, 2, 2 );
2424             }
2425         }
2426 
2427         // Draw the highlight
2428         if ( c.isEnabled() ) {
2429             g.setColor( c.hasFocus() ? MetalLookAndFeel.getPrimaryControl()
2430                         : MetalLookAndFeel.getControlHighlight() );
2431             g.drawLine( 1, 1, 13, 1 );
2432             g.drawLine( 1, 1, 1, 8 );
2433         }
2434 
2435         g.translate( -x, -y );
2436     }
2437 
2438     public int getIconWidth() {
2439         return 15;
2440     }
2441 
2442     public int getIconHeight() {
2443         return 16;
2444     }
2445 }
2446 
2447     private static class OceanVerticalSliderThumbIcon extends CachedPainter
2448                               implements Icon, Serializable, UIResource {
2449         // Used for clipping when the orientation is left to right
2450         private static Polygon LTR_THUMB_SHAPE;
2451         // Used for clipping when the orientation is right to left
2452         private static Polygon RTL_THUMB_SHAPE;
2453 
2454         static {
2455             LTR_THUMB_SHAPE = new Polygon(new int[] { 0,  8, 15,  8,  0},
2456                                           new int[] { 0,  0,  7, 14, 14 }, 5);
2457             RTL_THUMB_SHAPE = new Polygon(new int[] { 15, 15,  7,  0,  7},
2458                                           new int[] {  0, 14, 14,  7,  0}, 5);
2459         }
2460 
2461         OceanVerticalSliderThumbIcon() {
2462             super(3);
2463         }
2464 
2465         public void paintIcon(Component c, Graphics g, int x, int y) {
2466             if (!(g instanceof Graphics2D)) {
2467                 return;
2468             }
2469             paint(c, g, x, y, getIconWidth(), getIconHeight(),
2470                   MetalUtils.isLeftToRight(c), c.hasFocus(), c.isEnabled(),
2471                   MetalLookAndFeel.getCurrentTheme());
2472         }
2473 
2474         protected void paintToImage(Component c, Image image, Graphics g2,
2475                                     int w, int h, Object[] args) {
2476             Graphics2D g = (Graphics2D)g2;
2477             boolean leftToRight = ((Boolean)args[0]).booleanValue();
2478             boolean hasFocus = ((Boolean)args[1]).booleanValue();
2479             boolean enabled = ((Boolean)args[2]).booleanValue();
2480 
2481             Rectangle clip = g.getClipBounds();
2482             if (leftToRight) {
2483                 g.clip(LTR_THUMB_SHAPE);
2484             }
2485             else {
2486                 g.clip(RTL_THUMB_SHAPE);
2487             }
2488             if (!enabled) {
2489                 g.setColor(MetalLookAndFeel.getControl());
2490                 g.fillRect(1, 1, 14, 14);
2491             }
2492             else if (hasFocus) {
2493                 MetalUtils.drawGradient(c, g, "Slider.focusGradient",
2494                                         1, 1, 14, 14, false);
2495             }
2496             else {
2497                 MetalUtils.drawGradient(c, g, "Slider.gradient",
2498                                         1, 1, 14, 14, false);
2499             }
2500             g.setClip(clip);
2501 
2502             // Draw the frame
2503             if (hasFocus) {
2504                 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
2505             }
2506             else {
2507                 g.setColor(enabled ? MetalLookAndFeel.getPrimaryControlInfo() :
2508                            MetalLookAndFeel.getControlDarkShadow());
2509             }
2510 
2511             if (leftToRight) {
2512                 g.drawLine(  1,0  ,  8,0  ); // top
2513                 g.drawLine(  0,1  ,  0,13 ); // left
2514                 g.drawLine(  1,14 ,  8,14 ); // bottom
2515                 g.drawLine(  9,1  , 15,7  ); // top slant
2516                 g.drawLine(  9,13 , 15,7  ); // bottom slant
2517             }
2518             else {
2519                 g.drawLine(  7,0  , 14,0  ); // top
2520                 g.drawLine( 15,1  , 15,13 ); // right
2521                 g.drawLine(  7,14 , 14,14 ); // bottom
2522                 g.drawLine(  0,7  ,  6,1  ); // top slant
2523                 g.drawLine(  0,7  ,  6,13 ); // bottom slant
2524             }
2525 
2526             if (hasFocus && enabled) {
2527                 // Inner line.
2528                 g.setColor(MetalLookAndFeel.getPrimaryControl());
2529                 if (leftToRight) {
2530                     g.drawLine(  1,1  ,  8,1  ); // top
2531                     g.drawLine(  1,1  ,  1,13 ); // left
2532                     g.drawLine(  1,13 ,  8,13 ); // bottom
2533                     g.drawLine(  9,2  , 14,7  ); // top slant
2534                     g.drawLine(  9,12 , 14,7  ); // bottom slant
2535                 }
2536                 else {
2537                     g.drawLine(  7,1  , 14,1  ); // top
2538                     g.drawLine( 14,1  , 14,13 ); // right
2539                     g.drawLine(  7,13 , 14,13 ); // bottom
2540                     g.drawLine(  1,7  ,  7,1  ); // top slant
2541                     g.drawLine(  1,7  ,  7,13 ); // bottom slant
2542                 }
2543             }
2544         }
2545 
2546         public int getIconWidth() {
2547             return 16;
2548         }
2549 
2550         public int getIconHeight() {
2551             return 15;
2552         }
2553 
2554         protected Image createImage(Component c, int w, int h,
2555                                     GraphicsConfiguration config,
2556                                     Object[] args) {
2557             if (config == null) {
2558                 return new BufferedImage(w, h,BufferedImage.TYPE_INT_ARGB);
2559             }
2560             return config.createCompatibleImage(
2561                                 w, h, Transparency.BITMASK);
2562         }
2563     }
2564 
2565 
2566     private static class OceanHorizontalSliderThumbIcon extends CachedPainter
2567                               implements Icon, Serializable, UIResource {
2568         // Used for clipping
2569         private static Polygon THUMB_SHAPE;
2570 
2571         static {
2572             THUMB_SHAPE = new Polygon(new int[] { 0, 14, 14,  7,  0 },
2573                                       new int[] { 0,  0,  8, 15,  8 }, 5);
2574         }
2575 
2576         OceanHorizontalSliderThumbIcon() {
2577             super(3);
2578         }
2579 
2580         public void paintIcon(Component c, Graphics g, int x, int y) {
2581             if (!(g instanceof Graphics2D)) {
2582                 return;
2583             }
2584             paint(c, g, x, y, getIconWidth(), getIconHeight(),
2585                   c.hasFocus(), c.isEnabled(),
2586                   MetalLookAndFeel.getCurrentTheme());
2587         }
2588 
2589 
2590         protected Image createImage(Component c, int w, int h,
2591                                     GraphicsConfiguration config,
2592                                     Object[] args) {
2593             if (config == null) {
2594                 return new BufferedImage(w, h,BufferedImage.TYPE_INT_ARGB);
2595             }
2596             return config.createCompatibleImage(
2597                                 w, h, Transparency.BITMASK);
2598         }
2599 
2600         protected void paintToImage(Component c, Image image, Graphics g2,
2601                                     int w, int h, Object[] args) {
2602             Graphics2D g = (Graphics2D)g2;
2603             boolean hasFocus = ((Boolean)args[0]).booleanValue();
2604             boolean enabled = ((Boolean)args[1]).booleanValue();
2605 
2606             // Fill in the background
2607             Rectangle clip = g.getClipBounds();
2608             g.clip(THUMB_SHAPE);
2609             if (!enabled) {
2610                 g.setColor(MetalLookAndFeel.getControl());
2611                 g.fillRect(1, 1, 13, 14);
2612             }
2613             else if (hasFocus) {
2614                 MetalUtils.drawGradient(c, g, "Slider.focusGradient",
2615                                         1, 1, 13, 14, true);
2616             }
2617             else {
2618                 MetalUtils.drawGradient(c, g, "Slider.gradient",
2619                                         1, 1, 13, 14, true);
2620             }
2621             g.setClip(clip);
2622 
2623             // Draw the frame
2624             if (hasFocus) {
2625                 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
2626             }
2627             else {
2628                 g.setColor(enabled ? MetalLookAndFeel.getPrimaryControlInfo() :
2629                            MetalLookAndFeel.getControlDarkShadow());
2630             }
2631 
2632             g.drawLine(  1,0  , 13,0 );  // top
2633             g.drawLine(  0,1  ,  0,8 );  // left
2634             g.drawLine( 14,1  , 14,8 );  // right
2635             g.drawLine(  1,9  ,  7,15 ); // left slant
2636             g.drawLine(  7,15 , 14,8 );  // right slant
2637 
2638             if (hasFocus && enabled) {
2639                 // Inner line.
2640                 g.setColor(MetalLookAndFeel.getPrimaryControl());
2641                 g.fillRect(1, 1, 13, 1);
2642                 g.fillRect(1, 2, 1, 7);
2643                 g.fillRect(13, 2, 1, 7);
2644                 g.drawLine(2, 9, 7, 14);
2645                 g.drawLine(8, 13, 12, 9);
2646             }
2647         }
2648 
2649         public int getIconWidth() {
2650             return 15;
2651         }
2652 
2653         public int getIconHeight() {
2654             return 16;
2655         }
2656     }
2657 }