/*
 * @(#)StringObjectDropdown.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.text.*;
import java.util.*;
import javax.swing.*;

/**
 * <p>A view based on <code>JComboBox</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.  This view should not be made editable.</p>
 *
 * @author  Richard Rasala
 * @version 2.3.3
 * @since   2.3
 */
public class StringObjectDropdown extends Dropdown
    implements StringObjectView 
{
    /** The internal two way map. */
    protected StringObjectMap pairmap = null;
    
    
    /** Whether or not to sort. */
    protected boolean sort = false;
    
    
    //////////////////
    // Constructors //
    //////////////////
    
    /**
     * <p>The default constructor.</p>
     *
     * <p>Other constructors:</p>
     *
     * <ul><code>
     *   <li>StringObjectDropdown(Object[][])</li>
     *   <li>StringObjectDropdown(Object[][], Action)</li>
     *   <li>StringObjectDropdown(Object[][], Action, int)</li>
     *   <li>StringObjectDropdown(Object[][], Action, Font)</li>
     *   <li>StringObjectDropdown(Object[][], Action, Font, int)</li>
     *   <li>StringObjectDropdown(Object[][], Action, boolean)</li>
     *   <li>StringObjectDropdown(Object[][], Action, int, boolean)</li>
     *   <li>StringObjectDropdown(Object[][], Action, Font, boolean)</li>
     *   <li>StringObjectDropdown(Object[][], Action, Font, int, boolean)</li>
     *   <li>StringObjectDropdown(StringObjectPair[])</li>
     *   <li>StringObjectDropdown(StringObjectPair[], Action)</li>
     *   <li>StringObjectDropdown(StringObjectPair[], Action, int)</li>
     *   <li>StringObjectDropdown(StringObjectPair[], Action, Font)</li>
     *   <li>StringObjectDropdown(StringObjectPair[], Action, Font, int)</li>
     *   <li>StringObjectDropdown(StringObjectPair[], Action, boolean)</li>
     *   <li>StringObjectDropdown(StringObjectPair[], Action, int, boolean)</li>
     *   <li>StringObjectDropdown(StringObjectPair[], Action, Font, boolean)</li>
     *   <li>StringObjectDropdown(StringObjectPair[], Action, Font, int, boolean)</li>
     *   <li>StringObjectDropdown(StringObjectMap)</li>
     *   <li>StringObjectDropdown(StringObjectMap, Action)</li>
     *   <li>StringObjectDropdown(StringObjectMap, Action, int)</li>
     *   <li>StringObjectDropdown(StringObjectMap, Action, Font)</li>
     *   <li>StringObjectDropdown(StringObjectMap, Action, Font, int)</li>
     *   <li>StringObjectDropdown(StringObjectMap, Action, boolean)</li>
     *   <li>StringObjectDropdown(StringObjectMap, Action, int, boolean)</li>
     *   <li>StringObjectDropdown(StringObjectMap, Action, Font, boolean)</li>
     *   <li>StringObjectDropdown(StringObjectMap, Action, Font, int, boolean)</li>
     * </code></ul>
     *
     */
    public StringObjectDropdown()
    {
        initializeSODropdown(null, null, null, 0, false);
    }
    
    
    /**
     * <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   #StringObjectDropdown()
     */
    public StringObjectDropdown(Object[][] pairs)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), null, null, 0, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * and provides the action to perform when an option is selected.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(Object[][] pairs, Action action)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), action, null, 0, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * and provides the minimum width for the drop down list.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param minWidth the preferred minimum width
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(Object[][] pairs, Action action, int minWidth)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), action, null, minWidth, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * and provides the font.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(Object[][] pairs, Action action, Font font)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), action, font, 0, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * and provides the minimum width for the drop down list.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param minWidth the preferred minimum width
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(Object[][] pairs, Action action, Font font, int minWidth)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), action, font, minWidth, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (Object[][] pairs, Action action, boolean sort)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), action, null, 0, sort);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * provides the minimum width for the drop down list;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param minWidth the preferred minimum width
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (Object[][] pairs, Action action, int minWidth, boolean sort)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), action, null, minWidth, sort);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (Object[][] pairs, Action action, Font font, boolean sort)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), action, font, 0, sort);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * provides the minimum width for the drop down list;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param minWidth the preferred minimum width
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (Object[][] pairs, Action action, Font font, int minWidth, boolean sort)
    {
        initializeSODropdown(StringObjectPair.toArray(pairs), action, font, minWidth, sort);
    }
    
    
    /**
     * <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   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectPair[] pairs)
    {
        initializeSODropdown(pairs, null, null, 0, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * and provides the action to perform when an option is selected.</p>
     *
     * @param pairs  the string-object pairs to add
     * @param action the action to perform when an option is selected
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectPair[] pairs, Action action)
    {
        initializeSODropdown(pairs, action, null, 0, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * and provides the minimum width for the drop down list.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param minWidth the preferred minimum width
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectPair[] pairs, Action action, int minWidth)
    {
        initializeSODropdown(pairs, action, null, minWidth, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * and provides the font.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectPair[] pairs, Action action, Font font)
    {
        initializeSODropdown(pairs, action, font, 0, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * and provides the minimum width for the drop down list.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param minWidth the preferred minimum width
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectPair[] pairs, Action action, Font font, int minWidth)
    {
        initializeSODropdown(pairs, action, font, minWidth, false);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (StringObjectPair[] pairs, Action action, boolean sort)
    {
        initializeSODropdown(pairs, action, null, 0, sort);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * provides the minimum width for the drop down list;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param minWidth the preferred minimum width
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (StringObjectPair[] pairs, Action action, int minWidth, boolean sort)
    {
        initializeSODropdown(pairs, action, null, minWidth, sort);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (StringObjectPair[] pairs, Action action, Font font, boolean sort)
    {
        initializeSODropdown(pairs, action, font, 0, sort);
    }
    
    
    /**
     * <p>The constructor that uses a pairs array to construct
     * the internal two way map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * provides the minimum width for the drop down list;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param minWidth the preferred minimum width
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (StringObjectPair[] pairs, Action action, Font font, int minWidth, boolean sort)
    {
        initializeSODropdown(pairs, action, font, minWidth, sort);
    }
    
    
    /**
     * <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   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectMap map)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, null, null, 0, false);
    }
    
    
    /**
     * <p>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * and provides the action to perform when an option is selected.</p>
     *
     * @param map    the string-object map to add
     * @param action the action to perform when an option is selected
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectMap map, Action action)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, action, null, 0, false);
    }
    
    
    /**
     * <p>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action to perform when an option is selected;
     * and provides the minimum width for the drop down list.</p>
     *
     * @param map      the string-object map to add
     * @param action   the action to perform when an option is selected
     * @param minWidth the preferred minimum width
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectMap map, Action action, int minWidth)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, action, null, minWidth, false);
    }
    
    
    /**
     * <p>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action to perform when an option is selected
     * and provides the font.</p>
     *
     * @param map      the string-object map to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectMap map, Action action, Font font)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, action, font, 0, false);
    }
    
    
    /**
     * <p>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * and provides the minimum width for the drop down list.</p>
     *
     * @param map      the string-object map to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param minWidth the preferred minimum width
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown(StringObjectMap map, Action action, Font font, int minWidth)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, action, font, minWidth, false);
    }
    
    
    /**
     * <p>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action to perform when an option is selected;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param map      the string-object map to add
     * @param action   the action to perform when an option is selected
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (StringObjectMap map, Action action, boolean sort)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, action, null, 0, sort);
    }
    
    
    /**
     * <p>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action to perform when an option is selected;
     * provides the minimum width for the drop down list;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param map      the string-object map to add
     * @param action   the action to perform when an option is selected
     * @param minWidth the preferred minimum width
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (StringObjectMap map, Action action, int minWidth, boolean sort)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, action, null, minWidth, sort);
    }
    
    
    /**
     * <p>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param map      the string-object map to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (StringObjectMap map, Action action, Font font, boolean sort)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, action, font, 0, sort);
    }
    
    
    /**
     * <p>The constructor that copies the given string-object map
     * to construct the internal string-object map;
     * provides the action to perform when an option is selected;
     * provides the font;
     * provides the minimum width for the drop down list;
     * and allows the choice of whether or not to sort the strings.</p>
     *
     * @param map      the string-object map to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param minWidth the preferred minimum width
     * @param sort     whether or not to sort the strings before insertion in the view
     * @see   #StringObjectDropdown()
     */
    public StringObjectDropdown
        (StringObjectMap map, Action action, Font font, int minWidth, boolean sort)
    {
        StringObjectPair[] pairs =
            (map == null)
                ? null
                : map.getStringObjectPairs();
        
        initializeSODropdown(pairs, action, font, minWidth, sort);
    }
    
    
    /**
     * The initializer.
     *
     * @param pairs    the string-object pairs to add
     * @param action   the action to perform when an option is selected
     * @param font     the font for the view
     * @param minWidth the preferred minimum width
     * @param sort     whether or not to sort the strings before insertion in the view
     */
    protected final void initializeSODropdown(
        StringObjectPair[] pairs,
        Action             action,
        Font               font,
        int                minWidth,
        boolean            sort)
    {
        // remove existing strings from the view and then insert
        // new strings in the desired order
        super.removeAllItems();
        
        // initialize the pairmap
        pairmap = new StringObjectMap();
        
        // initialize or update the string object map
        pairmap.addPairs(pairs);
        
        // set whether or not to sort the strings
        this.sort = sort;
        
        // obtain the strings for the view
        String[] strings = getStrings();
        
        // initialize or update the view
        initializeDropdown(strings, null, font, minWidth, false);
        
        // action
        if (action != null)
            addActionListener(action);
    }
    
    
    ////////////////
    // Public API //
    ////////////////
    
    /**
     * <p>Returns the currently selected string in the view.</p>
     *
     * @return the selected string
     * @see #getSelectedObject()
     */
    public final String getSelectedString() {
        return (String)getSelectedItem();
    }
    
    
    /**
     * <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>
     *
     * <p>Fires property change Displayable.VIEW_STATE.</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;
        
        setSelectedItem(string);
        
        firePropertyChange(Displayable.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>
     *
     * <p>Fires property change Displayable.VIEW_STATE.</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>Returns the string object pairs in this view.  The string
     * object pairs are sorted if string sorting was specified in a
     * constructor.</p>
     *
     * @return the string object pairs in this view
     * @see #getStrings()
     * @see #getObjects()
     */
    public final StringObjectPair[] getStringObjectPairs() {
        StringObjectPair[] pairs = sort
            ? pairmap.getSortedStringObjectPairs()
            : pairmap.getStringObjectPairs();
        
        return pairs;
    }
    
    
    /**
     * <p>Returns the strings in this view.  The strings are sorted
     * if string sorting was specified in a constructor.</p>
     *
     * @return the strings in this view
     * @see #getStringObjectPairs()
     * @see #getObjects()
     */
    public final String[] getStrings() {
        String[] strings = sort
            ? pairmap.getSortedStrings()
            : pairmap.getStrings();
        
        return strings;
    }
    
    
    /**
     * <p>Returns the objects associated with the strings in this view.
     * The objects are sorted according to the ordering of the strings
     * if string sorting was specified in a constructor.</p>
     *
     * @return the objects associated with the strings in this view
     * @see #getStringObjectPairs()
     * @see #getStrings()
     */
    public final Object[] getObjects() {
        Object[] objects = sort
            ? pairmap.getSortedObjects()
            : pairmap.getObjects();
        
        return objects;
    }
    
    
    /**
     * <P>Returns the <CODE>String</CODE> associated with the given
     * <CODE>Object</CODE> in this view or <CODE>null</CODE> if no
     * association is found.</P>
     *
     * @param  object the object to associate with a string
     * @return the associated string or null
     * @see #getObject(String)
     */
    public final String getString(Object object) {
        return pairmap.getString(object);
    }
    
    
    /**
     * <P>Returns the <CODE>Object</CODE> associated with the given
     * <CODE>String</CODE> in this view or <CODE>null</CODE> if no
     * association is found.</P>
     *
     * @param  string the string to associate with an object
     * @return the associated object or null
     * @see #getString(Object)
     */
    public final Object getObject(String string) {
        return pairmap.getObject(string);
    }
    
    
    /**
     * <p>Clears the data structure and view and then adds the new pairs.</p>
     *
     * @param pairs the string-object pairs to set
     * @see #setPairs(StringObjectPair[])
     * @see #setPairs(StringObjectMap)
     */
    public final void setPairs(Object[][] pairs) {
        removeAllItems();
        addPairs(pairs);
    }
    
    
    /**
     * <p>Clears the data structure and view and then adds the new pairs.</p>
     *
     * @param pairs the string-object pairs to set
     * @see #setPairs(Object[][])
     * @see #setPairs(StringObjectMap)
     */
    public final void setPairs(StringObjectPair[] pairs) {
        removeAllItems();
        addPairs(pairs);
    }
    
    
    /**
     * <p>Clears the data structure and view and then adds the new map.</p>
     *
     * @param map the string-object map to set
     * @see #setPairs(Object[][])
     * @see #setPairs(StringObjectPair[])
     */
    public final void setPairs(StringObjectMap map) {
        removeAllItems();
        addPairs(map);
    }
    
    
    /**
     * <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;
        
        StringObjectPair[] oldContents = pairmap.getStringObjectPairs();
        
        int a = oldContents.length;
        int b = pairs.length;
        int c = a + b;
        
        StringObjectPair[] newContents = new StringObjectPair[c];
        
        for (int i = 0; i < a; i++)
            newContents[i] = oldContents[i];
        
        for (int i = 0; i < b; i++)
            newContents[a+i] = pairs[i];
            
        initializeSODropdown
            (newContents, null, null, getMinimumWidth(), sort);
    }
    
    
    /**
     * <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());
    }
    
    
    /**
     * <p>Clears the data structure and view.</p>
     */
    public final void removeAllItems() {
        super.removeAllItems();
        pairmap.clear();
    }
    
    
    /**
     * <p>Sets the font for this component.</p>
     *
     * <p>If the given font is <code>null</code> then it is set to
     * <code>getDefaultFont()</code>.</p>
     *
     * <p>Fires property change FONT.</p>
     *
     * @param font the font to set for this view
     */
    public void setFont(Font font) {
        // avoid problems during super class initialization
        
        if (pairmap == null) {
            super.setFont(font);
            return;
        }
        
        // if needed set the default font
        
        if (font == null)
            font = getDefaultFont();
        
        // reinitialize the drop down to reset all settings
        // except the selected string and default view state
        
        String selection = getSelectedString();
        
        String defaultViewState = getDefaultViewState();
        
        StringObjectPair[] pairs = pairmap.getStringObjectPairs();
        
        int minWidth = getMinimumWidth();
        
        removeAllItems();
        
        initializeSODropdown(pairs, null, font, minWidth, sort);
        
        setSelectedString(selection);
        
        setDefaultViewState(defaultViewState);
    }
    
    
}
