/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad.ui;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputListener;

import jnpad.GUIUtilities;
import jnpad.JNPadBundle;
import jnpad.util.Utilities;

/**
 * The Class TitledLabel.
 *
 * @version 0.3
 * @since   jNPad v0.1
 */
public class TitledLabel extends JPanel implements GradientPaintable {
  
  /** The lb icon and text. */
  private GradientLabel      lbIconAndText         = new GradientLabel();
  
  /** The pn components. */
  private JPanel             pnComponents          = new JPanel();

  /** The expand component. */
  private ExpandComponent    expandComponent;
  
  /** The close component. */
  private CloseComponent     closeComponent;

  /** The Constant ACTION_EXPAND. */
  public static final int    ACTION_EXPAND         = 0x1;
  
  /** The Constant ACTION_CLOSE. */
  public static final int    ACTION_CLOSE          = 0x2;
  
  /** The Constant ACTION_ALL. */
  public static final int    ACTION_ALL            = 0xF;

  /** The _actions. */
  private int                _actions;

  /** The fg. */
  private Color              fg                    = Color.BLACK;
  
  /** The sfg. */
  private Color              sfg                   = Color.RED;

  /** The Constant ACTION_COMMAND_EXPAND. */
  public static final String ACTION_COMMAND_EXPAND = "expandComponent"; //$NON-NLS-1$
  
  /** The Constant ACTION_COMMAND_CLOSE. */
  public static final String ACTION_COMMAND_CLOSE  = "closeComponent"; //$NON-NLS-1$

  /** Logger. */
  private final static Logger LOGGER                = Logger.getLogger(TitledLabel.class.getName());
  
  /** UID. */
  private static final long  serialVersionUID      = -3346585834547573367L;

  /**
   * Instantiates a new titled label.
   */
  public TitledLabel() {
    this(ACTION_ALL);
  }

  /**
   * Instantiates a new titled label.
   *
   * @param title the title
   */
  public TitledLabel(String title) {
    this(ACTION_ALL);
    setTitle(title);
  }

  /**
   * Instantiates a new titled label.
   *
   * @param title the title
   * @param icon the icon
   */
  public TitledLabel(String title, Icon icon) {
    this(ACTION_ALL);
    setTitle(title);
    setIcon(icon);
  }

  /**
   * Instantiates a new titled label.
   *
   * @param title the title
   * @param toolTip the tool tip
   * @param icon the icon
   */
  public TitledLabel(String title, String toolTip, Icon icon) {
    this(ACTION_ALL);
    setTitle(title);
    setToolTipText(toolTip);
    setIcon(icon);
  }

  /**
   * Instantiates a new titled label.
   *
   * @param actions the actions
   */
  public TitledLabel(int actions) {
    super(new BorderLayout());
    try {
      setBorder(BorderFactory.createEtchedBorder());

      add(lbIconAndText, BorderLayout.CENTER);
      add(pnComponents, BorderLayout.EAST);

      pnComponents.setLayout(new FlowLayout(FlowLayout.TRAILING, 0, 0));
      setComponents(actions);

      setOrientation(ORIENTATION_HORIZONTAL);

      MouseHandler mouseHandler = new MouseHandler();
      lbIconAndText.addMouseListener(mouseHandler);
      lbIconAndText.addMouseMotionListener(mouseHandler);
    }
    catch (Exception ex) {
      LOGGER.log(Level.WARNING, ex.getMessage(), ex);
    }
  }

  /**
   * Handle mouse event.
   *
   * @param e the e
   */
  private void handleMouseEvent(MouseEvent e) {
    MouseEvent me = SwingUtilities.convertMouseEvent(e.getComponent(), e , this);
    processMouseEvent(me);
  }

  /**
   * Handle mouse motion event.
   *
   * @param e the e
   */
  private void handleMouseMotionEvent(MouseEvent e) {
    MouseEvent me = SwingUtilities.convertMouseEvent(e.getComponent(), e , this);
    processMouseMotionEvent(me);
  }

  /**
   * Adds the action listener.
   *
   * @param listener the listener
   */
  public void addActionListener(ActionListener listener) {
    listenerList.add(ActionListener.class, listener);
  }

