// Copyright 1996, Marimba Inc. All Rights Reserved.


// @(#)ChoiceWidget.java, 1.15, 12/17/96





package marimba.gui;





import java.awt.*;


import java.util.*;





import marimba.persist.*;





/**


 * A generic widget which provides multiple choices.


 * This can be represented as a list or as a menu.


 *


 * @author	Arthur van Hoff


 * @author	Klaas Waslander


 * @version 	1.15, 12/17/96


 */


public abstract class ChoiceWidget extends Widget {


    static final String NOCHOICE[] = new String[0];





    String choices[] = NOCHOICE;


    String names[] = NOCHOICE;





    /**


     * The current choice. No choice is represented by -1.


     * @see #getIntegerValue


     * @see #getStringValue


     * @see #getValue


     * @see #setValue


     * @see #getChoiceCount


     */


    public int  current = -1;





    /**


     * Default constructor.


     */


    public ChoiceWidget() {


	choices = new String[3];


	choices[0] = "one";


	choices[1] = "two";


	choices[2] = "three";


    }





    /**


     * Constructor for constructing a choiceWidget with


     * a given number of choices.


     */


    public ChoiceWidget(int nchoices, String choices[]) {


	this.choices = new String[nchoices];


	for (int index = 0; index < nchoices; index++) {


	    this.choices[index] = choices[index];


	}


    }





    /**


     * Get the properties of this widget.


     */


    public void getProperties(PropertyList list) {


	super.getProperties(list);


	list.setBoolean("disabled", disabled, false);


	StringBuffer buf = new StringBuffer();


	for (int i = 0 ; i < choices.length ; i++) {


	    if (i > 0) {


		buf.append(',');


	    }


	    buf.append(choices[i]);


	    if ((i < names.length) && (names[i] != null)) {


		buf.append('/');


		buf.append(names[i]);


	    }


	}


	list.setString("choices", buf.toString(), "");


	list.setString("value", getStringValue(), null);


    }





    /**


     * Get the properties for the children of this widget.


     */


    public void getChildProperties(PropertyList list) {


    }





    /**


     * Set the properties of this widget.


     */


    public void setProperties(PropertyList list) {


	super.setProperties(list);


	disabled = list.getBoolean("disabled", false);


	setChoices(list.getString("choices", ""));


	setValue(list.getString("value", null));





	// REMIND: remove after version 0.9


	String str = list.getString("values", null);


	if (str != null) {


	    names = new String[choices.length];


	    int i = 0;


	    for (StringTokenizer t = new StringTokenizer(str, ",") ; t.hasMoreTokens() ; i++) {


		names[i] = t.nextToken();


	    }


	}


    }





    /**


     * Get the number of choices.


     * @see #current


     */


    public int getChoiceCount() {


	return choices.length;


    }





    /**


     * Get index of a value.


     * @see #getStringValue


     */


    public int getValueIndex(String value) {


	if (value != null) {


	    for (int i = 0 ; i < names.length ; i++) {


		if (value.equals(names[i])) {


		    return i;


		}


	    }


	    for (int i = 0 ; i < choices.length ; i++) {


		if (value.equals(choices[i])) {


		    return i;


		}


	    }


	}


	return -1;


    }





    /**


     * Get the current choice. This will return -1 if


     * no choice is selected.


     * @see #current


     */


    public int getIntegerValue() {


	return current;


    }





    /**


     * Get the current choice.


     * @see #current


     * @see #getValueIndex


     */


    public String getStringValue() {


	return (current < 0) ? null :


	    ((current < names.length) && (names[current] != null)) ?


		names[current] : choices[current];


    }





    /**


     * Get the current choice.


     * @see #current


     * @see #getText


     */


    public Object getValue() {


	return getStringValue();


    }





    /**


     * Set the current choice.


     * @see #current


     */


    public void setValue(Object value) {


	if (value instanceof String) {


	    setValue((String)value);


	} else if (value instanceof Number) {


	    setValue(((Number)value).intValue());


	} else if (value == null) {


	    setValue("");


	}


    }





    /**


     * Set the current choice.


     * @see #current


     * @see #setText


     */


    public void setValue(String value) {


	setValue(getValueIndex(value));


    }





    /**


     * Set the current choice given the index.


     * @see #current


     */


    public void setValue(int value) {


	if (value < 0) {


	    value = -1;


	} else if (value >= choices.length) {


	    value = choices.length - 1;


	}


	if (current != value) {


	    current = value;


	}


    }





    /**


     * Get the current choice.


     * @see #getStringValue


     */


    public String getText() {


	String str = getStringValue();


	return (str == null) ? "" : str;


    }





    /**


     * Set the choice.


     * @see #setValue


     */


    public void setText(String value) {


	setValue(value);


    }





