/*
  Copyright (c) 2003-2006, Robert F. Beeger (robert at beeger dot net)
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification,
  are permitted provided that the following conditions are met:

      * Redistributions of source code must retain the above copyright notice, this list
        of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above copyright notice, this
        list of conditions and the following disclaimer in the documentation and/or other
        materials provided with the distribution.
      * Neither the name of 'Robert F. Beeger' nor the names of his contributors may be
        used to endorse or promote products derived from this software without specific
        prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  Visit http://squareness.beeger.net/ for new releases of Squareness Look And Feel and other
  skins from the Squareness series.
*/
package net.beeger.squareness.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.io.Serializable;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.plaf.UIResource;

import net.beeger.squareness.SquarenessConstants;
import net.beeger.squareness.SquarenessLookAndFeel;

/**
 * The SquarenessIconFactory is a static factory that creates all painted icons.
 */
public class SquarenessIconFactory implements Serializable
{
  /**
   * Return the icon for radio buttons.
   *
   * @return The radio button icon
   */
  public static Icon getRadioButtonIcon ()
  {
    if (_radioButtonIcon == null)
    {
      _radioButtonIcon = new RadioButtonIcon();
    }
    return _radioButtonIcon;
  }

  /**
   * Return the icon for check boxes.
   *
   * @return The check box icon
   */
  public static Icon getCheckBoxIcon ()
  {
    if (_checBoxIcon == null)
    {
      _checBoxIcon = new CheckBoxIcon();
    }
    return _checBoxIcon;
  }

  /**
   * Return the icon for radio buttons.
   *
   * @return The radio button icon
   */
  public static Icon getRadioButtonMenuItemCheckIcon ()
  {
    if (_radioButtonMenuItemCheckIcon == null)
    {
      _radioButtonMenuItemCheckIcon = new RadioButtonMenuItemCheckIcon();
    }
    return _radioButtonMenuItemCheckIcon;
  }

  /**
   * Return the icon for check boxes.
   *
   * @return The check box icon
   */
  public static Icon getCheckBoxMenuItemCheckIcon ()
  {
    if (_checBoxMenuItemCheckIcon == null)
    {
      _checBoxMenuItemCheckIcon = new CheckBoxMenuItemCheckIcon();
    }
    return _checBoxMenuItemCheckIcon;
  }

  /**
   * Return the icon for check boxes.
   *
   * @return The check box icon
   */
  public static Icon getMenuItemCheckIcon ()
  {
    if (_menuItemCheckIcon == null)
    {
      _menuItemCheckIcon = new MenuItemCheckIcon();
    }
    return _menuItemCheckIcon;
  }

  /**
   * Return the icon for check boxes.
   *
   * @return The check box icon
   */
  public static Icon getMenuArrowIcon ()
  {
    if (_menuArrowIcon == null)
    {
      _menuArrowIcon = new MenuArrowIcon();
    }
    return _menuArrowIcon;
  }

  /**
   * Return the icon for check boxes.
   *
   * @return The check box icon
   */
  public static Icon getMenuItemArrowIcon ()
  {
    if (_menuItemArrowIcon == null)
    {
      _menuItemArrowIcon = new MenuItemArrowIcon();
    }
    return _menuItemArrowIcon;
  }

  /**
   * Return the close icon for frames.
   *
   * @return The close icon for frames.
   */
  public static Icon getCloseFrameIcon ()
  {
    if (_closeFrameIcon == null)
    {
      _closeFrameIcon = new CloseFrameIcon();
    }
    return _closeFrameIcon;
  }

  /**
   * Return the iconify icon for frames.
   *
   * @return The iconify icon for frames.
   */
  public static Icon getIconifyFrameIcon ()
  {
    if (_iconifyFrameIcon == null)
    {
      _iconifyFrameIcon = new IconifyFrameIcon();
    }
    return _iconifyFrameIcon;
  }

  /**
   * Return the maximize icon for frames.
   *
   * @return The maximize icon for frames.
   */
  public static Icon getMaximizeFrameIcon ()
  {
    if (_maximizeFrameIcon == null)
    {
      _maximizeFrameIcon = new MaximizeFrameIcon();
    }
    return _maximizeFrameIcon;
  }

