/*
 * @(#)MetalIconFactory.java	1.52 01/12/03
 *
 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package javax.swing.plaf.metal;

import javax.swing.*;
import javax.swing.plaf.UIResource;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;

/**
 * Factory object that vends <code>Icon</code>s for
 * the Java<sup><font size="-2">TM</font></sup> look and feel (Metal).
 * These icons are used extensively in Metal via the defaults mechanism.
 * While other look and feels often use GIFs for icons, creating icons
 * in code facilitates switching to other themes.
 *
 * <p>
 * Each method in this class returns
 * either an <code>Icon</code> or <code>null</code>,
 * where <code>null</code> implies that there is no default icon.
 *
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases. The current serialization support is
 * appropriate for short term storage or RMI between applications running
 * the same version of Swing.  As of 1.4, support for long term storage
 * of all JavaBeans<sup><font size="-2">TM</font></sup>
 * has been added to the <code>java.beans</code> package.
 * Please see {@link java.beans.XMLEncoder}.
 *
 * @version 1.52 12/03/01
 * @author Michael C. Albers
 */
public class MetalIconFactory implements Serializable {

    // List of code-drawn Icons
    private static Icon fileChooserDetailViewIcon;
    private static Icon fileChooserHomeFolderIcon;
    private static Icon fileChooserListViewIcon;
    private static Icon fileChooserNewFolderIcon;
    private static Icon fileChooserUpFolderIcon;
    private static Icon internalFrameAltMaximizeIcon;
    private static Icon internalFrameCloseIcon;
    private static Icon internalFrameDefaultMenuIcon;
    private static Icon internalFrameMaximizeIcon;
    private static Icon internalFrameMinimizeIcon;
    private static Icon radioButtonIcon; 
    private static Icon treeComputerIcon;
    private static Icon treeFloppyDriveIcon;
    private static Icon treeHardDriveIcon;


    private static Icon menuArrowIcon;
    private static Icon menuItemArrowIcon;
    private static Icon checkBoxMenuItemIcon;
    private static Icon radioButtonMenuItemIcon;
    private static Icon checkBoxIcon;


    // Constants
    public static final boolean DARK = false;
    public static final boolean LIGHT = true;

    // Accessor functions for Icons. Does the caching work.
    public static Icon getFileChooserDetailViewIcon() {
	if (fileChooserDetailViewIcon == null) {
	    fileChooserDetailViewIcon = new FileChooserDetailViewIcon();
	}
	return fileChooserDetailViewIcon;
    }

    public static Icon getFileChooserHomeFolderIcon() {
	if (fileChooserHomeFolderIcon == null) {
	    fileChooserHomeFolderIcon = new FileChooserHomeFolderIcon();
	}
	return fileChooserHomeFolderIcon;
    }

    public static Icon getFileChooserListViewIcon() {
	if (fileChooserListViewIcon == null) {
	    fileChooserListViewIcon = new FileChooserListViewIcon();
	}
	return fileChooserListViewIcon;
    }

    public static Icon getFileChooserNewFolderIcon() {
	if (fileChooserNewFolderIcon == null) {
	    fileChooserNewFolderIcon = new FileChooserNewFolderIcon();
	}
	return fileChooserNewFolderIcon;
    }

    public static Icon getFileChooserUpFolderIcon() {
	if (fileChooserUpFolderIcon == null) {
	    fileChooserUpFolderIcon = new FileChooserUpFolderIcon();
	}
	return fileChooserUpFolderIcon;
    }

    public static Icon getInternalFrameAltMaximizeIcon(int size) {
	return new InternalFrameAltMaximizeIcon(size);
    }

    public static Icon getInternalFrameCloseIcon(int size) {
	return new InternalFrameCloseIcon(size);
    }

    public static Icon getInternalFrameDefaultMenuIcon() {
	if (internalFrameDefaultMenuIcon == null) {
	    internalFrameDefaultMenuIcon = new InternalFrameDefaultMenuIcon();
	}
	return internalFrameDefaultMenuIcon;
    }

    public static Icon getInternalFrameMaximizeIcon(int size) {
	return new InternalFrameMaximizeIcon(size);
    }

    public static Icon getInternalFrameMinimizeIcon(int size) {
	return new InternalFrameMinimizeIcon(size);
    }

    public static Icon getRadioButtonIcon() {
	if (radioButtonIcon == null) {
	    radioButtonIcon = new RadioButtonIcon();
	}
	return radioButtonIcon;
    }

    /**
     * Returns a checkbox icon.
     * @since 1.3
     */
    public static Icon getCheckBoxIcon() {
	if (checkBoxIcon == null) {
	    checkBoxIcon = new CheckBoxIcon();
	}
	return checkBoxIcon;
    }

    public static Icon getTreeComputerIcon() {
        if ( treeComputerIcon == null ) {
	    treeComputerIcon = new TreeComputerIcon();
	}
	return treeComputerIcon;
    }

    public static Icon getTreeFloppyDriveIcon() {
        if ( treeFloppyDriveIcon == null ) {
	    treeFloppyDriveIcon = new TreeFloppyDriveIcon();
	}
	return treeFloppyDriveIcon;
    }

    public static Icon getTreeFolderIcon() {
	return new TreeFolderIcon();
    }

    public static Icon getTreeHardDriveIcon() {
        if ( treeHardDriveIcon == null ) {
	    treeHardDriveIcon = new TreeHardDriveIcon();
	}
	return treeHardDriveIcon;
    }

    public static Icon getTreeLeafIcon() {
	return new TreeLeafIcon();
    }

    public static Icon getTreeControlIcon( boolean isCollapsed ) {
	    return new TreeControlIcon( isCollapsed );
    }

    public static Icon getMenuArrowIcon() {
	if (menuArrowIcon == null) {
	    menuArrowIcon = new MenuArrowIcon();
	}
	return menuArrowIcon;
    }

    /**
     * Returns an icon to be used by <code>JCheckBoxMenuItem</code>.
     *
     * @return the default icon for check box menu items,
     *         or <code>null</code> if no default exists
     */
    public static Icon getMenuItemCheckIcon() {
        return null;
    }

    public static Icon getMenuItemArrowIcon() {
	if (menuItemArrowIcon == null) {
	    menuItemArrowIcon = new MenuItemArrowIcon();
	}
	return menuItemArrowIcon;
    }

    public static Icon getCheckBoxMenuItemIcon() {
	if (checkBoxMenuItemIcon == null) {
	    checkBoxMenuItemIcon = new CheckBoxMenuItemIcon();
	}
	return checkBoxMenuItemIcon;
    }

    public static Icon getRadioButtonMenuItemIcon() {
	if (radioButtonMenuItemIcon == null) {
	    radioButtonMenuItemIcon = new RadioButtonMenuItemIcon();
	}
	return radioButtonMenuItemIcon;
    }

    public static Icon getHorizontalSliderThumbIcon() {
      // don't cache these, bumps don't get updated otherwise
	return new HorizontalSliderThumbIcon();
    }

    public static Icon getVerticalSliderThumbIcon() {
      // don't cache these, bumps don't get updated otherwise
	return new VerticalSliderThumbIcon();
    }

    // File Chooser Detail View code
    private static class FileChooserDetailViewIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    g.translate(x, y);

	    // Draw outside edge of each of the documents
	    g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
	    //     top
	    g.drawLine(2,2, 5,2); // top
	    g.drawLine(2,3, 2,7); // left
	    g.drawLine(3,7, 6,7); // bottom
	    g.drawLine(6,6, 6,3); // right
	    //     bottom
	    g.drawLine(2,10, 5,10); // top
	    g.drawLine(2,11, 2,15); // left
	    g.drawLine(3,15, 6,15); // bottom
	    g.drawLine(6,14, 6,11); // right

	    // Draw little dots next to documents
	    //     Same color as outside edge
	    g.drawLine(8,5, 15,5);     // top
	    g.drawLine(8,13, 15,13);   // bottom

	    // Draw inner highlight on documents
	    g.setColor(MetalLookAndFeel.getPrimaryControl());
	    g.drawRect(3,3, 2,3);   // top
	    g.drawRect(3,11, 2,3);  // bottom