  /**
   * Removes the action listener.
   *
   * @param listener the listener
   */
  public void removeActionListener(ActionListener listener) {
    listenerList.remove(ActionListener.class, listener);
  }

  /**
   * Process action event.
   *
   * @param event the event
   */
  protected void processActionEvent(ActionEvent event) {
    Object[] listeners = listenerList.getListenerList();
    for (int i = listeners.length - 2; i >= 0; i -= 2)
      if (listeners[i] == ActionListener.class)
        ( (ActionListener) listeners[ (i + 1)]).actionPerformed(event);
  }

  /**
   * Sets the components.
   *
   * @param actions the new components
   */
  private void setComponents(int actions) {
    pnComponents.removeAll();

    String text = Utilities.defaultString(lbIconAndText.getText());

    if ( (actions & ACTION_EXPAND) != 0) {
      if (expandComponent == null) {
        expandComponent = new ExpandComponent(fg, JNPadBundle.getString("TitledLabel.maximize").concat(text), JNPadBundle.getString("TitledLabel.restore").concat(text)); //$NON-NLS-1$ //$NON-NLS-2$
        expandComponent.addMouseListener(new ActionMouseHandler(expandComponent, ACTION_COMMAND_EXPAND));
      }
      pnComponents.add(expandComponent);
    }
    if ( (actions & ACTION_CLOSE) != 0) {
      if (closeComponent == null) {
        closeComponent = new CloseComponent(fg, JNPadBundle.getString("TitledLabel.close").concat(text)); //$NON-NLS-1$
        closeComponent.addMouseListener(new ActionMouseHandler(closeComponent, ACTION_COMMAND_CLOSE));
      }
      pnComponents.add(closeComponent);
    }

    pnComponents.revalidate();
    pnComponents.repaint();

    _actions = actions;
  }

  /**
   * Sets the actions.
   *
   * @param actions the new actions
   */
  public void setActions(int actions) {
    if(_actions != actions) {
      setComponents(actions);
    }
  }

  /**
   * Sets the close tool tip text.
   *
   * @param text the new close tool tip text
   */
  public void setCloseToolTipText(String text) {
    if (closeComponent != null)
      closeComponent.setToolTipText(text);
  }

  /**
   * Sets the expand tool tip text.
   *
   * @param text the text
   * @param normalState the normal state
   */
  public void setExpandToolTipText(String text, boolean normalState) {
    if (expandComponent != null)
      expandComponent.setToolTipText(text, normalState);
  }

  /**
   * Checks if is maximized.
   *
   * @return true, if is maximized
   */
  public boolean isMaximized() {
    return (expandComponent != null && ((_actions & ACTION_EXPAND) != 0)) && expandComponent.isMaximized;
  }

  /**
   * Sets the as maximized.
   *
   * @param b the new as maximized
   */
  public void setAsMaximized(boolean b) {
    if (expandComponent != null && ( (_actions & ACTION_EXPAND) != 0) && expandComponent.isMaximized != b) {
      expandComponent.setAsMaximized(b);
    }
  }

  /**
   * Gets the expand component.
   *
   * @return the expand component
   */
  public JComponent getExpandComponent() {return expandComponent;}

  /**
   * Gets the close component.
   *
   * @return the close component
   */
  public JComponent getCloseComponent() {return closeComponent;}

  /**
   * Sets the title.
   *
   * @param title the new title
   */
  public void setTitle(String title) {
    lbIconAndText.setText(title);
    setCloseToolTipText(JNPadBundle.getString("TitledLabel.close").concat(title)); //$NON-NLS-1$
    setExpandToolTipText(JNPadBundle.getString("TitledLabel.maximize").concat(title), true); //$NON-NLS-1$
    setExpandToolTipText(JNPadBundle.getString("TitledLabel.restore").concat(title), false); //$NON-NLS-1$
  }

  /**
   * Sets the tool tip text.
   *
   * @param text the new tool tip text
   * @see javax.swing.JComponent#setToolTipText(java.lang.String)
   */
  @Override
  public void setToolTipText(String text) {
    lbIconAndText.setToolTipText(text);
  }

  /**
   * Gets the title.
   *
   * @return the title
   */
  public String getTitle() {return lbIconAndText.getText();}

  /**
   * Sets the icon.
   *
   * @param icon the new icon
   */
  public void setIcon(Icon icon) {
    lbIconAndText.setIcon(icon);
  }