  /**
   * Return the minimize icon for frames.
   *
   * @return The minimize icon for frames.
   */
  public static Icon getMinimizeFrameIcon ()
  {
    if (_minimizeFrameIcon == null)
    {
      _minimizeFrameIcon = new MinimizeFrameIcon();
    }
    return _minimizeFrameIcon;
  }

  /**
   * Return the icon with the up arrow (Used on scroll bars).
   *
   * @return The up arrow icon.
   */
  public static Icon getUpIcon ()
  {
    if (_upIcon == null)
    {
      _upIcon = new UpIcon();
    }
    return _upIcon;
  }

  /**
   * Return the icon with the down arrow (Used on scroll bars).
   *
   * @return The down arrow icon.
   */
  public static Icon getDownIcon ()
  {
    if (_downIcon == null)
    {
      _downIcon = new DownIcon();
    }
    return _downIcon;
  }

  /**
   * Return the icon with the left arrow (Used on scroll bars).
   *
   * @return The left arrow icon.
   */
  public static Icon getLeftIcon ()
  {
    if (_leftIcon == null)
    {
      _leftIcon = new LeftIcon();
    }
    return _leftIcon;
  }

  /**
   * Return the icon with the right arrow (Used on scroll bars).
   *
   * @return The right arrow icon.
   */
  public static Icon getRightIcon ()
  {
    if (_rightIcon == null)
    {
      _rightIcon = new RightIcon();
    }
    return _rightIcon;
  }

  /**
   * Return the icon with the up arrow for the spinner control.
   *
   * @return The up arrow icon for spinner controls.
   */
  public static Icon getSpinUpIcon ()
  {
    if (_spinUpIcon == null)
    {
      _spinUpIcon = new SpinUpIcon();
    }
    return _spinUpIcon;
  }

  /**
   * Return the icon with the down arrow for the spinner control.
   *
   * @return The down arrow icon for spinner controls.
   */
  public static Icon getSpinDownIcon ()
  {
    if (_spinDownIcon == null)
    {
      _spinDownIcon = new SpinDownIcon();
    }
    return _spinDownIcon;
  }

  //
  // private interface
  //

  /**
   * The radio buttton icon.
   */
  private static class RadioButtonIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's height.
     * 
     * @return an int specifying the fixed height of the icon.
     */
    public int getIconHeight ()
    {
      return 13;
    }

