// ============================================================================
// 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.I18n;
import de.caff.i18n.Localizable;
import de.caff.i18n.swing.RJMenu;
import de.caff.util.settings.EnumPreferenceProperty;
import de.caff.util.settings.EnumValue;

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

/**
 *  An enum preference property.
 *  This is one value out of a set of values.
 *
 *  @author <a href="mailto:rammi@caff.de">Rammi</a>
 *  @version $Revision$
 */
public class SwingEnumPreferenceProperty
        extends AbstractBasicSimpleEditablePreferenceProperty
        implements EnumPreferenceProperty
{
  /** The possible values. */
  private final EnumValue[] values;
  /** The currently selected value. */
  private EnumValue selectedValue;

  /**
   *  Constructor.
   *
   *  @param basicName  the name of this property
   *  @param baseTag    the basic i18n tag of this property
   *  @param values     the possible values of this property
   *  @param startValue the start value of this property
   */
  public SwingEnumPreferenceProperty(String basicName, String baseTag, EnumValue[] values, EnumValue startValue)
  {
    super(basicName, baseTag);
    this.values = values;
    this.selectedValue = startValue;
  }

  /**
   * Read the property value from the preferences.
   *
   * @param preferences preferences from where to read the property value
   */
  public void readFrom(Preferences preferences)
  {
    for (int v = 0;  v < values.length;  ++v) {
      if (values[v].isEqualTo(preferences, getBasicName())) {
        setValue(values[v]);
        break;
      }
    }
  }

  /**
   * Store the current property value in the preferences.
   *
   * @param preferences preferences where to store the property value
   */
  public void storeTo(Preferences preferences)
  {
    selectedValue.storeTo(preferences, getBasicName());
  }

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

  /**
   *  Get the current value.
   *  @return the value
   */
  public EnumValue getValue()
  {
    return selectedValue;
  }

  /**
   *  Set a new value.
   *  @param value new value
   */
  void setValue(EnumValue value)
  {
    if (!value.equals(selectedValue)) {
      EnumValue oldValue = selectedValue;
      selectedValue = value;
      fireValueChange(getBasicName(), oldValue, value);
    }
  }

  /**
   *  Get the possible values.
   *  @return possible values
   */
  public EnumValue[] getEnumValues(Locale l)
  {
    return values;
  }

  private class SpecialMenuItem
          extends JRadioButtonMenuItem
          implements PropertyChangeListener,
                     Localizable
  {
    /** The value. */
    private final EnumValue value;

    /**
     *  Constructor.
     */
    public SpecialMenuItem(EnumValue enumValue, Locale l)
    {
      super(enumValue.getShortName(l), enumValue == getValue());
      setToolTipText(enumValue.getLongName(l));
      addValueChangeListener(this);
      this.value = enumValue;
      addItemListener(new ItemListener()
      {
        public void itemStateChanged(ItemEvent e)
        {
          if (isSelected()) {
            setValue(value);
          }
        }
      });
    }

    /**
     * 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)
    {
      setSelected(value == evt.getNewValue());
    }

    /**
     * Notifies this component that it now has a parent component.
     */
    public void addNotify()
    {
      I18n.addLocalizationChangeListener(this);
      super.addNotify();
      addValueChangeListener(this);
      if (value == getValue()) {
        setSelected(true);
      }
    }

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

    /**
     * Sets the locale of this component.  This is a bound property.
     *
     * @param l the locale to become this component's locale
     * @see #getLocale
     * @since JDK1.1
     */
    public void setLocale(Locale l)
    {
      super.setLocale(l);
      setText(value.getShortName(l));
      setToolTipText(value.getLongName(l));
    }
  }

  /**
   *  Create a menu item for this boolean property.
   *  @param l locale
   *  @return menu item
   */
  public JMenuItem createMenuItem(Locale l)
  {
    RJMenu menu = new RJMenu(getBaseTag());
    ButtonGroup group = new ButtonGroup();
    for (int v = 0;  v < values.length;  ++v) {
      SpecialMenuItem menuItem = new SpecialMenuItem(values[v], l);
      menu.add(menuItem);
      group.add(menuItem);
    }
    return menu;
  }


}