  /**
   * Gets the icon.
   *
   * @return the icon
   */
  public Icon getIcon() {return lbIconAndText.getIcon();}

  /**
   * Sets the icon title gap.
   *
   * @param iconTextGap the new icon title gap
   */
  public void setIconTitleGap(int iconTextGap) {
    lbIconAndText.setIconTextGap(iconTextGap);
  }

  /**
   * Gets the icon title gap.
   *
   * @return the icon title gap
   */
  public int getIconTitleGap() {return lbIconAndText.getIconTextGap();}

  /**
   * Sets the title color.
   *
   * @param color the new title color
   */
  public void setTitleColor(Color color) {
    lbIconAndText.setForeground(color);
    if (closeComponent != null)
      closeComponent.setForeground(color);
    if (expandComponent != null)
      expandComponent.setForeground(color);
    fg = color;
    sfg = ColorUtilities.isVeryDark(color) ? ColorUtilities.deriveColor(color, 0.6f) : ColorUtilities.deriveColor(color, 0.3f);
  }

  /**
   * Gets the title color.
   *
   * @return the title color
   */
  public Color getTitleColor() {return lbIconAndText.getForeground();}

  /**
   * Sets the title font.
   *
   * @param font the new title font
   */
  public void setTitleFont(Font font) {
    lbIconAndText.setFont(font);
  }

  /**
   * Gets the title font.
   *
   * @return the title font
   */
  public Font getTitleFont() {return lbIconAndText.getFont();}

  /**
   * Sets the title horizontal alignment.
   *
   * @param alignment the new title horizontal alignment
   */
  public void setTitleHorizontalAlignment(int alignment) {
    lbIconAndText.setHorizontalAlignment(alignment);
  }

  /**
   * Gets the title horizontal alignment.
   *
   * @return the title horizontal alignment
   */
  public int getTitleHorizontalAlignment() {return lbIconAndText.getHorizontalAlignment();}

  /**
   * Gets the gradient color1.
   *
   * @return the gradient color1
   * @see jnpad.ui.GradientPaintable#getGradientColor1()
   */
  @Override
  public Color getGradientColor1() {
    return lbIconAndText.getGradientColor1();
  }

  /**
   * Gets the gradient color2.
   *
   * @return the gradient color2
   * @see jnpad.ui.GradientPaintable#getGradientColor2()
   */
  @Override
  public Color getGradientColor2() {
    return lbIconAndText.getGradientColor2();
  }

  /**
   * Gets the orientation.
   *
   * @return the orientation
   * @see jnpad.ui.Orientable#getOrientation()
   */
  @Override
  public int getOrientation() {
    return lbIconAndText.getOrientation();
  }

  /**
   * Sets the color.
   *
   * @param color the new color
   * @see jnpad.ui.GradientPaintable#setColor(java.awt.Color)
   */
  @Override
  public void setColor(Color color) {
    lbIconAndText.setColor(color);
    if (expandComponent != null)
      expandComponent.setColor(color);
    if (closeComponent != null)
      closeComponent.setColor(color);
  }

  /**
   * Sets the gradient color1.
   *
   * @param color1 the new gradient color1
   * @see jnpad.ui.GradientPaintable#setGradientColor1(java.awt.Color)
   */
  @Override
  public void setGradientColor1(Color color1) {
    lbIconAndText.setGradientColor1(color1);
    if (expandComponent != null)
      expandComponent.setGradientColor1(color1);
    if (closeComponent != null)
      closeComponent.setGradientColor1(color1);
  }

  /**
   * Sets the gradient color2.
   *
   * @param color2 the new gradient color2
   * @see jnpad.ui.GradientPaintable#setGradientColor2(java.awt.Color)
   */
  @Override
  public void setGradientColor2(Color color2) {
    lbIconAndText.setGradientColor2(color2);
    if (expandComponent != null)
      expandComponent.setGradientColor2(color2);
    if (closeComponent != null)
      closeComponent.setGradientColor2(color2);
  }

