// ============================================================================
// 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.util.settings.PreferenceProperty;

import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.prefs.Preferences;

/**
 *  A group of editable preference properties.
 *
 *  @author <a href="mailto:rammi@caff.de">Rammi</a>
 *  @version $Revision$
 */
public class EditablePreferenceGroup
        implements EditablePreferenceProperty
{
  /** The suffix for the tab index preference property. */
  public static final String TABBED_SUFFIX = "-TABIDX";

  /** A collection of {@link EditablePreferenceProperty} elements. */
  private Collection propertyList = new LinkedList();
  /** The common title for the collected preference properties. */
  private final String nameTag;
  /** Are there tabs to create for each added property? */
  private final boolean tabbed;
  /** The last tab position if tabbed. */
  private int tabIndex = 0;

  /**
   *  Create a preference group.
   *  @param nameTag the name tag
   *  @param tabbed  are there tabs to create for each added property?
   */
  public EditablePreferenceGroup(String nameTag, boolean tabbed)
  {
    this.nameTag = nameTag;
    this.tabbed  = tabbed;
  }


  /**
   *  Create a preference group.
   *  @param nameTag the name tag
   *  @param tabbed  are there tabs to create for each added property?
   *  @param properties preferences to collect in this group
   */
  public EditablePreferenceGroup(String nameTag, boolean tabbed, EditablePreferenceProperty[] properties)
  {
    this(nameTag, tabbed);
    if (properties != null) {
      propertyList.addAll(Arrays.asList(properties));
    }
  }

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

  /**
   * Get a common title for the editor components.
   * This will be displayed in a titled border around the components.
   * It's okay to return nothing especially if {@link #getEditorProvider(java.util.Locale)}
   * does return only 1 editor component.
   *
   * @param l locale used for i18n
   * @return common title or <code>null</code>
   */
  public String getName(Locale l)
  {
    return I18n.getString(nameTag, l);
  }

  /**
   * Read the property value from the preferences.
   *
   * @param preferences preferences from where to read the property value
   */
  public void readFrom(Preferences preferences)
  {
    for (Iterator iterator = propertyList.iterator(); iterator.hasNext();) {
      PreferenceProperty property = (PreferenceProperty)iterator.next();
      property.readFrom(preferences);
    }
    if (tabbed) {
      tabIndex = preferences.getInt(nameTag+TABBED_SUFFIX, tabIndex);
    }
  }

  /**
   * Store the current property value in the preferences.
   *
   * @param preferences preferences where to store the property value
   */
  public void storeTo(Preferences preferences)
  {
    for (Iterator iterator = propertyList.iterator(); iterator.hasNext();) {
      PreferenceProperty property = (PreferenceProperty)iterator.next();
      property.storeTo(preferences);
    }
    if (tabbed) {
      preferences.putInt(nameTag+TABBED_SUFFIX, tabIndex);
    }
  }

  /**
   *  Get the i18n name tag.
   *  @return name tag
   */
  String getNameTag()
  {
    return nameTag;
  }

  /**
   *  Get an iterator over the collected properties.
   *  @return property iterator
   */
  Iterator propertyIterator()
  {
    return propertyList.iterator();
  }

  /**
   * Add a listener which will be called for all value changes.
   *
   * @param listener value change listener to add
   */
  public void addValueChangeListener(PropertyChangeListener listener)
  {
    for (Iterator iterator = propertyList.iterator(); iterator.hasNext();) {
      PreferenceProperty property = (PreferenceProperty)iterator.next();
      property.addValueChangeListener(listener);
    }
  }

  /**
   * Remove a listener which will be called for all value changes.
   *
   * @param listener value change listener to remove
   */
  public void removeValueChangeListener(PropertyChangeListener listener)
  {
    for (Iterator iterator = propertyList.iterator(); iterator.hasNext();) {
      PreferenceProperty property = (PreferenceProperty)iterator.next();
      property.removeValueChangeListener(listener);
    }
  }

  /**
   *  Add a property to the preference list.
   *  @param property    property to add
   */
  protected void addProperty(EditablePreferenceProperty property)
  {
    propertyList.add(property);
  }

  /**
   *  Get the tab pos.
   *  @return selected tab position
   */
  int getTabIndex()
  {
    return tabIndex;
  }

  /**
   *  Set the tab position.
   *  @param tabIndex
   */
  void setTabIndex(int tabIndex)
  {
    this.tabIndex = tabIndex;
  }
}