	    // Draw inner inner highlight on documents
	    g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
	    g.drawLine(4,4, 4,5);     // top
	    g.drawLine(4,12, 4,13);   // bottom
	    
	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 18;
	}
	
	public int getIconHeight() {
	    return 18;
	}
    }  // End class FileChooserDetailViewIcon

    // File Chooser Home Folder code
    private static class FileChooserHomeFolderIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    g.translate(x, y);

	    // Draw outside edge of house
	    g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
	    g.drawLine(8,1, 1,8);  // left edge of roof
	    g.drawLine(8,1, 15,8); // right edge of roof
	    g.drawLine(11,2, 11,3); // left edge of chimney
	    g.drawLine(12,2, 12,4); // right edge of chimney
	    g.drawLine(3,7, 3,15); // left edge of house
	    g.drawLine(13,7, 13,15); // right edge of house
	    g.drawLine(4,15, 12,15); // bottom edge of house
	    // Draw door frame
	    //     same color as edge of house
	    g.drawLine( 6,9,  6,14); // left
	    g.drawLine(10,9, 10,14); // right
	    g.drawLine( 7,9,  9, 9); // top

	    // Draw roof body
    	    g.setColor(MetalLookAndFeel.getControlDarkShadow());
	    g.fillRect(8,2, 1,1); //top toward bottom
	    g.fillRect(7,3, 3,1);
	    g.fillRect(6,4, 5,1);
	    g.fillRect(5,5, 7,1);
	    g.fillRect(4,6, 9,2);
	    // Draw doornob
	    //     same color as roof body
	    g.drawLine(9,12, 9,12);

	    // Paint the house
	    g.setColor(MetalLookAndFeel.getPrimaryControl());
	    g.drawLine(4,8, 12,8); // above door
	    g.fillRect(4,9, 2,6); // left of door
	    g.fillRect(11,9, 2,6); // right of door

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 18;
	}
	
	public int getIconHeight() {
	    return 18;
	}
    }  // End class FileChooserHomeFolderIcon

    // File Chooser List View code
    private static class FileChooserListViewIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    g.translate(x, y);

	    // Draw outside edge of each of the documents
	    g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
	    //     top left
	    g.drawLine(2,2, 5,2); // top
	    g.drawLine(2,3, 2,7); // left
	    g.drawLine(3,7, 6,7); // bottom
	    g.drawLine(6,6, 6,3); // right
	    //     top right
	    g.drawLine(10,2, 13,2); // top
	    g.drawLine(10,3, 10,7); // left
	    g.drawLine(11,7, 14,7); // bottom
	    g.drawLine(14,6, 14,3); // right
	    //     bottom left
	    g.drawLine(2,10, 5,10); // top
	    g.drawLine(2,11, 2,15); // left
	    g.drawLine(3,15, 6,15); // bottom
	    g.drawLine(6,14, 6,11); // right
	    //     bottom right
	    g.drawLine(10,10, 13,10); // top
	    g.drawLine(10,11, 10,15); // left
	    g.drawLine(11,15, 14,15); // bottom
	    g.drawLine(14,14, 14,11); // right

	    // Draw little dots next to documents
	    //     Same color as outside edge
	    g.drawLine(8,5, 8,5);     // top left
	    g.drawLine(16,5, 16,5);   // top right
	    g.drawLine(8,13, 8,13);   // bottom left
	    g.drawLine(16,13, 16,13); // bottom right

	    // Draw inner highlight on documents
	    g.setColor(MetalLookAndFeel.getPrimaryControl());
	    g.drawRect(3,3, 2,3);   // top left
	    g.drawRect(11,3, 2,3);  // top right
	    g.drawRect(3,11, 2,3);  // bottom left
	    g.drawRect(11,11, 2,3); // bottom right

	    // Draw inner inner highlight on documents
	    g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
	    g.drawLine(4,4, 4,5);     // top left
	    g.drawLine(12,4, 12,5);   // top right
	    g.drawLine(4,12, 4,13);   // bottom left
	    g.drawLine(12,12, 12,13); // bottom right
	    
	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 18;
	}
	
	public int getIconHeight() {
	    return 18;
	}
    }  // End class FileChooserListViewIcon

    // File Chooser New Folder code
    private static class FileChooserNewFolderIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    g.translate(x, y);

	    // Fill background
	    g.setColor(MetalLookAndFeel.getPrimaryControl());
	    g.fillRect(3,5, 12,9);

	    // Draw outside edge of folder
	    g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
	    g.drawLine(1,6,    1,14); // left
	    g.drawLine(2,14,  15,14); // bottom
	    g.drawLine(15,13, 15,5);  // right
	    g.drawLine(2,5,    9,5);  // top left
	    g.drawLine(10,6,  14,6);  // top right

	    // Draw inner folder highlight
	    g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
	    g.drawLine( 2,6,  2,13); // left
	    g.drawLine( 3,6,  9,6);  // top left
	    g.drawLine(10,7, 14,7);  // top right

	    // Draw tab on folder
	    g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
	    g.drawLine(11,3, 15,3); // top
	    g.drawLine(10,4, 15,4); // bottom

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 18;
	}
	
	public int getIconHeight() {
	    return 18;
	}
    }  // End class FileChooserNewFolderIcon

    // File Chooser Up Folder code
    private static class FileChooserUpFolderIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    g.translate(x, y);

	    // Fill background
	    g.setColor(MetalLookAndFeel.getPrimaryControl());
	    g.fillRect(3,5, 12,9);

	    // Draw outside edge of folder
	    g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
	    g.drawLine(1,6,    1,14); // left
	    g.drawLine(2,14,  15,14); // bottom
	    g.drawLine(15,13, 15,5);  // right
	    g.drawLine(2,5,    9,5);  // top left
	    g.drawLine(10,6,  14,6);  // top right
	    // Draw the UP arrow
	    //     same color as edge
	    g.drawLine(8,13,  8,16); // arrow shaft
	    g.drawLine(8, 9,  8, 9); // arrowhead top
	    g.drawLine(7,10,  9,10);
	    g.drawLine(6,11, 10,11);
	    g.drawLine(5,12, 11,12);

	    // Draw inner folder highlight
	    g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
	    g.drawLine( 2,6,  2,13); // left
	    g.drawLine( 3,6,  9,6);  // top left
	    g.drawLine(10,7, 14,7);  // top right

	    // Draw tab on folder
	    g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
	    g.drawLine(11,3, 15,3); // top
	    g.drawLine(10,4, 15,4); // bottom

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 18;
	}
	
	public int getIconHeight() {
	    return 18;
	}
    }  // End class FileChooserUpFolderIcon


    /**
     * Defines an icon for Palette close
     * @since 1.3
     */
    public static class PaletteCloseIcon implements Icon, UIResource, Serializable{
        int iconSize = 7;

        public void paintIcon(Component c, Graphics g, int x, int y) {
	    JButton parentButton = (JButton)c;
	    ButtonModel buttonModel = parentButton.getModel();

	    Color back;
	    Color highlight = MetalLookAndFeel.getPrimaryControlHighlight();
	    Color shadow = MetalLookAndFeel.getPrimaryControlInfo();
	    if (buttonModel.isPressed() && buttonModel.isArmed()) {
	        back = shadow;
	    } else {
	        back = MetalLookAndFeel.getPrimaryControlDarkShadow();
	    }

	    g.translate(x, y);
	    g.setColor(back);
	    g.drawLine( 0, 1, 5, 6);
	    g.drawLine( 1, 0, 6, 5);
	    g.drawLine( 1, 1, 6, 6);
	    g.drawLine( 6, 1, 1, 6);
	    g.drawLine( 5,0, 0,5);
	    g.drawLine(5,1, 1,5);
	   
	    g.setColor(highlight);
	    g.drawLine(6,2, 5,3);
	    g.drawLine(2,6, 3, 5);
	    g.drawLine(6,6,6,6);


	    g.translate(-x, -y);
	}

	public int getIconWidth() {
	    return iconSize;
	}
	
	public int getIconHeight() {
	    return iconSize;
	}
    }

    // Internal Frame Close code
    private static class InternalFrameCloseIcon implements Icon, UIResource, Serializable {
	int iconSize = 16;
	
        public InternalFrameCloseIcon(int size) {
	    iconSize = size;
	}
	
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    JButton parentButton = (JButton)c;
	    ButtonModel buttonModel = parentButton.getModel();

	    Color backgroundColor = MetalLookAndFeel.getPrimaryControl();
	    Color internalBackgroundColor = 
		MetalLookAndFeel.getPrimaryControl();
	    Color mainItemColor = 
		MetalLookAndFeel.getPrimaryControlDarkShadow();
	    Color darkHighlightColor = MetalLookAndFeel.getBlack();
	    Color xLightHighlightColor = MetalLookAndFeel.getWhite();
	    Color boxLightHighlightColor = MetalLookAndFeel.getWhite();
	    
	    // if the inactive window
	    if (parentButton.getClientProperty("paintActive") != Boolean.TRUE)
	    {
		backgroundColor = MetalLookAndFeel.getControl();
		internalBackgroundColor = backgroundColor;
		mainItemColor = MetalLookAndFeel.getControlDarkShadow();
		// if inactive and pressed
		if (buttonModel.isPressed() && buttonModel.isArmed()) {
		    internalBackgroundColor =
			MetalLookAndFeel.getControlShadow();
		    xLightHighlightColor = internalBackgroundColor;
		    mainItemColor = darkHighlightColor;
		}
	    }
	    // if pressed
	    else if (buttonModel.isPressed() && buttonModel.isArmed()) {
		internalBackgroundColor =
		    MetalLookAndFeel.getPrimaryControlShadow();
		xLightHighlightColor = internalBackgroundColor;
		mainItemColor = darkHighlightColor;
		// darkHighlightColor is still "getBlack()"
	    }

	    // Some calculations that are needed more than once later on.
	    int oneHalf = (int)(iconSize / 2); // 16 -> 8

	    g.translate(x, y);

	    // fill background
	    g.setColor(backgroundColor);
	    g.fillRect(0,0, iconSize,iconSize);
	    
	    // fill inside of box area
	    g.setColor(internalBackgroundColor);
	    g.fillRect(3,3, iconSize-6,iconSize-6);

	    // THE BOX
	    // the top/left dark higlight - some of this will get overwritten
	    g.setColor(darkHighlightColor);
	    g.drawRect(1,1, iconSize-3,iconSize-3);
	    // draw the inside bottom/right highlight
	    g.drawRect(2,2, iconSize-5,iconSize-5);
	    // draw the light/outside, bottom/right highlight
	    g.setColor(boxLightHighlightColor);
	    g.drawRect(2,2, iconSize-3,iconSize-3);
	    // draw the "normal" box
	    g.setColor(mainItemColor);
	    g.drawRect(2,2, iconSize-4,iconSize-4);
	    g.drawLine(3,iconSize-3, 3,iconSize-3); // lower left
	    g.drawLine(iconSize-3,3, iconSize-3,3); // up right

	    // THE "X"
	    // Dark highlight
	    g.setColor(darkHighlightColor);
	    g.drawLine(4,5, 5,4); // far up left
	    g.drawLine(4,iconSize-6, iconSize-6,4); // against body of "X"
	    // Light highlight
	    g.setColor(xLightHighlightColor);
	    g.drawLine(6,iconSize-5, iconSize-5,6); // against body of "X"
	      // one pixel over from the body
	    g.drawLine(oneHalf,oneHalf+2, oneHalf+2,oneHalf);
	      // bottom right
	    g.drawLine(iconSize-5,iconSize-5, iconSize-4,iconSize-5);
	    g.drawLine(iconSize-5,iconSize-4, iconSize-5,iconSize-4);
	    // Main color
	    g.setColor(mainItemColor);
	      // Upper left to lower right
	    g.drawLine(5,5, iconSize-6,iconSize-6); // g.drawLine(5,5, 10,10);
	    g.drawLine(6,5, iconSize-5,iconSize-6); // g.drawLine(6,5, 11,10);
	    g.drawLine(5,6, iconSize-6,iconSize-5); // g.drawLine(5,6, 10,11);
	      // Lower left to upper right
	    g.drawLine(5,iconSize-5, iconSize-5,5); // g.drawLine(5,11, 11,5);
	    g.drawLine(5,iconSize-6, iconSize-6,5); // g.drawLine(5,10, 10,5);
	    
	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return iconSize;
	}

	public int getIconHeight() {
	    return iconSize;
	}
    }  // End class InternalFrameCloseIcon

    // Internal Frame Alternate Maximize code (actually, the un-maximize icon)
    private static class InternalFrameAltMaximizeIcon implements Icon, UIResource, Serializable {
	int iconSize = 16;

        public InternalFrameAltMaximizeIcon(int size) {
	    iconSize = size;
	}

        public void paintIcon(Component c, Graphics g, int x, int y) {
	    JButton parentButton = (JButton)c;
	    ButtonModel buttonModel = parentButton.getModel();

	    Color backgroundColor = MetalLookAndFeel.getPrimaryControl();
	    Color internalBackgroundColor = 
		MetalLookAndFeel.getPrimaryControl();
	    Color mainItemColor = 
		MetalLookAndFeel.getPrimaryControlDarkShadow();
	    Color darkHighlightColor = MetalLookAndFeel.getBlack();
	    // ul = Upper Left and lr = Lower Right
	    Color ulLightHighlightColor = MetalLookAndFeel.getWhite();
	    Color lrLightHighlightColor = MetalLookAndFeel.getWhite();
	    
	    // if the internal frame is inactive
	    if (parentButton.getClientProperty("paintActive") != Boolean.TRUE)
	    {
		backgroundColor = MetalLookAndFeel.getControl();
		internalBackgroundColor = backgroundColor;
		mainItemColor = MetalLookAndFeel.getControlDarkShadow();
		// if inactive and pressed
		if (buttonModel.isPressed() && buttonModel.isArmed()) {
		    internalBackgroundColor =
			MetalLookAndFeel.getControlShadow();
		    ulLightHighlightColor = internalBackgroundColor;
		    mainItemColor = darkHighlightColor;
		}
	    }
	    // if the button is pressed and the mouse is over it
	    else if (buttonModel.isPressed() && buttonModel.isArmed()) {
		internalBackgroundColor =
		    MetalLookAndFeel.getPrimaryControlShadow();
		ulLightHighlightColor = internalBackgroundColor;
		mainItemColor = darkHighlightColor;
		// darkHighlightColor is still "getBlack()"
	    }

	    g.translate(x, y);

	    // fill background
	    g.setColor(backgroundColor);
	    g.fillRect(0,0, iconSize,iconSize);

	    // BOX
	    // fill inside the box
	    g.setColor(internalBackgroundColor);
	    g.fillRect(3,6, iconSize-9,iconSize-9);

	    // draw dark highlight color
	    g.setColor(darkHighlightColor);
	    g.drawRect(1,5, iconSize-8,iconSize-8);
	    g.drawLine(1,iconSize-2, 1,iconSize-2); // extra pixel on bottom

	    // draw lower right light highlight
	    g.setColor(lrLightHighlightColor);
	    g.drawRect(2,6, iconSize-7,iconSize-7);
	    // draw upper left light highlight
	    g.setColor(ulLightHighlightColor);
	    g.drawRect(3,7, iconSize-9,iconSize-9);

	    // draw the main box
	    g.setColor(mainItemColor);
	    g.drawRect(2,6, iconSize-8,iconSize-8);

	    // Six extraneous pixels to deal with
	    g.setColor(ulLightHighlightColor);
	    g.drawLine(iconSize-6,8,iconSize-6,8);
	    g.drawLine(iconSize-9,6, iconSize-7,8);
	    g.setColor(mainItemColor);
	    g.drawLine(3,iconSize-3,3,iconSize-3);
	    g.setColor(darkHighlightColor);
	    g.drawLine(iconSize-6,9,iconSize-6,9);
	    g.setColor(backgroundColor);
	    g.drawLine(iconSize-9,5,iconSize-9,5);

	    // ARROW
	    // do the shaft first
	    g.setColor(mainItemColor);
	    g.fillRect(iconSize-7,3, 3,5); // do a big block
	    g.drawLine(iconSize-6,5, iconSize-3,2); // top shaft
	    g.drawLine(iconSize-6,6, iconSize-2,2); // bottom shaft
	    g.drawLine(iconSize-6,7, iconSize-3,7); // bottom arrow head

	    // draw the dark highlight
	    g.setColor(darkHighlightColor);
	    g.drawLine(iconSize-8,2, iconSize-7,2); // top of arrowhead
	    g.drawLine(iconSize-8,3, iconSize-8,7); // left of arrowhead
	    g.drawLine(iconSize-6,4, iconSize-3,1); // top of shaft
	    g.drawLine(iconSize-4,6, iconSize-3,6); // top,right of arrowhead

	    // draw the light highlight
	    g.setColor(lrLightHighlightColor);
	    g.drawLine(iconSize-6,3, iconSize-6,3); // top
	    g.drawLine(iconSize-4,5, iconSize-2,3); // under shaft
	    g.drawLine(iconSize-4,8, iconSize-3,8); // under arrowhead
	    g.drawLine(iconSize-2,8, iconSize-2,7); // right of arrowhead

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return iconSize;
	}
	
	public int getIconHeight() {
	    return iconSize;
	}
    }  // End class InternalFrameAltMaximizeIcon

    // Code for the default icons that goes in the upper left corner
    private static class InternalFrameDefaultMenuIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {

	    Color windowBodyColor = MetalLookAndFeel.getWindowBackground();
	    Color titleColor = MetalLookAndFeel.getPrimaryControl();
	    Color edgeColor = MetalLookAndFeel.getPrimaryControlDarkShadow();

	    g.translate(x, y);

	    // draw background color for title area
	    // catch four corners and title area
	    g.setColor(titleColor);
	    g.fillRect(0,0, 16,16);

	    // fill body of window
	    g.setColor(windowBodyColor);
	    g.fillRect(2,6, 13,9);
	    // draw light parts of two "bumps"
	    g.drawLine(2,2, 2,2);
	    g.drawLine(5,2, 5,2);
	    g.drawLine(8,2, 8,2);
	    g.drawLine(11,2, 11,2);
	    
	    // draw line around edge of title and icon
	    g.setColor(edgeColor);
	    g.drawRect(1,1, 13,13); // entire inner edge
	    g.drawLine(1,0, 14,0); // top outter edge
	    g.drawLine(15,1, 15,14); // right outter edge
	    g.drawLine(1,15, 14,15); // bottom outter edge
	    g.drawLine(0,1, 0,14); // left outter edge
	    g.drawLine(2,5, 13,5); // bottom of title bar area
	    // draw dark part of four "bumps" (same color)
	    g.drawLine(3,3, 3,3);
	    g.drawLine(6,3, 6,3);
	    g.drawLine(9,3, 9,3);
	    g.drawLine(12,3, 12,3);

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 16;
	}
	
	public int getIconHeight() {
	    return 16;
	}
    }  // End class InternalFrameDefaultMenuIcon

    // Internal Frame Maximize code
    private static class InternalFrameMaximizeIcon implements Icon, UIResource, Serializable {
	protected int iconSize = 16;

        public InternalFrameMaximizeIcon(int size) {
	    iconSize = size;
	}

        public void paintIcon(Component c, Graphics g, int x, int y) {
	    JButton parentButton = (JButton)c;
	    ButtonModel buttonModel = parentButton.getModel();

	    Color backgroundColor = MetalLookAndFeel.getPrimaryControl();
	    Color internalBackgroundColor = 
		MetalLookAndFeel.getPrimaryControl();
	    Color mainItemColor = 
		MetalLookAndFeel.getPrimaryControlDarkShadow();
	    Color darkHighlightColor = MetalLookAndFeel.getBlack();
	    // ul = Upper Left and lr = Lower Right
	    Color ulLightHighlightColor = MetalLookAndFeel.getWhite();
	    Color lrLightHighlightColor = MetalLookAndFeel.getWhite();
	    
	    // if the internal frame is inactive
	    if (parentButton.getClientProperty("paintActive") != Boolean.TRUE)
	    {
		backgroundColor = MetalLookAndFeel.getControl();
		internalBackgroundColor = backgroundColor;
		mainItemColor = MetalLookAndFeel.getControlDarkShadow();
		// if inactive and pressed
		if (buttonModel.isPressed() && buttonModel.isArmed()) {
		    internalBackgroundColor =
			MetalLookAndFeel.getControlShadow();
		    ulLightHighlightColor = internalBackgroundColor;
		    mainItemColor = darkHighlightColor;
		}
	    }
	    // if the button is pressed and the mouse is over it
	    else if (buttonModel.isPressed() && buttonModel.isArmed()) {
		internalBackgroundColor =
		    MetalLookAndFeel.getPrimaryControlShadow();
		ulLightHighlightColor = internalBackgroundColor;
		mainItemColor = darkHighlightColor;
		// darkHighlightColor is still "getBlack()"
	    }

	    g.translate(x, y);

	    // fill background
	    g.setColor(backgroundColor);
	    g.fillRect(0,0, iconSize,iconSize);

	    // BOX drawing
	    // fill inside the box
	    g.setColor(internalBackgroundColor);
	    g.fillRect(3,7, iconSize-10,iconSize-10);

	    // light highlight
	    g.setColor(ulLightHighlightColor);
	    g.drawRect(3,7, iconSize-10,iconSize-10); // up,left
	    g.setColor(lrLightHighlightColor);
	    g.drawRect(2,6, iconSize-7,iconSize-7); // low,right
	    // dark highlight
	    g.setColor(darkHighlightColor);
	    g.drawRect(1,5, iconSize-7,iconSize-7); // outer
	    g.drawRect(2,6, iconSize-9,iconSize-9); // inner
	    // main box
	    g.setColor(mainItemColor);
	    g.drawRect(2,6, iconSize-8,iconSize-8); // g.drawRect(2,6, 8,8);

	    // ARROW drawing
	    // dark highlight
	    g.setColor(darkHighlightColor);
	      // down,left to up,right - inside box
	    g.drawLine(3,iconSize-5, iconSize-9,7);
	      // down,left to up,right - outside box
	    g.drawLine(iconSize-6,4, iconSize-5,3);
	      // outside edge of arrow head
	    g.drawLine(iconSize-7,1, iconSize-7,2);
	      // outside edge of arrow head
	    g.drawLine(iconSize-6,1, iconSize-2,1);
	    // light highlight
	    g.setColor(ulLightHighlightColor);
	      // down,left to up,right - inside box
	    g.drawLine(5,iconSize-4, iconSize-8,9);
	    g.setColor(lrLightHighlightColor);
	    g.drawLine(iconSize-6,3, iconSize-4,5); // outside box
	    g.drawLine(iconSize-4,5, iconSize-4,6); // one down from this
	    g.drawLine(iconSize-2,7, iconSize-1,7); // outside edge arrow head
	    g.drawLine(iconSize-1,2, iconSize-1,6); // outside edge arrow head
	    // main part of arrow
	    g.setColor(mainItemColor);
	    g.drawLine(3,iconSize-4, iconSize-3,2); // top edge of staff
	    g.drawLine(3,iconSize-3, iconSize-2,2); // bottom edge of staff
	    g.drawLine(4,iconSize-3, 5,iconSize-3); // highlights inside of box
	    g.drawLine(iconSize-7,8, iconSize-7,9); // highlights inside of box
	    g.drawLine(iconSize-6,2, iconSize-4,2); // top of arrow head
	    g.drawRect(iconSize-3,3, 1,3); // right of arrow head

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return iconSize;
	}
	
	public int getIconHeight() {
	    return iconSize;
	}
    }  // End class InternalFrameMaximizeIcon

    // Internal Frame Minimize code
    private static class InternalFrameMinimizeIcon implements Icon, UIResource, Serializable {
	int iconSize = 16;

        public InternalFrameMinimizeIcon(int size) {
	    iconSize = size;
	}

        public void paintIcon(Component c, Graphics g, int x, int y) {
	    JButton parentButton = (JButton)c;
	    ButtonModel buttonModel = parentButton.getModel();


	    Color backgroundColor = MetalLookAndFeel.getPrimaryControl();
	    Color internalBackgroundColor = 
		MetalLookAndFeel.getPrimaryControl();
	    Color mainItemColor = 
		MetalLookAndFeel.getPrimaryControlDarkShadow();
	    Color darkHighlightColor = MetalLookAndFeel.getBlack();
	    // ul = Upper Left and lr = Lower Right
	    Color ulLightHighlightColor = MetalLookAndFeel.getWhite();
	    Color lrLightHighlightColor = MetalLookAndFeel.getWhite();
	    
	    // if the internal frame is inactive
	    if (parentButton.getClientProperty("paintActive") != Boolean.TRUE)
	    {
		backgroundColor = MetalLookAndFeel.getControl();
		internalBackgroundColor = backgroundColor;
		mainItemColor = MetalLookAndFeel.getControlDarkShadow();
		// if inactive and pressed
		if (buttonModel.isPressed() && buttonModel.isArmed()) {
		    internalBackgroundColor =
			MetalLookAndFeel.getControlShadow();
		    ulLightHighlightColor = internalBackgroundColor;
		    mainItemColor = darkHighlightColor;
		}
	    }
	    // if the button is pressed and the mouse is over it
	    else if (buttonModel.isPressed() && buttonModel.isArmed()) {
		internalBackgroundColor =
		    MetalLookAndFeel.getPrimaryControlShadow();
		ulLightHighlightColor = internalBackgroundColor;
		mainItemColor = darkHighlightColor;
		// darkHighlightColor is still "getBlack()"
	    }

	    g.translate(x, y);

	    // fill background
	    g.setColor(backgroundColor);
	    g.fillRect(0,0, iconSize,iconSize);

	    // BOX drawing
	    // fill inside the box
	    g.setColor(internalBackgroundColor);
	    g.fillRect(4,11, iconSize-13,iconSize-13);
	    // light highlight
	    g.setColor(lrLightHighlightColor);
	    g.drawRect(2,10, iconSize-10,iconSize-11); // low,right
	    g.setColor(ulLightHighlightColor);
	    g.drawRect(3,10, iconSize-12,iconSize-12); // up,left
	    // dark highlight
	    g.setColor(darkHighlightColor);
	    g.drawRect(1,8, iconSize-10,iconSize-10); // outer
	    g.drawRect(2,9, iconSize-12,iconSize-12); // inner
	    // main box
	    g.setColor(mainItemColor);
	    g.drawRect(2,9, iconSize-11,iconSize-11);
	    g.drawLine(iconSize-10,10, iconSize-10,10); // up right highlight
	    g.drawLine(3,iconSize-3, 3,iconSize-3); // low left highlight

	    // ARROW
	    // do the shaft first
	    g.setColor(mainItemColor);
	    g.fillRect(iconSize-7,3, 3,5); // do a big block
	    g.drawLine(iconSize-6,5, iconSize-3,2); // top shaft
	    g.drawLine(iconSize-6,6, iconSize-2,2); // bottom shaft
	    g.drawLine(iconSize-6,7, iconSize-3,7); // bottom arrow head

	    // draw the dark highlight
	    g.setColor(darkHighlightColor);
	    g.drawLine(iconSize-8,2, iconSize-7,2); // top of arrowhead
	    g.drawLine(iconSize-8,3, iconSize-8,7); // left of arrowhead
	    g.drawLine(iconSize-6,4, iconSize-3,1); // top of shaft
	    g.drawLine(iconSize-4,6, iconSize-3,6); // top,right of arrowhead

	    // draw the light highlight
	    g.setColor(lrLightHighlightColor);
	    g.drawLine(iconSize-6,3, iconSize-6,3); // top
	    g.drawLine(iconSize-4,5, iconSize-2,3); // under shaft
	    g.drawLine(iconSize-7,8, iconSize-3,8); // under arrowhead
	    g.drawLine(iconSize-2,8, iconSize-2,7); // right of arrowhead

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return iconSize;
	}
	
	public int getIconHeight() {
	    return iconSize;
	}
    }  // End class InternalFrameMinimizeIcon

    private static class CheckBoxIcon implements Icon, UIResource, Serializable {
	
	protected int getControlSize() { return 13; }
	
	public void paintIcon(Component c, Graphics g, int x, int y) {
	    
	    JCheckBox cb = (JCheckBox)c;
	    ButtonModel model = cb.getModel();
	    int controlSize = getControlSize();
	    
	    boolean drawCheck = model.isSelected();
	    
	    if ( model.isEnabled() ) {
		if (model.isPressed() && model.isArmed()) {
		    g.setColor( MetalLookAndFeel.getControlShadow() );
		    g.fillRect( x, y, controlSize-1, controlSize-1);
		    MetalUtils.drawPressed3DBorder(g, x, y, controlSize, controlSize);
		} else {
		    MetalUtils.drawFlush3DBorder(g, x, y, controlSize, controlSize);
		}
		g.setColor( MetalLookAndFeel.getControlInfo() );
	    } else {
	        g.setColor( MetalLookAndFeel.getControlShadow() );
	        g.drawRect( x, y, controlSize-1, controlSize-1);
	    }
	    
	    if (model.isSelected()) {
		drawCheck(c,g,x,y);
	    }
	    
	}
	
	protected void drawCheck(Component c, Graphics g, int x, int y) {
	    int controlSize = getControlSize();
	    g.fillRect( x+3, y+5, 2, controlSize-8 );
	    g.drawLine( x+(controlSize-4), y+3, x+5, y+(controlSize-6) );
	    g.drawLine( x+(controlSize-4), y+4, x+5, y+(controlSize-5) );
	}
	
	public int getIconWidth() {
	    return getControlSize();
	}
	
	public int getIconHeight() {
	    return getControlSize();
	}
    } // End class CheckBoxIcon

    // Radio button code
    private static class RadioButtonIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    JRadioButton rb = (JRadioButton)c;
	    ButtonModel model = rb.getModel();
	    boolean drawDot = model.isSelected();

	    Color background = c.getBackground();
	    Color dotColor = c.getForeground();
	    Color shadow = MetalLookAndFeel.getControlShadow();
	    Color darkCircle = MetalLookAndFeel.getControlDarkShadow();
	    Color whiteInnerLeftArc = MetalLookAndFeel.getControlHighlight();
	    Color whiteOuterRightArc = MetalLookAndFeel.getControlHighlight();
	    Color interiorColor = background;

	    // Set up colors per RadioButtonModel condition
	    if ( !model.isEnabled() ) {
		whiteInnerLeftArc = whiteOuterRightArc = background;
		darkCircle = dotColor = shadow;
	    }
	    else if (model.isPressed() && model.isArmed() ) {
		whiteInnerLeftArc = interiorColor = shadow;
	    }
	    
	    g.translate(x, y);

	    // fill interior
	    g.setColor(interiorColor);
	    g.fillRect(2,2, 9,9);
	   
	    // draw Dark Circle (start at top, go clockwise)
	    g.setColor(darkCircle);
	    g.drawLine( 4, 0,  7, 0);
	    g.drawLine( 8, 1,  9, 1);
	    g.drawLine(10, 2, 10, 3);
	    g.drawLine(11, 4, 11, 7);
	    g.drawLine(10, 8, 10, 9);
	    g.drawLine( 9,10,  8,10);
	    g.drawLine( 7,11,  4,11);
	    g.drawLine( 3,10,  2,10);
	    g.drawLine( 1, 9,  1, 8);
	    g.drawLine( 0, 7,  0, 4);
	    g.drawLine( 1, 3,  1, 2);
	    g.drawLine( 2, 1,  3, 1);

	    // draw Inner Left (usually) White Arc
	    //  start at lower left corner, go clockwise
	    g.setColor(whiteInnerLeftArc);
	    g.drawLine( 2, 9,  2, 8);
	    g.drawLine( 1, 7,  1, 4);
	    g.drawLine( 2, 2,  2, 3);
	    g.drawLine( 2, 2,  3, 2);
	    g.drawLine( 4, 1,  7, 1);
	    g.drawLine( 8, 2,  9, 2);
	    // draw Outer Right White Arc
	    //  start at upper right corner, go clockwise
	    g.setColor(whiteOuterRightArc);
	    g.drawLine(10, 1, 10, 1);
	    g.drawLine(11, 2, 11, 3);
	    g.drawLine(12, 4, 12, 7);
	    g.drawLine(11, 8, 11, 9);
	    g.drawLine(10,10, 10,10);
	    g.drawLine( 9,11,  8,11);
	    g.drawLine( 7,12,  4,12);
	    g.drawLine( 3,11,  2,11);

	    // selected dot
	    if ( drawDot ) {
		g.setColor(dotColor);
		g.fillRect( 4, 4,  4, 4);
		g.drawLine( 4, 3,  7, 3);
		g.drawLine( 8, 4,  8, 7);
		g.drawLine( 7, 8,  4, 8);
		g.drawLine( 3, 7,  3, 4);
	    }

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 13;
	}
	
	public int getIconHeight() {
	    return 13;
	}
    }  // End class RadioButtonIcon

    // Tree Computer Icon code
    private static class TreeComputerIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    g.translate(x, y);

	    // Fill glass portion of monitor
	    g.setColor(MetalLookAndFeel.getPrimaryControl());
	    g.fillRect(5,4, 6,4);

	    // Draw outside edge of monitor
	    g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
	    g.drawLine( 2,2,  2,8); // left
	    g.drawLine(13,2, 13,8); // right
	    g.drawLine( 3,1, 12,1); // top
	    g.drawLine(12,9, 12,9); // bottom right base
	    g.drawLine( 3,9,  3,9); // bottom left base
	    // Draw the edge of the glass
	    g.drawLine( 4,4,  4,7); // left
	    g.drawLine( 5,3, 10,3); // top
	    g.drawLine(11,4, 11,7); // right
	    g.drawLine( 5,8, 10,8); // bottom
	    // Draw the edge of the CPU
	    g.drawLine( 1,10, 14,10); // top
	    g.drawLine(14,10, 14,14); // right
	    g.drawLine( 1,14, 14,14); // bottom
	    g.drawLine( 1,10,  1,14); // left

	    // Draw the disk drives
	    g.setColor(MetalLookAndFeel.getControlDarkShadow());
	    g.drawLine( 6,12,  8,12); // left
	    g.drawLine(10,12, 12,12); // right

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 16;
	}
	
	public int getIconHeight() {
	    return 16;
	}
    }  // End class TreeComputerIcon

    // Tree HardDrive Icon code
    private static class TreeHardDriveIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    g.translate(x, y);

	    // Draw edges of the disks
	    g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
	    //     top disk
	    g.drawLine(1,4, 1,5); // left
	    g.drawLine(2,3, 3,3);
	    g.drawLine(4,2, 11,2); // top
	    g.drawLine(12,3, 13,3);
	    g.drawLine(14,4, 14,5); // right
	    g.drawLine(12,6, 13,6);
	    g.drawLine(4,7, 11,7); // bottom
	    g.drawLine(2,6, 3,6);
	    //     middle disk
	    g.drawLine(1,7, 1,8); // left
	    g.drawLine(2,9, 3,9);
	    g.drawLine(4,10, 11,10); // bottom
	    g.drawLine(12,9, 13,9);
	    g.drawLine(14,7, 14, 8); // right
	    //     bottom disk
	    g.drawLine(1,10, 1,11); // left
	    g.drawLine(2,12, 3,12);
	    g.drawLine(4,13, 11,13); // bottom
	    g.drawLine(12,12, 13,12);
	    g.drawLine(14,10, 14,11); // right

	    // Draw the down right shadows
	    g.setColor(MetalLookAndFeel.getControlShadow());
	    //     top disk
	    g.drawLine(7,6, 7,6);
	    g.drawLine(9,6, 9,6);
	    g.drawLine(10,5, 10,5);
	    g.drawLine(11,6, 11,6);
	    g.drawLine(12,5, 13,5);
	    g.drawLine(13,4, 13,4);
	    //     middle disk
	    g.drawLine(7,9, 7,9);
	    g.drawLine(9,9, 9,9);
	    g.drawLine(10,8, 10,8);
	    g.drawLine(11,9, 11,9);
	    g.drawLine(12,8, 13,8);
	    g.drawLine(13,7, 13,7);
	    //     bottom disk
	    g.drawLine(7,12, 7,12);
	    g.drawLine(9,12, 9,12);
	    g.drawLine(10,11, 10,11);
	    g.drawLine(11,12, 11,12);
	    g.drawLine(12,11, 13,11);
	    g.drawLine(13,10, 13,10);

	    // Draw the up left highlight
	    g.setColor(MetalLookAndFeel.getControlHighlight());
	    //     top disk
	    g.drawLine(4,3, 5,3);
	    g.drawLine(7,3, 9,3);
	    g.drawLine(11,3, 11,3);
	    g.drawLine(2,4, 6,4);
	    g.drawLine(8,4, 8,4);
	    g.drawLine(2,5, 3,5);
	    g.drawLine(4,6, 4,6);
	    //     middle disk
	    g.drawLine(2,7, 3,7);
	    g.drawLine(2,8, 3,8);
	    g.drawLine(4,9, 4,9);
	    //     bottom disk
	    g.drawLine(2,10, 3,10);
	    g.drawLine(2,11, 3,11);
	    g.drawLine(4,12, 4,12);

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 16;
	}
	
	public int getIconHeight() {
	    return 16;
	}
    }  // End class TreeHardDriveIcon

    // Tree FloppyDrive Icon code
    private static class TreeFloppyDriveIcon implements Icon, UIResource, Serializable {
        public void paintIcon(Component c, Graphics g, int x, int y) {
	    g.translate(x, y);

	    // Fill body of floppy
	    g.setColor(MetalLookAndFeel.getPrimaryControl());
	    g.fillRect(2,2, 12,12);

	    // Draw outside edge of floppy
	    g.setColor(MetalLookAndFeel.getPrimaryControlInfo());
	    g.drawLine( 1, 1, 13, 1); // top
	    g.drawLine(14, 2, 14,14); // right
	    g.drawLine( 1,14, 14,14); // bottom
	    g.drawLine( 1, 1,  1,14); // left

	    // Draw grey-ish highlights
	    g.setColor(MetalLookAndFeel.getControlDarkShadow());
	    g.fillRect(5,2, 6,5); // metal disk protector part
	    g.drawLine(4,8, 11,8); // top of label
	    g.drawLine(3,9, 3,13); // left of label
	    g.drawLine(12,9, 12,13); // right of label

	    // Draw label and exposed disk
	    g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
	    g.fillRect(8,3, 2,3); // exposed disk
	    g.fillRect(4,9, 8,5); // label

	    // Draw text on label
	    g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
	    g.drawLine(5,10, 9,10);
	    g.drawLine(5,12, 8,12);

	    g.translate(-x, -y);
	}
	
	public int getIconWidth() {
	    return 16;
	}
	
	public int getIconHeight() {
	    return 16;
	}
    }  // End class TreeFloppyDriveIcon


    static private final Dimension folderIcon16Size = new Dimension( 16, 16 );

    /**
     * Utility class for caching icon images.  This is necessary because
     * we need a new image whenever we are rendering into a new 
     * GraphicsConfiguration, but we do not want to keep recreating icon 
     * images for GC's that we have already seen (for example, 
     * dragging a window back and forth between monitors on a multimon 
     * system, or drawing an icon to different Components that have different
     * GC's).
     * So now whenever we create a new icon image for a given GC, we
     * cache that image with the GC for later retrieval.
     */
    static class ImageCacher {
	Vector images = new Vector(1, 1);
	ImageGcPair currentImageGcPair;

	class ImageGcPair {
	    Image image;
	    GraphicsConfiguration gc;
	    ImageGcPair(Image image, GraphicsConfiguration gc) {
		this.image = image;
		this.gc = gc;
	    }

	    boolean hasSameConfiguration(GraphicsConfiguration newGC) {
		if (((newGC != null) && (newGC.equals(gc))) ||
		    ((newGC == null) && (gc == null))) 
		{
		    return true;
		}
		return false;
	    }

	}

	Image getImage(GraphicsConfiguration newGC) {
	    if ((currentImageGcPair == null) ||
		!(currentImageGcPair.hasSameConfiguration(newGC)))
	    {
		Enumeration elements = images.elements();
		while (elements.hasMoreElements()) {
		    ImageGcPair imgGcPair = (ImageGcPair)elements.nextElement();
		    if (imgGcPair.hasSameConfiguration(newGC)) {
			currentImageGcPair = imgGcPair;
			return imgGcPair.image;
		    }
		}
		return null;
	    }
	    return currentImageGcPair.image;
	}

	void cacheImage(Image image, GraphicsConfiguration gc) {
	    ImageGcPair imgGcPair = new ImageGcPair(image, gc);
	    images.addElement(imgGcPair);
	    currentImageGcPair = imgGcPair;
	}

    }

    /**
     * <p>
     * <strong>Warning:</strong>
     * Serialized objects of this class will not be compatible with
     * future Swing releases. The current serialization support is
     * appropriate for short term storage or RMI between applications running
     * the same version of Swing.  As of 1.4, support for long term storage
     * of all JavaBeans<sup><font size="-2">TM</font></sup>
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     */
    public static class FolderIcon16 implements Icon, Serializable {

	ImageCacher imageCacher;

	public void paintIcon(Component c, Graphics g, int x, int y) {
	    GraphicsConfiguration gc = c.getGraphicsConfiguration();
	    if (imageCacher == null) {
		imageCacher = new ImageCacher();
	    }
	    Image image = imageCacher.getImage(gc);
	    if (image == null) {
		if (gc != null) {
		    image = gc.createCompatibleImage(getIconWidth(), 
						     getIconHeight(),
						     Transparency.BITMASK);
		} else {
		    image = new BufferedImage(getIconWidth(),
					      getIconHeight(),
					      BufferedImage.TYPE_INT_ARGB);
		}
                Graphics imageG = image.getGraphics();		
		paintMe(c,imageG);
		imageG.dispose();
		imageCacher.cacheImage(image, gc);
	    }
            g.drawImage(image, x, y+getShift(), null);
	}


	private void paintMe(Component c, Graphics g) {

	    int right = folderIcon16Size.width - 1;
	    int bottom = folderIcon16Size.height - 1;

	    // Draw tab top
	    g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
	    g.drawLine( right - 5, 3, right, 3 );
	    g.drawLine( right - 6, 4, right, 4 );

	    // Draw folder front
	    g.setColor( MetalLookAndFeel.getPrimaryControl() );
	    g.fillRect( 2, 7, 13, 8 );

	    // Draw tab bottom
	    g.setColor( MetalLookAndFeel.getPrimaryControlShadow() );
	    g.drawLine( right - 6, 5, right - 1, 5 );

	    // Draw outline
	    g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
	    g.drawLine( 0, 6, 0, bottom );            // left side
	    g.drawLine( 1, 5, right - 7, 5 );         // first part of top
	    g.drawLine( right - 6, 6, right - 1, 6 ); // second part of top
	    g.drawLine( right, 5, right, bottom );    // right side
	    g.drawLine( 0, bottom, right, bottom );   // bottom

	    // Draw highlight
	    g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
	    g.drawLine( 1, 6, 1, bottom - 1 );
	    g.drawLine( 1, 6, right - 7, 6 );
	    g.drawLine( right - 6, 7, right - 1, 7 );

	}

        public int getShift() { return 0; }
        public int getAdditionalHeight() { return 0; }

	public int getIconWidth() { return folderIcon16Size.width; }
	public int getIconHeight() { return folderIcon16Size.height + getAdditionalHeight(); }
    }

  
    /**
     * <p>
     * <strong>Warning:</strong>
     * Serialized objects of this class will not be compatible with
     * future Swing releases. The current serialization support is
     * appropriate for short term storage or RMI between applications running
     * the same version of Swing.  As of 1.4, support for long term storage
     * of all JavaBeans<sup><font size="-2">TM</font></sup>
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     */
    public static class TreeFolderIcon extends FolderIcon16 {
        public int getShift() { return -1; }
        public int getAdditionalHeight() { return 2; }
    }


    static private final Dimension fileIcon16Size = new Dimension( 16, 16 );

    /**
     * <p>
     * <strong>Warning:</strong>
     * Serialized objects of this class will not be compatible with
     * future Swing releases. The current serialization support is
     * appropriate for short term storage or RMI between applications running
     * the same version of Swing.  As of 1.4, support for long term storage
     * of all JavaBeans<sup><font size="-2">TM</font></sup>
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     */
    public static class FileIcon16 implements Icon, Serializable {

	ImageCacher imageCacher;

	public void paintIcon(Component c, Graphics g, int x, int y) {
	    GraphicsConfiguration gc = c.getGraphicsConfiguration();
	    if (imageCacher == null) {
		imageCacher = new ImageCacher();
	    }
	    Image image = imageCacher.getImage(gc);
	    if (image == null) {
		if (gc != null) {
		    image = gc.createCompatibleImage(getIconWidth(), 
						     getIconHeight(),
						     Transparency.BITMASK);
		} else {
		    image = new BufferedImage(getIconWidth(),
					      getIconHeight(),
					      BufferedImage.TYPE_INT_ARGB);
		}
                Graphics imageG = image.getGraphics();		
		paintMe(c,imageG);
		imageG.dispose();
		imageCacher.cacheImage(image, gc);
	    }
            g.drawImage(image, x, y+getShift(), null);
	}

        private void paintMe(Component c, Graphics g) {

		int right = fileIcon16Size.width - 1;
		int bottom = fileIcon16Size.height - 1;

		// Draw fill
		g.setColor( MetalLookAndFeel.getWindowBackground() );
		g.fillRect( 4, 2, 9, 12 );

		// Draw frame
		g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
		g.drawLine( 2, 0, 2, bottom );                 // left
		g.drawLine( 2, 0, right - 4, 0 );              // top
		g.drawLine( 2, bottom, right - 1, bottom );    // bottom
		g.drawLine( right - 1, 6, right - 1, bottom ); // right
		g.drawLine( right - 6, 2, right - 2, 6 );      // slant 1
		g.drawLine( right - 5, 1, right - 4, 1 );      // part of slant 2
		g.drawLine( right - 3, 2, right - 3, 3 );      // part of slant 2
		g.drawLine( right - 2, 4, right - 2, 5 );      // part of slant 2

		// Draw highlight
		g.setColor( MetalLookAndFeel.getPrimaryControl() );
		g.drawLine( 3, 1, 3, bottom - 1 );                  // left
		g.drawLine( 3, 1, right - 6, 1 );                   // top
		g.drawLine( right - 2, 7, right - 2, bottom - 1 );  // right
		g.drawLine( right - 5, 2, right - 3, 4 );           // slant
		g.drawLine( 3, bottom - 1, right - 2, bottom - 1 ); // bottom

	}

        public int getShift() { return 0; }
        public int getAdditionalHeight() { return 0; }

	public int getIconWidth() { return fileIcon16Size.width; }
	public int getIconHeight() { return fileIcon16Size.height + getAdditionalHeight(); }
    }


    public static class TreeLeafIcon extends FileIcon16 {
        public int getShift() { return 2; }
        public int getAdditionalHeight() { return 4; }
    }


    static private final Dimension treeControlSize = new Dimension( 18, 18 );

    /**
     * <p>
     * <strong>Warning:</strong>
     * Serialized objects of this class will not be compatible with
     * future Swing releases. The current serialization support is
     * appropriate for short term storage or RMI between applications running
     * the same version of Swing.  As of 1.4, support for long term storage
     * of all JavaBeans<sup><font size="-2">TM</font></sup>
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     */
    public static class TreeControlIcon implements Icon, Serializable {
        // This data member should not have been exposed.  It's called
        // isLight, but now it really means isCollapsed.  Since we can't change
        // any APIs... that's life.
        protected boolean isLight;


        public TreeControlIcon( boolean isCollapsed ) {
	    isLight = isCollapsed;
	}

	ImageCacher imageCacher;

        transient boolean cachedOrientation = true;

	public void paintIcon(Component c, Graphics g, int x, int y) {

	    GraphicsConfiguration gc = c.getGraphicsConfiguration();

	    if (imageCacher == null) {
		imageCacher = new ImageCacher();
	    }
	    Image image = imageCacher.getImage(gc);

	    if (image == null || cachedOrientation != MetalUtils.isLeftToRight(c)) {
		cachedOrientation = MetalUtils.isLeftToRight(c);
		if (gc != null) {
		    image = gc.createCompatibleImage(getIconWidth(), 
						     getIconHeight(),
						     Transparency.BITMASK);
		} else {
		    image = new BufferedImage(getIconWidth(),
					      getIconHeight(),
					      BufferedImage.TYPE_INT_ARGB);
		}
                Graphics imageG = image.getGraphics();		
		paintMe(c,imageG,x,y);
		imageG.dispose();
		imageCacher.cacheImage(image, gc);
		
	    }

	    if (MetalUtils.isLeftToRight(c)) {
	        if (isLight) {    // isCollapsed
		    g.drawImage(image, x+5, y+3, x+18, y+13, 
				       4,3, 17, 13, null);
		}
	        else {
		    g.drawImage(image, x+5, y+3, x+18, y+17, 
				       4,3, 17, 17, null);
		}
	    }
	    else {
	        if (isLight) {    // isCollapsed
		    g.drawImage(image, x+3, y+3, x+16, y+13, 
				       4, 3, 17, 13, null);
		}
		else {
		    g.drawImage(image, x+3, y+3, x+16, y+17, 
				       4, 3, 17, 17, null);
		}
	    }
	}

	public void paintMe(Component c, Graphics g, int x, int y) {

	    g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );

	    int xoff = (MetalUtils.isLeftToRight(c)) ? 0 : 4;

	    // Draw circle
	    g.drawLine( xoff + 4, 6, xoff + 4, 9 );     // left
	    g.drawLine( xoff + 5, 5, xoff + 5, 5 );     // top left dot
	    g.drawLine( xoff + 6, 4, xoff + 9, 4 );     // top
	    g.drawLine( xoff + 10, 5, xoff + 10, 5 );   // top right dot
	    g.drawLine( xoff + 11, 6, xoff + 11, 9 );   // right
	    g.drawLine( xoff + 10, 10, xoff + 10, 10 ); // botom right dot
	    g.drawLine( xoff + 6, 11, xoff + 9, 11 );   // bottom
	    g.drawLine( xoff + 5, 10, xoff + 5, 10 );   // bottom left dot

	    // Draw Center Dot
	    g.drawLine( xoff + 7, 7, xoff + 8, 7 );
	    g.drawLine( xoff + 7, 8, xoff + 8, 8 );

	    // Draw Handle
	    if ( isLight ) {    // isCollapsed
	        if( MetalUtils.isLeftToRight(c) ) {
	            g.drawLine( 12, 7, 15, 7 );
		    g.drawLine( 12, 8, 15, 8 );
		    //	g.setColor( c.getBackground() );
		    //	g.drawLine( 16, 7, 16, 8 );
		}
		else {
		    g.drawLine(4, 7, 7, 7);
		    g.drawLine(4, 8, 7, 8);
		}
	    }
	    else {
	        g.drawLine( xoff + 7, 12, xoff + 7, 15 );
		g.drawLine( xoff + 8, 12, xoff + 8, 15 );
		//	g.setColor( c.getBackground() );
		//	g.drawLine( xoff + 7, 16, xoff + 8, 16 );
	    }

	    // Draw Fill
	    g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
	    g.drawLine( xoff + 5, 6, xoff + 5, 9 );      // left shadow
	    g.drawLine( xoff + 6, 5, xoff + 9, 5 );      // top shadow

	    g.setColor( MetalLookAndFeel.getPrimaryControlShadow() );
	    g.drawLine( xoff + 6, 6, xoff + 6, 6 );      // top left fill
	    g.drawLine( xoff + 9, 6, xoff + 9, 6 );      // top right fill
	    g.drawLine( xoff + 6, 9, xoff + 6, 9 );      // bottom left fill
	    g.drawLine( xoff + 10, 6, xoff + 10, 9 );    // right fill
	    g.drawLine( xoff + 6, 10, xoff + 9, 10 );    // bottom fill

	    g.setColor( MetalLookAndFeel.getPrimaryControl() );
	    g.drawLine( xoff + 6, 7, xoff + 6, 8 );      // left highlight
	    g.drawLine( xoff + 7, 6, xoff + 8, 6 );      // top highlight
	    g.drawLine( xoff + 9, 7, xoff + 9, 7 );      // right highlight
	    g.drawLine( xoff + 7, 9, xoff + 7, 9 );      // bottom highlight

	    g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() );
	    g.drawLine( xoff + 8, 9, xoff + 9, 9 );
	    g.drawLine( xoff + 9, 8, xoff + 9, 8 );
	}

	public int getIconWidth() { return treeControlSize.width; }
	public int getIconHeight() { return treeControlSize.height; }
    }

  //
  // Menu Icons
  //

    static private final Dimension menuArrowIconSize = new Dimension( 4, 8 );
    static private final Dimension menuCheckIconSize = new Dimension( 10, 10 );
    static private final int xOff = 4;

    private static class MenuArrowIcon implements Icon, UIResource, Serializable
    {
	public void paintIcon( Component c, Graphics g, int x, int y )
	{
	    JMenuItem b = (JMenuItem) c;
	    ButtonModel model = b.getModel();

	    g.translate( x, y );

	    if ( !model.isEnabled() )
	    {
	        g.setColor( MetalLookAndFeel.getMenuDisabledForeground() );
	    }
	    else
	    {
	        if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
		{
		    g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
		}
		else
		{
		    g.setColor( b.getForeground() );
		}
	    }
            if( MetalUtils.isLeftToRight(b) ) {
                g.drawLine( 0, 0, 0, 7 );
                g.drawLine( 1, 1, 1, 6 );
                g.drawLine( 2, 2, 2, 5 );
                g.drawLine( 3, 3, 3, 4 );
            } else {
                g.drawLine( 4, 0, 4, 7 );
                g.drawLine( 3, 1, 3, 6 );
                g.drawLine( 2, 2, 2, 5 );
                g.drawLine( 1, 3, 1, 4 );
            }

	    g.translate( -x, -y );
	}

	public int getIconWidth() { return menuArrowIconSize.width; }

	public int getIconHeight() { return menuArrowIconSize.height; }

    } // End class MenuArrowIcon

    private static class MenuItemArrowIcon implements Icon, UIResource, Serializable
    {
	public void paintIcon( Component c, Graphics g, int x, int y )
	{
	}

	public int getIconWidth() { return menuArrowIconSize.width; }

	public int getIconHeight() { return menuArrowIconSize.height; }

    } // End class MenuItemArrowIcon

    private static class CheckBoxMenuItemIcon implements Icon, UIResource, Serializable
    {
	public void paintIcon( Component c, Graphics g, int x, int y )
	{
	    JMenuItem b = (JMenuItem) c;
	    ButtonModel model = b.getModel();

	    boolean isSelected = model.isSelected();
	    boolean isEnabled = model.isEnabled();
	    boolean isPressed = model.isPressed();
	    boolean isArmed = model.isArmed();
	    
	    g.translate( x, y );

	    if ( isEnabled )
	    {
	        if ( isPressed || isArmed )
		{
		    g.setColor( MetalLookAndFeel.getControlInfo()  );
		    g.drawLine( 0, 0, 8, 0 );
		    g.drawLine( 0, 0, 0, 8 );
		    g.drawLine( 8, 2, 8, 8 );
		    g.drawLine( 2, 8, 8, 8 );

		    g.setColor( MetalLookAndFeel.getPrimaryControl()  );
		    g.drawLine( 1, 1, 7, 1 );
		    g.drawLine( 1, 1, 1, 7 );
		    g.drawLine( 9, 1, 9, 9 );
		    g.drawLine( 1, 9, 9, 9 );
		}
		else
		{
		    g.setColor( MetalLookAndFeel.getControlDarkShadow()  );
		    g.drawLine( 0, 0, 8, 0 );
		    g.drawLine( 0, 0, 0, 8 );
		    g.drawLine( 8, 2, 8, 8 );
		    g.drawLine( 2, 8, 8, 8 );

		    g.setColor( MetalLookAndFeel.getControlHighlight()  );
		    g.drawLine( 1, 1, 7, 1 );
		    g.drawLine( 1, 1, 1, 7 );
		    g.drawLine( 9, 1, 9, 9 );
		    g.drawLine( 1, 9, 9, 9 );
		}
	    }
	    else
	    {
	        g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
		g.drawRect( 0, 0, 8, 8 );
	    }

	    if ( isSelected )
	    {
	        if ( isEnabled )
		{
		    if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
		    {
		        g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
		    }
		    else
		    {
		        g.setColor( b.getForeground() );
		    }
		}
		else
		{
		    g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
		}

		g.drawLine( 2, 2, 2, 6 );
		g.drawLine( 3, 2, 3, 6 );
		g.drawLine( 4, 4, 8, 0 );
		g.drawLine( 4, 5, 9, 0 );
	    }

	    g.translate( -x, -y );
	}

	public int getIconWidth() { return menuCheckIconSize.width; }

	public int getIconHeight() { return menuCheckIconSize.height; }

    }  // End class CheckBoxMenuItemIcon

    private static class RadioButtonMenuItemIcon implements Icon, UIResource, Serializable
    {
	public void paintIcon( Component c, Graphics g, int x, int y )
	{
	    JMenuItem b = (JMenuItem) c;
	    ButtonModel model = b.getModel();

	    boolean isSelected = model.isSelected();
	    boolean isEnabled = model.isEnabled();
	    boolean isPressed = model.isPressed();
	    boolean isArmed = model.isArmed();
	    
	    g.translate( x, y );

	    if ( isEnabled )
	    {
	        if ( isPressed || isArmed )
		{
		    g.setColor( MetalLookAndFeel.getPrimaryControl()  );
		    g.drawLine( 3, 1, 8, 1 );
		    g.drawLine( 2, 9, 7, 9 );
		    g.drawLine( 1, 3, 1, 8 );
		    g.drawLine( 9, 2, 9, 7 );
		    g.drawLine( 2, 2, 2, 2 );
		    g.drawLine( 8, 8, 8, 8 );

		    g.setColor( MetalLookAndFeel.getControlInfo()  );
		    g.drawLine( 2, 0, 6, 0 );
		    g.drawLine( 2, 8, 6, 8 );
		    g.drawLine( 0, 2, 0, 6 );
		    g.drawLine( 8, 2, 8, 6 );
		    g.drawLine( 1, 1, 1, 1 );
		    g.drawLine( 7, 1, 7, 1 );
		    g.drawLine( 1, 7, 1, 7 );
		    g.drawLine( 7, 7, 7, 7 );
		}
		else
		{
		    g.setColor( MetalLookAndFeel.getControlHighlight()  );
		    g.drawLine( 3, 1, 8, 1 );
		    g.drawLine( 2, 9, 7, 9 );
		    g.drawLine( 1, 3, 1, 8 );
		    g.drawLine( 9, 2, 9, 7 );
		    g.drawLine( 2, 2, 2, 2 );
		    g.drawLine( 8, 8, 8, 8 );

		    g.setColor( MetalLookAndFeel.getControlDarkShadow()  );
		    g.drawLine( 2, 0, 6, 0 );
		    g.drawLine( 2, 8, 6, 8 );
		    g.drawLine( 0, 2, 0, 6 );
		    g.drawLine( 8, 2, 8, 6 );
		    g.drawLine( 1, 1, 1, 1 );
		    g.drawLine( 7, 1, 7, 1 );
		    g.drawLine( 1, 7, 1, 7 );
		    g.drawLine( 7, 7, 7, 7 );
		}
	    }
	    else
	    {
	        g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
		g.drawLine( 2, 0, 6, 0 );
		g.drawLine( 2, 8, 6, 8 );
		g.drawLine( 0, 2, 0, 6 );
		g.drawLine( 8, 2, 8, 6 );
		g.drawLine( 1, 1, 1, 1 );
		g.drawLine( 7, 1, 7, 1 );
		g.drawLine( 1, 7, 1, 7 );
		g.drawLine( 7, 7, 7, 7 );
	    }

	    if ( isSelected )
	    {
	        if ( isEnabled )
		{
		    if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) )
		    {
		        g.setColor( MetalLookAndFeel.getMenuSelectedForeground() );
		    }
		    else
		    {
		        g.setColor( b.getForeground() );
		    }
		}
		else
		{
		    g.setColor( MetalLookAndFeel.getMenuDisabledForeground()  );
		}

		g.drawLine( 3, 2, 5, 2 );
		g.drawLine( 2, 3, 6, 3 );
		g.drawLine( 2, 4, 6, 4 );
		g.drawLine( 2, 5, 6, 5 );
		g.drawLine( 3, 6, 5, 6 );
	    }

	    g.translate( -x, -y );
	}

	public int getIconWidth() { return menuCheckIconSize.width; }

	public int getIconHeight() { return menuCheckIconSize.height; }

    }  // End class RadioButtonMenuItemIcon