  /**
   * Sets the gradient colors.
   *
   * @param color1 the color1
   * @param color2 the color2
   * @see jnpad.ui.GradientPaintable#setGradientColors(java.awt.Color, java.awt.Color)
   */
  @Override
  public void setGradientColors(Color color1, Color color2) {
    lbIconAndText.setGradientColors(color1, color2);
    if (expandComponent != null)
      expandComponent.setGradientColors(color1, color2);
    if (closeComponent != null)
      closeComponent.setGradientColors(color1, color2);
  }

  /**
   * Sets the orientation.
   *
   * @param orientation the new orientation
   * @see jnpad.ui.Orientable#setOrientation(int)
   */
  @Override
  public void setOrientation(int orientation) {
    lbIconAndText.setOrientation(orientation);
    if (expandComponent != null)
      expandComponent.setOrientation(orientation);
    if (closeComponent != null)
      closeComponent.setOrientation(orientation);
  }

  /**
   * Support orientation.
   *
   * @param orientation the orientation
   * @return true, if successful
   * @see jnpad.ui.Orientable#supportOrientation(int)
   */
  @Override
  public boolean supportOrientation(int orientation) {
    return lbIconAndText.supportOrientation(orientation);
  }

  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class ActionMouseHandler.
   */
  private class ActionMouseHandler extends MouseAdapter {
    
    /** The _component. */
    private Component _component;
    
    /** The _action. */
    private String    _action;

    /**
     * Instantiates a new action mouse handler.
     *
     * @param component the component
     * @param action the action
     */
    ActionMouseHandler(Component component, String action) {
      _component = component;
      _action    = action;
    }

    /**
     * Mouse entered.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseAdapter#mouseEntered(java.awt.event.MouseEvent)
     */
    @Override
    public void mouseEntered(final MouseEvent e) {
      _component.setForeground(sfg);
    }

    /**
     * Mouse exited.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseAdapter#mouseExited(java.awt.event.MouseEvent)
     */
    @Override
    public void mouseExited(final MouseEvent e) {
      _component.setForeground(fg);
    }

    /**
     * Mouse clicked.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent)
     */
    @Override
    public void mouseClicked(final MouseEvent e) {
      if (SwingUtilities.isLeftMouseButton(e)) {
        processActionEvent(new ActionEvent(TitledLabel.this,
                                           ActionEvent.ACTION_PERFORMED,
                                           _action,
                                           e.getWhen(),
                                           e.getModifiers()));
      }
    }

    /**
     * Mouse released.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseAdapter#mouseReleased(java.awt.event.MouseEvent)
     */
    @Override
    public void mouseReleased(final MouseEvent e) {
      if (SwingUtilities.isLeftMouseButton(e)) {
        _component.setForeground(fg);
      }
    }
  }
  //////////////////////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class MouseHandler.
   */
  private class MouseHandler implements MouseInputListener {
    
    /**
     * Mouse clicked.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
     */
    public void mouseClicked(final MouseEvent e) {handleMouseEvent(e);}

    /**
     * Mouse pressed.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
     */
    public void mousePressed(final MouseEvent e) {handleMouseEvent(e);}

    /**
     * Mouse released.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
     */
    public void mouseReleased(final MouseEvent e) {handleMouseEvent(e);}

    /**
     * Mouse entered.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
     */
    public void mouseEntered(final MouseEvent e) {handleMouseEvent(e);}

    /**
     * Mouse exited.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
     */
    public void mouseExited(final MouseEvent e) {handleMouseEvent(e);}

    /**
     * Mouse dragged.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
     */
    public void mouseDragged(final MouseEvent e) {handleMouseMotionEvent(e);}

    /**
     * Mouse moved.
     *
     * @param e MouseEvent
     * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
     */
    public void mouseMoved(final MouseEvent e) {handleMouseMotionEvent(e);}
  }
  //////////////////////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class ExpandComponent.
   */
  private static class ExpandComponent extends JComponent implements GradientPaintable {
    
    /** The _gradient color1. */
    private Color             _gradientColor1;
    
    /** The _gradient color2. */
    private Color             _gradientColor2;
    
    /** The _orientation. */
    private int               _orientation     = ORIENTATION_VERTICAL;
    
    /** The is maximized. */
    private boolean           isMaximized;
    
    /** The tooltip_maximized. */
    private String            tooltip_normal, tooltip_maximized;

    /** UID. */
    private static final long serialVersionUID = -3954029750338007549L;

