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