    /**


     * Get the choices, these are the strings that represent


     * the choices on screen.


     */


    public String[] getChoices() {


	return choices;


    }





    /**


     * Get the choice at the given position.


     */


    public String getChoice(int pos) {


	if (pos < choices.length) {


	    return choices[pos];


	}


	return null;


    }





    /**


     * Get the names of the choices. If a name exists for


     * a choice that name is used for accessing a choice.


     */


    public String[] getNames() {


	return names;


    }





    /**


     * Get the name at the given position.


     */


    public String getName(int pos) {


	if (pos < names.length) {


	    return names[pos];


	}


	return null;


    }





    /**


     * Append a choice to the list of possible choices.


     * of this choice widget.


     */


    public void addChoice(String newChoice) {


	insertChoiceAt(newChoice, getChoices().length);


    }





    /**


     * Insert a choice before the choice at the position.


     * with the given index.


     */


    public void insertChoiceAt(String newChoice, int index) {


	if (newChoice == null) {


	    newChoice = "";


	}


	String  currentChoices[] = getChoices();


	if (index < 0 || index > currentChoices.length) {


	    return;


	}





	String  newChoices[] = new String[choices.length+1];


	System.arraycopy(currentChoices, 0, newChoices, 0, index);


	newChoices[index] = newChoice;


	System.arraycopy(currentChoices, index, newChoices, index+1, currentChoices.length-index);





	choices = newChoices;


	if (current >= index) {


	    setValue(current+1);


	}


    }





    /**


     * Remove the first choice with the given name.


     */


    public void removeChoice(String oldChoice) {


	removeChoiceAt(getValueIndex(oldChoice));


    }





    /**


     * Remove the choice with the given index.


     */


    public void removeChoiceAt(int index) {


	String  currentChoices[] = getChoices();


	if (index < 0 || index >= currentChoices.length) {


	    return;


	}





	String  newChoices[] = new String[choices.length-1];


	System.arraycopy(currentChoices, 0, newChoices, 0, index);


	System.arraycopy(currentChoices, index+1, newChoices, index, currentChoices.length-index-1);





	choices = newChoices;


	if (index <= current) {


	    setValue(-1);


	}


    }





    /**


     * Remove all the choices from this widget.


     */


    public void removeAllChoices() {


	setChoices("");


	setValue(-1);


    }





    /**


     * Set choices from a comma seperated list.


     * Every choice can consist of a "choice/name" pair, where


     * the choice is used for the onscreen representation of the


     * choice and the name the choice represents in the code.


     */


    public void setChoices(String list) {


	if (choices == null) {


	    setChoices(NOCHOICE, NOCHOICE);


	    return;


	}


	Vector choices = new Vector();


	Vector names = new Vector();


	for (StringTokenizer t = new StringTokenizer(list, ",") ; t.hasMoreTokens() ; ) {


	    String str = t.nextToken();


	    int i = str.lastIndexOf('/');


	    if (i < 0) {


		choices.addElement(str);


	    } else {


		choices.addElement(str.substring(0, i));


		names.setSize(choices.size());


		names.setElementAt(str.substring(i+1), choices.size()-1);


	    }


	}


	if (choices.size() > 0) {


	    String chs[] = new String[choices.size()];


	    String nms[] = new String[names.size()];


	    choices.copyInto(chs);


	    names.copyInto(nms);


	    setChoices(chs, nms);


	} else {


	    setChoices(NOCHOICE, NOCHOICE);


	}


    }





    /**


     * Set the choices by specifying a Vector


     * containing the strings that represent


     * the choices.


     */


    public void setChoices(Vector choices) {


	if ((choices != null) && (choices.size() > 0)) {


	    String chs[] = new String[choices.size()];


	    choices.copyInto(chs);


	    setChoices(chs, NOCHOICE);


	} else {


	    setChoices(NOCHOICE, NOCHOICE);


	}


    }





    /**


     * Set the choices by specifying the strings


     * that appear on screen.


     */


    public void setChoices(String choices[]) {


	if (choices != null) {


	    setChoices(choices, NOCHOICE);


	} else {


	    setChoices(NOCHOICE, NOCHOICE);


	}


    }





    /**


     * Set the choices by specifying the choices and the


     * names by which they can be referenced. The strings


     * from the choices array appear on screen, the strings


     * in the names array are used to reference those choices.


     */


    public void setChoices(String choices[], String names[]) {


	if (choices == null) {


	    choices = NOCHOICE;


	}


	if (names == null) {


	    names = NOCHOICE;


	}


	this.choices = choices;


	this.names = names;


    }





    /**


     * Debugging.


     */


    public void paramString(StringBuffer buf) {


	super.paramString(buf);


	buf.append(",current=");


	buf.append(current);


	buf.append(",value=");


	buf.append(getStringValue());


    }


}