    /**
     * Instantiates a new expand component.
     *
     * @param foreground the foreground
     * @param tooltip_normal the tooltip_normal
     * @param tooltip_maximized the tooltip_maximized
     */
    ExpandComponent(Color foreground, String tooltip_normal, String tooltip_maximized) {
      this.tooltip_normal = tooltip_normal;
      this.tooltip_maximized = tooltip_maximized;
      setForeground(foreground);
      setToolTipText(tooltip_normal);
    }

    /**
     * Sets the tool tip text.
     *
     * @param text the text
     * @param normalState the normal state
     */
    void setToolTipText(String text, boolean normalState) {
      if (normalState) {
        tooltip_normal = text;
        if (!isMaximized) {
          setToolTipText(tooltip_normal);
        }
      }
      else {
        tooltip_maximized = text;
        if (isMaximized) {
          setToolTipText(tooltip_maximized);
        }
      }
    }

    /**
     * Sets the as maximized.
     *
     * @param b the new as maximized
     */
    void setAsMaximized(boolean b) {
      isMaximized = b;
      setToolTipText(b ? tooltip_maximized : tooltip_normal);
      repaint();
    }

    /**
     * Paint component.
     *
     * @param g Graphics
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    @Override
    public void paintComponent(Graphics g) {
      Dimension d = getSize();

      int thickness = 2;

      try {
        Graphics2D g2D = (Graphics2D) g;

        final Object oldAntialiasing = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
        g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        if (_orientation == ORIENTATION_VERTICAL) {
          GradientPaint paint = new GradientPaint(d.width / 2.0f,
                                                  0,
                                                  getGradientColor1(),
                                                  d.width / 2.0f,
                                                  d.height,
                                                  getGradientColor2(),
                                                  true);
          g2D.setPaint(paint);
        }
        else
          g2D.setColor(getGradientColor2());

        g2D.fillRect(0, 0, d.width, d.height);

        if (isMaximized) { // restablecer
          GUIUtilities.paintRestore(g, getForeground(), 3, 6, d.width - 10, d.height - 10, thickness);
        }
        else { // maximizar
          GUIUtilities.paintMaximize(g, getForeground(), 4, 4, d.width - 8, d.height - 8, 2, thickness);
        }

        g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntialiasing);
      }
      catch (Exception e) { // no pasa
        g.setColor(getGradientColor2());
        g.fillRect(0, 0, d.width, d.height);
        if (isMaximized) { // restablecer
          GUIUtilities.paintRestore(g, getForeground(), 3, 6, d.width - 10, d.height - 10, thickness);
        }
        else { // maximizar
          GUIUtilities.paintMaximize(g, getForeground(), 4, 4, d.width - 8, d.height - 8, 2, thickness);
        }
      }
    }

    /**
     * Gets the gradient color1.
     *
     * @return Color
     * @see jnpad.ui.GradientPaintable#getGradientColor1()
     */
    @Override
    public Color getGradientColor1() {
      return (_gradientColor1 == null) ? getBackground() : _gradientColor1;
    }

    /**
     * Gets the gradient color2.
     *
     * @return Color
     * @see jnpad.ui.GradientPaintable#getGradientColor2()
     */
    @Override
    public Color getGradientColor2() {
      return (_gradientColor2 == null) ? getBackground() : _gradientColor2;
    }

    /**
     * Sets the color.
     *
     * @param color Color
     * @see jnpad.ui.GradientPaintable#setColor(java.awt.Color)
     */
    @Override
    public void setColor(Color color) {
      setGradientColors(color, color);
      setBackground(color); // no hace falta
    }

    /**
     * Sets the gradient color1.
     *
     * @param color1 Color
     * @see jnpad.ui.GradientPaintable#setGradientColor1(java.awt.Color)
     */
    @Override
    public void setGradientColor1(Color color1) {
      Color oldGC1 = _gradientColor1;
      _gradientColor1 = color1;
      if ( (oldGC1 != null) ? !oldGC1.equals(color1) : ( (color1 != null) /*&& !color1.equals(oldGC1)*/)) { //Keep FindBugs happy
        repaint();
      }
    }

