/*
 * @(#)StringObjectRadioPanel.java    2.3.3   2 May 2006
 *
 * Copyright 2006
 * College of Computer and Information Science
 * Northeastern University
 * Boston, MA  02115
 *
 * The Java Power Tools software may be used for educational
 * purposes as long as this copyright notice is retained intact
 * at the top of all source files.
 *
 * To discuss possible commercial use of this software, 
 * contact Richard Rasala at Northeastern University, 
 * College of Computer and Information Science,
 * 617-373-2462 or rasala@ccs.neu.edu.
 *
 * The Java Power Tools software has been designed and built
 * in collaboration with Viera Proulx and Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All publication rights are retained.  This software or its 
 * documentation may not be published in any media either
 * in whole or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */

package edu.neu.ccs.gui;

import edu.neu.ccs.*;
import edu.neu.ccs.util.*;
import edu.neu.ccs.quick.*;

import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;

/**
 * <P>A view based on <CODE>RadioPanel</CODE> for the selection of an object
 * using an associated string in a <CODE>StringObjectMap</CODE>.</P>
 *
 * <P>It is invalid to modify the items in this view after construction by
 * using methods of the base class.</P>
 *
 * @author  Richard Rasala
 * @version 2.3.3
 * @since   2.3
 */
public class StringObjectRadioPanel extends RadioPanel 
    implements StringObjectView 
{
    /** The internal two way map. */
    protected StringObjectMap pairmap = null;
    
    
    //////////////////
    // Constructors //
    //////////////////
    
    /**
     * <P>The default constructor.</P>
     *
     * <p>Other constructors:</p>
     *
     * <ul><code>
     *   <li>StringObjectRadioPanel(Object[][])</li>
     *   <li>StringObjectRadioPanel(Object[][], ActionListener)</li>
     *   <li>StringObjectRadioPanel(Object[][], ActionListener, int)</li>
     *   <li>StringObjectRadioPanel(Object[][], ActionListener, int, LayoutManager)</li>
     *   <li>StringObjectRadioPanel(StringObjectPair[])</li>
     *   <li>StringObjectRadioPanel(StringObjectPair[], ActionListener)</li>
     *   <li>StringObjectRadioPanel(StringObjectPair[], ActionListener, int)</li>
     *   <li>StringObjectRadioPanel(StringObjectPair[], ActionListener, int, LayoutManager)</li>
     *   <li>StringObjectRadioPanel(StringObjectMap)</li>
     *   <li>StringObjectRadioPanel(StringObjectMap, ActionListener)</li>
     *   <li>StringObjectRadioPanel(StringObjectMap, ActionListener, int)</li>
     *   <li>StringObjectRadioPanel(StringObjectMap, ActionListener, int, LayoutManager)</li>
     * </code></ul>
     */
    public StringObjectRadioPanel()
    {
        initializeSORadioPanel(null, null, -1, null);
    }
    
    
    /**
     * <P>The constructor that uses a pairs array to construct
     * the internal two way map.</P>
     *
     * @param pairs the string-object pairs to add
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(Object[][] pairs)
    {
        initializeSORadioPanel(StringObjectPair.toArray(pairs), null, -1, null);
    }
    
    
    /**
     * <P>The constructor that uses a pairs array to construct
     * the internal two way map;
     * and provides the action listener to perform when an option is selected.</P>
     *
     * @param pairs  the string-object pairs to add
     * @param action the action listener to perform when an option is selected
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(Object[][] pairs, ActionListener action)
    {
        initializeSORadioPanel(StringObjectPair.toArray(pairs), action, -1, null);
    }
    
    
    /**
     * <P>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action listener to perform when an option is selected;
     * and provides the initial selection string.</P>
     *
     * @param pairs     the string-object pairs to add
     * @param action    the action listener to perform when an option is selected
     * @param selection the desired preferred selection
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(Object[][] pairs, ActionListener action, int selection)
    {
        initializeSORadioPanel(StringObjectPair.toArray(pairs), action, selection, null);
    }
    
    
    /**
     * <P>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action listener to perform when an option is selected;
     * provides the initial selection string;
     * and provides the layout manager.</P>
     *
     * @param pairs     the string-object pairs to add
     * @param action    the action listener to perform when an option is selected
     * @param selection the desired preferred selection
     * @param layout    the layout manager
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel
        (Object[][] pairs, ActionListener action, int selection, LayoutManager layout)
    {
        initializeSORadioPanel(StringObjectPair.toArray(pairs), action, selection, layout);
    }
    
    
    /**
     * <P>The constructor that uses a pairs array to construct
     * the internal two way map.</P>
     *
     * @param pairs the string-object pairs to add
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(StringObjectPair[] pairs)
    {
        initializeSORadioPanel(pairs, null, -1, null);
    }
    
    
    /**
     * <P>The constructor that uses a pairs array to construct
     * the internal two way map;
     * and provides the action listener to perform when an option is selected.</P>
     *
     * @param pairs  the string-object pairs to add
     * @param action the action listener to perform when an option is selected
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(StringObjectPair[] pairs, ActionListener action)
    {
        initializeSORadioPanel(pairs, action, -1, null);
    }
    
    
    /**
     * <P>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action listener to perform when an option is selected;
     * and provides the initial selection string.</P>
     *
     * @param pairs     the string-object pairs to add
     * @param action    the action listener to perform when an option is selected
     * @param selection the desired preferred selection
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(StringObjectPair[] pairs, ActionListener action, int selection)
    {
        initializeSORadioPanel(pairs, action, selection, null);
    }
    
    
    /**
     * <P>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action listener to perform when an option is selected;
     * provides the initial selection string;
     * and provides the layout manager.</P>
     *
     * @param pairs     the string-object pairs to add
     * @param action    the action listener to perform when an option is selected
     * @param selection the desired preferred selection
     * @param layout    the layout manager
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel
        (StringObjectPair[] pairs, ActionListener action, int selection, LayoutManager layout)
    {
        initializeSORadioPanel(pairs, action, selection, layout);
    }
    
    
    /**
     * <P>The constructor that copies the given string-object map
     * to construct the internal string-object map.</P>
     *
     * @param map the string-object map to add
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(StringObjectMap map)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSORadioPanel(pairs, null, -1, null);
    }
    
    
    /**
     * <P>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * and provides the action listener to perform when an option is selected.</P>
     *
     * @param map    the string-object map to add
     * @param action the action listener to perform when an option is selected
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(StringObjectMap map, ActionListener action)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSORadioPanel(pairs, action, -1, null);
    }
    
    
    /**
     * <P>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action listener to perform when an option is selected;
     * and provides the initial selection string.</P>
     *
     * @param map       the string-object map to add
     * @param action    the action listener to perform when an option is selected
     * @param selection the desired preferred selection
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel(StringObjectMap map, ActionListener action, int selection)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSORadioPanel(pairs, action, selection, null);
    }
    
    
    /**
     * <P>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action listener to perform when an option is selected;
     * provides the initial selection string;
     * and provides the layout manager.</P>
     *
     * @param map       the string-object map to add
     * @param action    the action listener to perform when an option is selected
     * @param selection the desired preferred selection
     * @param layout    the layout manager
     * @see #StringObjectRadioPanel()
     */
    public StringObjectRadioPanel
        (StringObjectMap map, ActionListener action, int selection, LayoutManager layout)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSORadioPanel(pairs, action, selection, layout);
    }
    
    
    /**
     * The initializer.
     *
     * @param pairs     the string-object pairs to add
     * @param action    the action listener to perform when an option is selected
     * @param selection the desired preferred selection
     * @param layout    the layout manager
     */
    protected final void initializeSORadioPanel
        (StringObjectPair[] pairs, ActionListener action, int selection, LayoutManager layout)
    {
        // initialize map
        pairmap = new StringObjectMap(pairs);
        
        // initialize common action
        addActionListener(action);
        
        // initialize base class
        initializeRadioPanel(pairmap.getStrings(), selection, layout);
    }
    
    
    ////////////////
    // Public API //
    ////////////////
    
    /**
     * <P>Returns the currently selected string in the view.</P>
     *
     * @return the selected string
     * @see #getSelectedObject()
     */
    public final String getSelectedString() {
        return getSelectedLabel();
    }
    
    
    /**
     * <P>Returns the object corresponding to the currently
     * selected string in the view.</P>
     *
     * @return the selected object
     * @see #getSelectedString()
     */
    public final Object getSelectedObject() {
        return pairmap.getObject(getSelectedString());
    }
    
    
    /**
     * <P>Sets the view to the string provided that the
     * string is in the internal map.</P>
     *
     * <P>Does nothing if the string is <CODE>null</CODE>
     * or is not in the internal map.</P>
     *
     * <P>Does nothing if the view state will be unchanged.</P>
     *
     * @param string the string to use to set the view
     * @see #setSelectedObject(Object)
     */
    public final void setSelectedString(String string) {
        if (! pairmap.containsString(string))
            return;
        
        String oldString = getSelectedString();
        
        if (string.equals(oldString))
            return;
        
        setSelectedLabel(string);
        
        firePropertyChange(StringObjectView.VIEW_STATE, oldString, string);
    }
    
    
    /**
     * <P>Sets the view to the string corresponding to the
     * given object.</P>
     *
     * <P>Does nothing if the object is <CODE>null</CODE>
     * or is not in the internal map.</P>
     *
     * @param object the object to use to set the view
     * @see #setSelectedString(String)
     */
    public final void setSelectedObject(Object object) {
        setSelectedString(pairmap.getString(object));
    }
    
    
    /**
     * <p>Adds the new pair with the given string and object.</p>
     *
     * @param string the string
     * @param object the object
     * @see #addPair(StringObjectPair)
     */
    public final void addPair(String string, Object object) {
        if (string == null)
            return;
        
        if (object == null)
            return;
        
        addPair(new StringObjectPair(string, object));
    }
    
    
    /**
     * <p>Adds the new string-object pair.</p>
     *
     * @param pair the string-object pair
     */
    public final void addPair(StringObjectPair pair) {
        if (pair == null)
            return;
        
        addPairs(new StringObjectPair[] { pair });
    }
    
    
    /**
     * <p>Adds the new pairs.</p>
     *
     * @param pairs the string-object pairs to add
     * @see #addPairs(StringObjectPair[])
     * @see #addPairs(StringObjectMap)
     */
    public final void addPairs(Object[][] pairs) {
        if (pairs == null)
            return;
        
        addPairs(StringObjectPair.toArray(pairs));
    }
    
    
    /**
     * <p>Adds the new pairs.</p>
     *
     * @param pairs the string-object pairs to add
     * @see #addPairs(Object[][])
     * @see #addPairs(StringObjectMap)
     */
    public final void addPairs(StringObjectPair[] pairs) {
        if (pairs == null)
            return;
        
        int length = pairs.length;
        
        for (int i = 0; i < length; i++) {
            if (pairmap.addPair(pairs[i])) {
                addOption(pairs[i].getString());
            }
        }
    }
    
    
    /**
     * <p>Adds the new map.</p>
     *
     * @param map the string-object map to add
     * @see #addPairs(Object[][])
     * @see #addPairs(StringObjectPair[])
     */
    public final void addPairs(StringObjectMap map) {
        if (map == null)
            return;
        
        addPairs(map.getStringObjectPairs());
    }
    
    
}