private static class VerticalSliderThumbIcon implements Icon, Serializable, UIResource {
    protected static MetalBumps controlBumps;
    protected static MetalBumps primaryBumps;

    public VerticalSliderThumbIcon() {
        controlBumps = new MetalBumps( 6, 10,
				MetalLookAndFeel.getControlHighlight(),
				MetalLookAndFeel.getControlInfo(),
				MetalLookAndFeel.getControl() );        
        primaryBumps = new MetalBumps( 6, 10,
				MetalLookAndFeel.getPrimaryControl(),
				MetalLookAndFeel.getPrimaryControlDarkShadow(),
				MetalLookAndFeel.getPrimaryControlShadow() );        
    }

    public void paintIcon( Component c, Graphics g, int x, int y ) {
        JSlider slider = (JSlider)c;

	boolean leftToRight = MetalUtils.isLeftToRight(slider);

        g.translate( x, y );

	// Draw the frame
	if ( slider.hasFocus() ) {
	    g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
	}
	else {
	    g.setColor( slider.isEnabled() ? MetalLookAndFeel.getPrimaryControlInfo() :
			                     MetalLookAndFeel.getControlDarkShadow() );
	}

	if (leftToRight) {
	    g.drawLine(  1,0  ,  8,0  ); // top
	    g.drawLine(  0,1  ,  0,13 ); // left
	    g.drawLine(  1,14 ,  8,14 ); // bottom
	    g.drawLine(  9,1  , 15,7  ); // top slant
	    g.drawLine(  9,13 , 15,7  ); // bottom slant
	}
	else {
	    g.drawLine(  7,0  , 14,0  ); // top
	    g.drawLine( 15,1  , 15,13 ); // right
	    g.drawLine(  7,14 , 14,14 ); // bottom
	    g.drawLine(  0,7  ,  6,1  ); // top slant
	    g.drawLine(  0,7  ,  6,13 ); // bottom slant
	}

	// Fill in the background
	if ( slider.hasFocus() ) {
	    g.setColor( c.getForeground() );
	}
	else {
	    g.setColor( MetalLookAndFeel.getControl() );
	}

	if (leftToRight) {
	    g.fillRect(  1,1 ,  8,13 );

	    g.drawLine(  9,2 ,  9,12 );
	    g.drawLine( 10,3 , 10,11 );
	    g.drawLine( 11,4 , 11,10 );
	    g.drawLine( 12,5 , 12,9 );
	    g.drawLine( 13,6 , 13,8 );
	    g.drawLine( 14,7 , 14,7 );
	}
	else {
	    g.fillRect(  7,1,   8,13 );

	    g.drawLine(  6,3 ,  6,12 );
	    g.drawLine(  5,4 ,  5,11 );
	    g.drawLine(  4,5 ,  4,10 );
	    g.drawLine(  3,6 ,  3,9 );
	    g.drawLine(  2,7 ,  2,8 );
	}

	// Draw the bumps
	int offset = (leftToRight) ? 2 : 8;
	if ( slider.isEnabled() ) {
	    if ( slider.hasFocus() ) {
	        primaryBumps.paintIcon( c, g, offset, 2 );
	    }
	    else {
	        controlBumps.paintIcon( c, g, offset, 2 );
	    }
	}

	// Draw the highlight
	if ( slider.isEnabled() ) {
	    g.setColor( slider.hasFocus() ? MetalLookAndFeel.getPrimaryControl()
			: MetalLookAndFeel.getControlHighlight() );
	    if (leftToRight) {
	        g.drawLine( 1, 1, 8, 1 );
		g.drawLine( 1, 1, 1, 13 );
	    }
	    else {
	        g.drawLine(  8,1  , 14,1  ); // top
		g.drawLine(  1,7  ,  7,1  ); // top slant
	    }
	}

        g.translate( -x, -y );
    }