    /**
     * Sets the gradient color2.
     *
     * @param color2 Color
     * @see jnpad.ui.GradientPaintable#setGradientColor2(java.awt.Color)
     */
    @Override
    public void setGradientColor2(Color color2) {
      Color oldGC2 = _gradientColor2;
      _gradientColor2 = color2;
      if ( (oldGC2 != null) ? !oldGC2.equals(color2) : ( (color2 != null) /*&& !color2.equals(oldGC2)*/)) { //Keep FindBugs happy
        repaint();
      }
    }

    /**
     * Sets the gradient colors.
     *
     * @param color1 Color
     * @param color2 Color
     * @see jnpad.ui.GradientPaintable#setGradientColors(java.awt.Color, java.awt.Color)
     */
    @Override
    public void setGradientColors(Color color1, Color color2) {
      Color oldGC1 = _gradientColor1;
      Color oldGC2 = _gradientColor2;
      _gradientColor1 = color1;
      _gradientColor2 = color2;
      if ( ( (oldGC1 != null) ? !oldGC1.equals(color1) : ( (color1 != null) /*&& !color1.equals(oldGC1)*/)) ||  //Keep FindBugs happy
           ( (oldGC2 != null) ? !oldGC2.equals(color2) : ( (color2 != null) /*&& !color2.equals(oldGC2)*/))) {  //Keep FindBugs happy
        repaint();
      }
    }

    /**
     * Gets the orientation.
     *
     * @return int
     * @see jnpad.ui.Orientable#getOrientation()
     */
    @Override
    public int getOrientation() {return _orientation;}

    /**
     * Sets the orientation.
     *
     * @param orientation int
     * @see jnpad.ui.Orientable#setOrientation(int)
     */
    @Override
    public void setOrientation(int orientation) {
      //if (!supportOrientation(orientation))
      //  return;
      int oldOrientation = _orientation;
      _orientation = orientation;
      if (oldOrientation != orientation) {
        repaint();
      }
    }

    /**
     * Support orientation.
     *
     * @param orientation int
     * @return boolean
     * @see jnpad.ui.Orientable#supportOrientation(int)
     */
    @Override
    public boolean supportOrientation(int orientation) {
      switch (orientation) {
        case ORIENTATION_VERTICAL:
          return true;
        default:
          return false;
      }
    }

    /**
     * Gets the preferred size.
     *
     * @return Dimension
     * @see javax.swing.JComponent#getPreferredSize()
     */
    @Override
    public Dimension getPreferredSize() {return new Dimension(16, 16);}
  }
  //////////////////////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////////////////////////
  /**
   * The Class CloseComponent.
   */
  private static class CloseComponent extends JComponent implements GradientPaintable {
    
    /** The _gradient color1. */
    private Color             _gradientColor1;
    
    /** The _gradient color2. */
    private Color             _gradientColor2;
    
    /** The _orientation. */
    private int               _orientation     = ORIENTATION_VERTICAL;
    
    /** The _stroke. */
    private BasicStroke       _stroke          = new BasicStroke(2.5f);

    /** UID. */
    private static final long serialVersionUID = 6377704503042360998L;

    /**
     * Instantiates a new close component.
     *
     * @param foreground the foreground
     * @param tooltip the tooltip
     */
    CloseComponent(Color foreground, String tooltip) {
      setForeground(foreground);
      setToolTipText(tooltip);
    }

    /**
     * Paint component.
     *
     * @param g Graphics
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    @Override
    public void paintComponent(Graphics g) {
      Dimension d = getSize();

      try {
        Graphics2D g2D = (Graphics2D) g;

        final Object oldAntialiasing = g2D.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
        g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        if (_orientation == ORIENTATION_VERTICAL) {
          GradientPaint paint = new GradientPaint(d.width / 2.0f,
                                                  0,
                                                  getGradientColor1(),
                                                  d.width / 2.0f,
                                                  d.height,
                                                  getGradientColor2(),
                                                  true);
          g2D.setPaint(paint);
        }
        else
          g2D.setColor(getGradientColor2());

        g2D.fillRect(0, 0, d.width, d.height);

        g.setColor(getForeground());
        g2D.setStroke(_stroke);
        g2D.drawLine(5, 5, d.width - 5, d.height - 5);
        g2D.drawLine(5, d.height - 5, d.width - 5, 5);

        g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntialiasing);
      }
      catch (Exception e) { // no pasa
        g.setColor(getGradientColor2());
        g.fillRect(0, 0, d.width, d.height);
        GUIUtilities.paintCross(g, getForeground(), d.width / 2, d.height / 2, 6, 2);
      }
    }

    /**
     * Gets the gradient color1.
     *
     * @return Color
     * @see jnpad.ui.GradientPaintable#getGradientColor1()
     */
    @Override
    public Color getGradientColor1() {
      return (_gradientColor1 == null) ? getBackground() : _gradientColor1;
    }