    /**
     * Return the icon's width.
     * 
     * @return an int specifying the fixed width of the icon.
     */
    public int getIconWidth ()
    {
      return 13;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
      Color oldColor = graphics.getColor();

      Color borderColor = SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor();
      Color disabledBorderColor = SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor();
      Color normalColor = SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalControlBackgroundColor();
      Color selectedColor = SquarenessLookAndFeel.getCurrentSquarenessTheme().getSelectedControlBackgroundColor();
      Color selectedShadowColor = SquarenessLookAndFeel.getCurrentSquarenessTheme().getSelectedControlBackgroundShadowColor();

      int middle = 6;
      int min = 0;
      int max = 12;

      Graphics2D graphics2D = (Graphics2D) graphics;
      graphics2D.translate(x, y);

      graphics2D.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL));

      GeneralPath borderPath = new GeneralPath(GeneralPath.WIND_NON_ZERO);
      borderPath.moveTo(middle, min);
      borderPath.lineTo(max,    middle);
      borderPath.lineTo(middle, max);
      borderPath.lineTo(min,    middle);
      borderPath.closePath();

      JRadioButton radioButton = (JRadioButton) component;
      ButtonModel model = radioButton.getModel();

      boolean isRollover = ((Boolean) radioButton.getClientProperty(SquarenessConstants.ROLLOVER_CLENT_PROPERTY_KEY)).booleanValue();

      if ((isRollover || model.isPressed() || radioButton.hasFocus()) && model.isEnabled())
      {
        graphics2D.setPaint(selectedColor);
      }
      else
      {
        graphics2D.setPaint(normalColor);
      }
      graphics2D.fill(borderPath);

      if (model.isPressed())
      {
        GeneralPath shadowPath = new GeneralPath(GeneralPath.WIND_NON_ZERO);
        shadowPath.moveTo(middle,     min);
        shadowPath.lineTo(middle + 1, min + 1);
        shadowPath.lineTo(min + 1,    middle + 1);
        shadowPath.lineTo(min,        middle);
        shadowPath.closePath();

        graphics2D.setPaint(selectedShadowColor);
        graphics2D.fill(shadowPath);
        graphics2D.draw(shadowPath);
      }

      if (model.isEnabled())
      {
        graphics2D.setPaint(borderColor);
      }
      else
      {
        graphics2D.setPaint(disabledBorderColor);
      }
      graphics2D.draw(borderPath);

      if (model.isSelected())
      {
        GeneralPath markPath = new GeneralPath(GeneralPath.WIND_NON_ZERO);
        markPath.moveTo(middle,   min + 3);
        markPath.lineTo(max - 3,  middle);
        markPath.lineTo(middle,   max - 3);
        markPath.lineTo(min + 3,  middle);
        markPath.closePath();

        if (model.isEnabled())
        {
          graphics2D.setPaint(borderColor);
        }
        else
        {
          graphics2D.setPaint(disabledBorderColor);
        }
        graphics2D.fill(markPath);
        graphics2D.draw(markPath);
      }

      graphics2D.translate(-x, -y);
      graphics.setColor(oldColor);
    }
  }

  /**
   * The radio buttton icon.
   */
  private static class RadioButtonMenuItemCheckIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's height.
     *
     * @return an int specifying the fixed height of the icon.
     */
    public int getIconHeight ()
    {
      return 7;
    }

    /**
     * Return the icon's width.
     *
     * @return an int specifying the fixed width of the icon.
     */
    public int getIconWidth ()
    {
      return 7;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
      Color oldColor = graphics.getColor();

      Color borderColor = SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor();
      Color disabledBorderColor = SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor();

      int middle = 3;
      int min = 0;
      int max = 6;

      Graphics2D graphics2D = (Graphics2D) graphics;
      graphics2D.translate(x, y);

      JRadioButtonMenuItem radioButton = (JRadioButtonMenuItem) component;
      ButtonModel model = radioButton.getModel();

      GeneralPath markPath = new GeneralPath(GeneralPath.WIND_NON_ZERO);
      markPath.moveTo(middle, min);
      markPath.lineTo(max, middle);
      markPath.lineTo(middle, max);
      markPath.lineTo(min, middle);
      markPath.closePath();

      if (model.isEnabled())
      {
        graphics2D.setPaint(borderColor);
      }
      else
      {
        graphics2D.setPaint(disabledBorderColor);
      }
      if (model.isSelected())
      {
        graphics2D.fill(markPath);
      }
      graphics2D.draw(markPath);

      graphics2D.translate(-x, -y);
      graphics.setColor(oldColor);
    }
  }

  /**
   * The check box icon.
   */
  private static class CheckBoxIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's height.
     * 
     * @return an int specifying the fixed height of the icon.
     */
    public int getIconHeight ()
    {
      return 13;
    }

    /**
     * Return the icon's width.
     * 
     * @return an int specifying the fixed width of the icon.
     */
    public int getIconWidth ()
    {
      return 13;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
      Color oldColor = graphics.getColor();

      Color selectedShadowColor = SquarenessLookAndFeel.getCurrentSquarenessTheme().getSelectedControlBackgroundShadowColor();

      Graphics2D graphics2D = (Graphics2D) graphics;
      graphics2D.translate(x, y);

      int min = 0;
      int max = 12;

      GeneralPath borderPath = new GeneralPath(GeneralPath.WIND_NON_ZERO);
      borderPath.moveTo(min, min);
      borderPath.lineTo(max, min);
      borderPath.lineTo(max, max);
      borderPath.lineTo(min, max);
      borderPath.closePath();

      JCheckBox checkBox = (JCheckBox) component;
      ButtonModel model = checkBox.getModel();

      boolean isRollover = ((Boolean) checkBox.getClientProperty(SquarenessConstants.ROLLOVER_CLENT_PROPERTY_KEY)).booleanValue();

      if ((isRollover || model.isPressed() || checkBox.hasFocus()) && model.isEnabled())
      {
        graphics2D.setPaint(SquarenessLookAndFeel.getCurrentSquarenessTheme().getSelectedControlBackgroundColor());
      }
      else
      {
        graphics2D.setPaint(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalControlBackgroundColor());
      }
      graphics2D.fill(borderPath);

      if (model.isPressed())
      {
        GeneralPath shadowPath = new GeneralPath(GeneralPath.WIND_NON_ZERO);
        shadowPath.moveTo(min,    min);
        shadowPath.lineTo(max,    min);
        shadowPath.lineTo(max,    min + 2);
        shadowPath.lineTo(min + 2,min + 2);
        shadowPath.lineTo(min + 2,max);
        shadowPath.lineTo(min,    max);
        shadowPath.closePath();

        graphics2D.setPaint(selectedShadowColor);
        graphics2D.fill(shadowPath);
        graphics2D.draw(shadowPath);
      }

      if (model.isEnabled())
      {
        graphics2D.setPaint(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        graphics2D.setPaint(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      graphics2D.draw(borderPath);

      if (model.isSelected())
      {
        if (model.isEnabled())
        {
          graphics2D.setPaint(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
        }
        else
        {
          graphics2D.setPaint(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
        }

        graphics2D.drawLine(min + 4, min + 3, max - 3, max - 4);
        graphics2D.drawLine(min + 3, min + 3, max - 3, max - 3);
        graphics2D.drawLine(min + 3, min + 4, max - 4, max - 3);

        graphics2D.drawLine(max - 4, min + 3, min + 3, max - 4);
        graphics2D.drawLine(max - 3, min + 3, min + 3, max - 3);
        graphics2D.drawLine(max - 3, min + 4, min + 4, max - 3);
      }

      graphics2D.translate(-x, -y);
      graphics.setColor(oldColor);
    }
  }

  /**
   * The check box icon.
   */
  private static class CheckBoxMenuItemCheckIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's height.
     *
     * @return an int specifying the fixed height of the icon.
     */
    public int getIconHeight ()
    {
      return 7;
    }

    /**
     * Return the icon's width.
     *
     * @return an int specifying the fixed width of the icon.
     */
    public int getIconWidth ()
    {
      return 7;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
      Color oldColor = graphics.getColor();

      graphics.translate(x, y);

      int min = 0;
      int max = 6;

      JCheckBoxMenuItem checkBox = (JCheckBoxMenuItem) component;
      ButtonModel model = checkBox.getModel();

      if (model.isEnabled())
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }

      if (model.isSelected())
      {
        graphics.drawLine(min + 2, min + 1, max - 1, max - 2);
        graphics.drawLine(min + 1, min + 1, max - 1, max - 1);
        graphics.drawLine(min + 1, min + 2, max - 2, max - 1);

        graphics.drawLine(min + 1, max - 2, max - 2, min + 1);
        graphics.drawLine(min + 1, max - 1, max - 1, min + 1);
        graphics.drawLine(min + 2, max - 1, max - 1, min + 2);
      }
      else
      {
        graphics.drawLine(min, min, min, max);
        graphics.drawLine(min, min, max, min);
        graphics.drawLine(max, min, max, max);
        graphics.drawLine(min, max, max, max);
      }

      graphics.translate(-x, -y);
      graphics.setColor(oldColor);
    }
  }

  /**
   * The check box icon.
   */
  private static class MenuItemCheckIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's height.
     *
     * @return an int specifying the fixed height of the icon.
     */
    public int getIconHeight ()
    {
      return 7;
    }

    /**
     * Return the icon's width.
     *
     * @return an int specifying the fixed width of the icon.
     */
    public int getIconWidth ()
    {
      return 7;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
    }
  }

  /**
   * The check box icon.
   */
  private static class MenuArrowIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's height.
     *
     * @return an int specifying the fixed height of the icon.
     */
    public int getIconHeight ()
    {
      return 7;
    }

    /**
     * Return the icon's width.
     *
     * @return an int specifying the fixed width of the icon.
     */
    public int getIconWidth ()
    {
      return 7;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
      Color oldColor = graphics.getColor();

      if (component.isEnabled())
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }

      int startLine1X = 2;
      int startLine2X = 1;
      int startLine3X = 1;
      int endLine1X = 5;
      int endLine2X = 4;
      int endLine3X = 3;

      if (component.getComponentOrientation().equals(ComponentOrientation.RIGHT_TO_LEFT))
      {
        startLine1X = 4;
        startLine2X = 5;
        startLine3X = 5;
        endLine1X = 1;
        endLine2X = 2;
        endLine3X = 3;
      }

      graphics.translate(x, y);

      graphics.drawLine(startLine1X, 0, endLine1X, 3);
      graphics.drawLine(startLine2X, 0, endLine2X, 3);
      graphics.drawLine(startLine3X, 1, endLine3X, 3);

      graphics.drawLine(startLine1X, 6, endLine1X, 3);
      graphics.drawLine(startLine2X, 6, endLine2X, 3);
      graphics.drawLine(startLine3X, 5, endLine3X, 3);

      graphics.translate(-x, -y);
      graphics.setColor(oldColor);
    }
  }

  /**
   * The check box icon.
   */
  private static class MenuItemArrowIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's height.
     *
     * @return an int specifying the fixed height of the icon.
     */
    public int getIconHeight ()
    {
      return 7;
    }

    /**
     * Return the icon's width.
     *
     * @return an int specifying the fixed width of the icon.
     */
    public int getIconWidth ()
    {
      return 7;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
    }
  }

  /**
   * The close icon for frames.
   */
  private static class CloseFrameIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's width.
     *
     * @return The icon#s width.
     */
    public int getIconWidth ()
    {
      return 11;
    }

    /**
     * Return the icon's height.
     *
     * @return The icon's height.
     */
    public int getIconHeight ()
    {
      return 11;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
      Color oldColor = graphics.getColor();

      AbstractButton button = (AbstractButton) component;
      ButtonModel model = button.getModel();

      boolean isRollover = ((Boolean) button.getClientProperty(SquarenessConstants.ROLLOVER_CLENT_PROPERTY_KEY)).booleanValue();

      if (!model.isEnabled())
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      else if (model.isPressed() || !isRollover)
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getSelectedControlBackgroundColor());
      }

      graphics.translate(x, y);

      graphics.drawLine(1, 1, 9, 9);
      graphics.drawLine(9, 1, 1, 9);

      if (!model.isEnabled() || !model.isPressed())
      {
        graphics.drawLine(2, 1, 9, 8);
        graphics.drawLine(1, 2, 8, 9);

        graphics.drawLine(8, 1, 1, 8);
        graphics.drawLine(9, 2, 2, 9);
      }

      graphics.translate(-x, -y);
      graphics.setColor(oldColor);
    }
  }

  /**
   * The iconify icon for frames.
   */
  private static class IconifyFrameIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's width.
     *
     * @return The icon#s width.
     */
    public int getIconWidth ()
    {
      return 11;  //To change body of implemented methods use Options | File Templates.
    }

    /**
     * Return the icon's height.
     *
     * @return The icon#s height.
     */
    public int getIconHeight ()
    {
      return 11;  //To change body of implemented methods use Options | File Templates.
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
      Color oldColor = graphics.getColor();

      AbstractButton button = (AbstractButton) component;
      ButtonModel model = button.getModel();

      boolean isRollover = ((Boolean) button.getClientProperty(SquarenessConstants.ROLLOVER_CLENT_PROPERTY_KEY)).booleanValue();

      if (!model.isEnabled())
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      else if (model.isPressed() || !isRollover)
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getSelectedControlBackgroundColor());
      }

      if (!model.isEnabled() || !model.isPressed())
      {
        graphics.fillRect(x + 4, y + 4, 3, 3);
      }
      else
      {
        graphics.drawLine(x + 5, y + 5, x + 5, y + 5);
      }

      graphics.setColor(oldColor);
    }
  }

  /**
   * The maximize icon for frames.
   */
  private static class MaximizeFrameIcon implements Icon, UIResource, Serializable
  {
    /**
     * Return the icon's width.
     *
     * @return The icon#s width.
     */
    public int getIconWidth ()
    {
      return 11;
    }

    /**
     * Return the icon's height.
     *
     * @return The icon#s height.
     */
    public int getIconHeight ()
    {
      return 11;
    }

    /**
     * Draw the icon at the specified location.
     *
     * @param component The component to paint the icon on.
     * @param graphics The graphics to use for the painting.
     * @param x The x position at which to paint the icon
     * @param y The y position at which to paint the icon.
     */
    public void paintIcon (Component component, Graphics graphics, int x, int y)
    {
      Color oldColor = graphics.getColor();

      AbstractButton button = (AbstractButton) component;
      ButtonModel model = button.getModel();

      boolean isRollover = ((Boolean) button.getClientProperty(SquarenessConstants.ROLLOVER_CLENT_PROPERTY_KEY)).booleanValue();

      if (!model.isEnabled())
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      else if (model.isPressed() || !isRollover)
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        graphics.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getSelectedControlBackgroundColor());
      }

      if (!model.isEnabled() || !model.isPressed())
      {
        graphics.fillRect(x + 4, y + 2, 3, 7);
        graphics.fillRect(x + 2, y + 4, 7, 3);
      }
      else
      {
        graphics.drawLine(x + 5, y + 2, x + 5, y + 8);
        graphics.drawLine(x + 2, y + 5, x + 8, y + 5);
      }

      graphics.setColor(oldColor);
    }
  }

  private static class MinimizeFrameIcon implements Icon, UIResource, Serializable
  {
    public int getIconWidth ()
    {
      return 11;  //To change body of implemented methods use Options | File Templates.
    }

    public int getIconHeight ()
    {
      return 11;  //To change body of implemented methods use Options | File Templates.
    }

    public void paintIcon (Component c, Graphics g, int x, int y)
    {
      Color oldColor = g.getColor();

      AbstractButton button = (AbstractButton) c;
      ButtonModel model = button.getModel();

      boolean isRollover = ((Boolean) button.getClientProperty(SquarenessConstants.ROLLOVER_CLENT_PROPERTY_KEY)).booleanValue();

      if (!model.isEnabled())
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      else if (model.isPressed() || !isRollover)
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getSelectedControlBackgroundColor());
      }

      if (!model.isEnabled() || !model.isPressed())
      {
        g.fillRect(x + 2, y + 4, 7, 3);
      }
      else
      {
        g.drawLine(x + 2, y + 5, x + 8, y + 5);
      }

      g.setColor(oldColor);
    }
  }

  private static class UpIcon implements Icon, UIResource, Serializable
  {
    public int getIconHeight ()
    {
      return 6;
    }

    public int getIconWidth ()
    {
      return 11;
    }

    public void paintIcon (Component c, Graphics g, int x, int y)
    {
      Color oldColor = g.getColor();

      if (c.isEnabled())
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      g.drawLine(x + 4, y,     x,     y + 4);
      g.drawLine(x + 4, y + 1, x + 1, y + 4);
      g.drawLine(x + 4, y + 2, x + 1, y + 5);

      g.drawLine(x + 4, y,     x + 8, y + 4);
      g.drawLine(x + 4, y + 1, x + 7, y + 4);
      g.drawLine(x + 4, y + 2, x + 7, y + 5);

      g.setColor(oldColor);
    }
  }

  private static class DownIcon implements Icon, UIResource, Serializable
  {
    public int getIconHeight ()
    {
      return 6;
    }

    public int getIconWidth ()
    {
      return 11;
    }

    public void paintIcon (Component c, Graphics g, int x, int y)
    {
      Color oldColor = g.getColor();

      if (c.isEnabled())
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      g.drawLine(x + 4, y + 5,     x,     y + 5 - 4);
      g.drawLine(x + 4, y + 5 - 1, x + 1, y + 5 - 4);
      g.drawLine(x + 4, y + 5 - 2, x + 1, y + 5 - 5);

      g.drawLine(x + 4, y + 5,     x + 8, y + 5 - 4);
      g.drawLine(x + 4, y + 5 - 1, x + 7, y + 5 - 4);
      g.drawLine(x + 4, y + 5 - 2, x + 7, y + 5 - 5);

      g.setColor(oldColor);
    }
  }

  private static class LeftIcon implements Icon, UIResource, Serializable
  {
    public int getIconHeight ()
    {
      return 9;
    }

    public int getIconWidth ()
    {
      return 6;
    }

    public void paintIcon (Component c, Graphics g, int x, int y)
    {
      Color oldColor = g.getColor();

      if (c.isEnabled())
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      g.drawLine(x,     y + 4, x + 4, y);
      g.drawLine(x + 1, y + 4, x + 4, y + 1);
      g.drawLine(x + 2, y + 4, x + 5, y + 1);

      g.drawLine(x,     y + 4, x + 4, y + 8);
      g.drawLine(x + 1, y + 4, x + 4, y + 7);
      g.drawLine(x + 2, y + 4, x + 5, y + 7);

      g.setColor(oldColor);
    }
  }

  private static class RightIcon implements Icon, UIResource, Serializable
  {
    public int getIconHeight ()
    {
      return 9;
    }

    public int getIconWidth ()
    {
      return 6;
    }

    public void paintIcon (Component c, Graphics g, int x, int y)
    {
      Color oldColor = g.getColor();

      if (c.isEnabled())
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      g.drawLine(x + 5,     y + 4, x + 5 - 4, y);
      g.drawLine(x + 5 - 1, y + 4, x + 5 - 4, y + 1);
      g.drawLine(x + 5 - 2, y + 4, x + 5 - 5, y + 1);

      g.drawLine(x + 5,     y + 4, x + 5 - 4, y + 8);
      g.drawLine(x + 5 - 1, y + 4, x + 5 - 4, y + 7);
      g.drawLine(x + 5 - 2, y + 4, x + 5 - 5, y + 7);

      g.setColor(oldColor);
    }
  }

  private static class SpinUpIcon implements Icon, UIResource, Serializable
  {
    public int getIconHeight ()
    {
      return 4;
    }

    public int getIconWidth ()
    {
      return 7;
    }

    public void paintIcon (Component c, Graphics g, int x, int y)
    {
      Color oldColor = g.getColor();

      if (c.isEnabled())
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      g.drawLine(x + 3, y,     x,     y + 3);
      g.drawLine(x + 3, y + 1, x + 1, y + 3);
      g.drawLine(x + 3, y + 2, x + 2, y + 3);

      g.drawLine(x + 3, y,     x + 6, y + 3);
      g.drawLine(x + 3, y + 1, x + 5, y + 3);
      g.drawLine(x + 3, y + 2, x + 4, y + 3);

      g.setColor(oldColor);
    }
  }

  private static class SpinDownIcon implements Icon, UIResource, Serializable
  {
    public int getIconHeight ()
    {
      return 4;
    }

    public int getIconWidth ()
    {
      return 7;
    }

    public void paintIcon (Component c, Graphics g, int x, int y)
    {
      Color oldColor = g.getColor();

      if (c.isEnabled())
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getNormalBorderColor());
      }
      else
      {
        g.setColor(SquarenessLookAndFeel.getCurrentSquarenessTheme().getDisabledBorderColor());
      }
      g.drawLine(x + 3, y + 3,     x,     y + 3 - 3);
      g.drawLine(x + 3, y + 3 - 1, x + 1, y + 3 - 3);
      g.drawLine(x + 3, y + 3 - 2, x + 2, y + 3 - 3);

      g.drawLine(x + 3, y + 3,     x + 6, y + 3 - 3);
      g.drawLine(x + 3, y + 3 - 1, x + 5, y + 3 - 3);
      g.drawLine(x + 3, y + 3 - 2, x + 4, y + 3 - 3);

      g.setColor(oldColor);
    }
  }

  private static Icon _radioButtonIcon;
  private static Icon _checBoxIcon;

  private static Icon _closeFrameIcon;
  private static Icon _iconifyFrameIcon;
  private static Icon _maximizeFrameIcon;
  private static Icon _minimizeFrameIcon;

  private static Icon _upIcon;
  private static Icon _downIcon;
  private static Icon _leftIcon;
  private static Icon _rightIcon;

  private static Icon _spinUpIcon;
  private static Icon _spinDownIcon;
  private static Icon _radioButtonMenuItemCheckIcon;
  private static Icon _checBoxMenuItemCheckIcon;
  private static Icon _menuItemCheckIcon;
  private static Icon _menuArrowIcon;
  private static Icon _menuItemArrowIcon;

}