    public int getIconWidth() {
        return 16;
    }

    public int getIconHeight() {
        return 15;
    }
}

private static class HorizontalSliderThumbIcon implements Icon, Serializable, UIResource {
    protected static MetalBumps controlBumps;
    protected static MetalBumps primaryBumps;

    public HorizontalSliderThumbIcon() {
        controlBumps = new MetalBumps( 10, 6,
				MetalLookAndFeel.getControlHighlight(),
				MetalLookAndFeel.getControlInfo(),
				MetalLookAndFeel.getControl() );        
        primaryBumps = new MetalBumps( 10, 6,
				MetalLookAndFeel.getPrimaryControl(),
				MetalLookAndFeel.getPrimaryControlDarkShadow(),
				MetalLookAndFeel.getPrimaryControlShadow() );        
    }

    public void paintIcon( Component c, Graphics g, int x, int y ) {
        JSlider slider = (JSlider)c;

        g.translate( x, y );
	
	// Draw the frame
	if ( slider.hasFocus() ) {
	    g.setColor( MetalLookAndFeel.getPrimaryControlInfo() );
	}
	else {
	    g.setColor( slider.isEnabled() ? MetalLookAndFeel.getPrimaryControlInfo() :
			                     MetalLookAndFeel.getControlDarkShadow() );
	}

	g.drawLine(  1,0  , 13,0 );  // top
	g.drawLine(  0,1  ,  0,8 );  // left
	g.drawLine( 14,1  , 14,8 );  // right
	g.drawLine(  1,9  ,  7,15 ); // left slant
	g.drawLine(  7,15 , 14,8 );  // right slant

	// Fill in the background
	if ( slider.hasFocus() ) {
	    g.setColor( c.getForeground() );
	}
	else {
	    g.setColor( MetalLookAndFeel.getControl() );
	}
	g.fillRect( 1,1, 13, 8 );
	
	g.drawLine( 2,9  , 12,9 );
	g.drawLine( 3,10 , 11,10 );
	g.drawLine( 4,11 , 10,11 );
	g.drawLine( 5,12 ,  9,12 );
	g.drawLine( 6,13 ,  8,13 );
	g.drawLine( 7,14 ,  7,14 );
	
	// Draw the bumps
	if ( slider.isEnabled() ) {
	    if ( slider.hasFocus() ) {
	        primaryBumps.paintIcon( c, g, 2, 2 );
	    }
	    else {
	        controlBumps.paintIcon( c, g, 2, 2 );
	    }
	}

	// Draw the highlight
	if ( slider.isEnabled() ) {
	    g.setColor( slider.hasFocus() ? MetalLookAndFeel.getPrimaryControl()
			: MetalLookAndFeel.getControlHighlight() );
	    g.drawLine( 1, 1, 13, 1 );
	    g.drawLine( 1, 1, 1, 8 );
	}
	    
        g.translate( -x, -y );
    }

    public int getIconWidth() {
        return 15;
    }

    public int getIconHeight() {
        return 16;
    }
}

}
