// ============================================================================
// File:               $File$
//
// Project:            
//
// Purpose:            
//
// Author:             Rammi
//
// Copyright Notice:   (c) 2005  Rammi (rammi@caff.de)
//                     This code is in the public domain.
//                     Use at own risk.
//                     No guarantees given.
//
// Latest change:      $Date$
//
// History:	       $Log$
//=============================================================================
package de.caff.util.settings.swing;

import de.caff.i18n.swing.RJMenuItem;
import de.caff.util.settings.ColorPreferenceProperty;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Locale;
import java.util.prefs.Preferences;

/**
 *  A preference property with a color value.
 *
 *  @author <a href="mailto:rammi@caff.de">Rammi</a>
 *  @version $Revision$
 */
public class SwingColorPreferenceProperty
        extends AbstractBasicSimpleEditablePreferenceProperty
        implements ColorPreferenceProperty
{
  /** The color. */
  private Color value;

  /**
   *  Create a color preference property,
   *  @param basicName  basic name (prefix)
   *  @param baseTag    basic i18n tag
   *  @param defaultValue the default color
   */
  public SwingColorPreferenceProperty(String basicName, String baseTag, Color defaultValue)
  {
    super(basicName, baseTag);
    value = defaultValue;
  }

  /**
   * Read the property value from the preferences.
   *
   * @param preferences preferences from where to read the property value
   */
  public void readFrom(Preferences preferences)
  {
    setValue(new Color(preferences.getInt(getBasicName(),
                                          value != null ?  value.getRGB()  :  0)));
  }

  /**
   * Store the current property value in the preferences.
   *
   * @param preferences preferences where to store the property value
   */
  public void storeTo(Preferences preferences)
  {
    if (value == null) {
      preferences.remove(getBasicName());
    }
    else {
      preferences.putInt(getBasicName(), value.getRGB());
    }
  }

  /**
   * Get the editor components for editing this preference property.
   *
   * @param l locale used for i18n
   * @return editor component
   */
  public EditorProvider getEditorProvider(Locale l)
  {
    return new ColorEditor(this, l);
  }

  /**
   *  Get the color value,.
   *  @return color value
   */
  public Color getValue()
  {
    return value;
  }

  /**
   *  Set the color value.
   *  @param value new color
   */
  public void setValue(Color value)
  {
    if (value != null ? !value.equals(this.value) : this.value != null) {
      Color oldColor = this.value;
      this.value = value;
      fireValueChange(getBasicName(), oldColor, value);
    }
  }

  private class SpecialMenuItem
          extends RJMenuItem
          implements PropertyChangeListener
  {
    /** The color. */
    private Color color;

    /**
     *  Constructor.
     *  @param tag basic resource tag
     *  @param color start color
     *  @param l     current locale
     */
    public SpecialMenuItem(String tag, Color color, Locale l)
    {
      super(tag, l);
      this.color = color;
      setIcon(ColorEditor.createColoredIcon(color));

      addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {
          setValue(SpecialMenuItem.this.color);
        }
      });
    }

    /**
     * This method gets called when a bound property is changed.
     *
     * @param evt A PropertyChangeEvent object describing the event source
     *            and the property that has changed.
     */
    public void propertyChange(PropertyChangeEvent evt)
    {
      final Color newColor = (Color)evt.getNewValue();
      handleNewColor(newColor);
    }

    private void handleNewColor(final Color newColor)
    {
      setEnabled(!color.equals(newColor));
    }

    /**
     * Notifies this component that it now has a parent component.
     */
    public void addNotify()
    {
      super.addNotify();
      addValueChangeListener(this);
      handleNewColor(getValue());
    }

    /**
     * Overrides <code>removeNotify</code> to remove this from the value listeners-
     */
    public void removeNotify()
    {
      super.removeNotify();
      removeValueChangeListener(this);
    }
  }

  /**
   *  Create a menu entry which allows to switch to a given color.
   *  @param tag    i18n tag to use for switching to color
   *  @param color  color to switrch to
   *  @param l      locale to use
   *  @return menu item
   */
  public JMenuItem createMenuItem(String tag, Color color, Locale l)
  {
    return new SpecialMenuItem(tag, color, l);
  }

}