    /**
     * Gets the gradient color2.
     *
     * @return Color
     * @see jnpad.ui.GradientPaintable#getGradientColor2()
     */
    @Override
    public Color getGradientColor2() {
      return (_gradientColor2 == null) ? getBackground() : _gradientColor2;
    }

    /**
     * Sets the color.
     *
     * @param color Color
     * @see jnpad.ui.GradientPaintable#setColor(java.awt.Color)
     */
    @Override
    public void setColor(Color color) {
      setGradientColors(color, color);
      setBackground(color); // no hace falta
    }

    /**
     * Sets the gradient color1.
     *
     * @param color1 Color
     * @see jnpad.ui.GradientPaintable#setGradientColor1(java.awt.Color)
     */
    @Override
    public void setGradientColor1(Color color1) {
      Color oldGC1 = _gradientColor1;
      _gradientColor1 = color1;
      if ( (oldGC1 != null) ? !oldGC1.equals(color1) : ( (color1 != null) /*&& !color1.equals(oldGC1)*/)) { //Keep FindBugs happy
        repaint();
      }
    }

    /**
     * Sets the gradient color2.
     *
     * @param color2 Color
     * @see jnpad.ui.GradientPaintable#setGradientColor2(java.awt.Color)
     */
    @Override
    public void setGradientColor2(Color color2) {
      Color oldGC2 = _gradientColor2;
      _gradientColor2 = color2;
      if ( (oldGC2 != null) ? !oldGC2.equals(color2) : ( (color2 != null) /*&& !color2.equals(oldGC2)*/)) { //Keep FindBugs happy
        repaint();
      }
    }

    /**
     * Sets the gradient colors.
     *
     * @param color1 Color
     * @param color2 Color
     * @see jnpad.ui.GradientPaintable#setGradientColors(java.awt.Color, java.awt.Color)
     */
    @Override
    public void setGradientColors(Color color1, Color color2) {
      Color oldGC1 = _gradientColor1;
      Color oldGC2 = _gradientColor2;
      _gradientColor1 = color1;
      _gradientColor2 = color2;
      if ( ( (oldGC1 != null) ? !oldGC1.equals(color1) : ( (color1 != null) /*&& !color1.equals(oldGC1)*/)) || //Keep FindBugs happy
           ( (oldGC2 != null) ? !oldGC2.equals(color2) : ( (color2 != null) /*&& !color2.equals(oldGC2)*/))) { //Keep FindBugs happy
        repaint();
      }
    }

    /**
     * Gets the orientation.
     *
     * @return int
     * @see jnpad.ui.Orientable#getOrientation()
     */
    @Override
    public int getOrientation() {return _orientation;}

    /**
     * Sets the orientation.
     *
     * @param orientation int
     * @see jnpad.ui.Orientable#setOrientation(int)
     */
    @Override
    public void setOrientation(int orientation) {
      //if (!supportOrientation(orientation))
      //  return;
      int oldOrientation = _orientation;
      _orientation = orientation;
      if (oldOrientation != orientation) {
        repaint();
      }
    }

    /**
     * Support orientation.
     *
     * @param orientation the orientation
     * @return boolean
     * @see jnpad.ui.Orientable#supportOrientation(int)
     */
    @Override
    public boolean supportOrientation(int orientation) {
      switch (orientation) {
        case ORIENTATION_VERTICAL:
          return true;
        default:
          return false;
      }
    }

    /**
     * Gets the preferred size.
     *
     * @return Dimension
     * @see javax.swing.JComponent#getPreferredSize()
     */
    @Override
    public Dimension getPreferredSize() {return new Dimension(16, 16);}
  }
  //////////////////////////////////////////////////////////////////////////////

}
