
package uk.co.wingpath.gui;

import java.awt.*;
import javax.swing.*;
import uk.co.wingpath.event.*;
import uk.co.wingpath.util.*;

/**
* This provides a uniform interface to Swing components that allow the user
* to enter or select a single value (JTextField, JComboBox, etc.).
* <p>The component may have an associated label, which will be displayed
* alongside the component in containers such as {@link GridBagPanel}.
* <p>Changes to the component value made by the user may be monitored by
* registering a value listener with the component.
*/
public interface WComponent<T>
    extends Variable<T>
{
    /**
    * Gets the value of the component.
    * <p>If the user is currently editing the value, this will not affect
    * the value returned by this method until the user presses Enter or
    * permanently moves the focus, or the <code>checkValue</code> method
    * is called.
    * @return the value of the component.
    */
    T getValue ();

    /**
    * Sets the value of the component.
    * <p>If the user is currently editing the value, their changes will be
    * lost.
    * <p>This method does NOT fire a value event, unless the user was editing
    * the value.
    * @param value the new value for the component.
    */
    void setValue (T value);

    /**
    * Checks whether the value that the user has entered is valid.
    * <p>If the value is valid, it is stored as the value of the component,
    * a value event is fired, and <code>true</code> is returned.
    * If the value is not valid, an error
    * message is displayed and <code>false</code> is returned.
    * <p>If the user is not editing the value, <code>true</code> is returned.
    * <p>For components where the user can only select from a pre-defined
    * set of values (e.g. combo-boxes), <code>true</code> is returned.
    * @return <code>false</code> if the user has entered an invalid value,
    * <code>true</code> otherwise.
    */
    boolean checkValue ();

    /**
    * Tests whether the component value is different from the specified
    * value.
    * <p>If the user is currently editing the value, <code>true</code> is
    * returned. Otherwise, the current component value is compared with the
    * specified value using the <code>equals</code> method, and
    * <code>true</code> is returned if they differ.
    * @param oldValue the value to be compared with the current component
    * value.
    * @return <code>true</code> if the value has changed, <code>false</code>
    * otherwise.
    */
    boolean hasValueChanged (T oldValue);

    /**
     * Adds the specified value listener to receive 
     * value events from this component.
     * <p>A value event is fired when the user changes the component value.
     * Calling the <code>setValue</code> method does NOT fire a value event.
     * @param l the value listener to be added
     */ 
    void addValueListener (ValueListener l);

    /**
     * Removes the specified value listener so that it no longer
     * receives value events from this component.
     *
     * @param l the action listener to be removed
     */ 
    void removeValueListener (ValueListener l);

    /**
    * Gets the underlying JLabel.
    * <p>This method is intended to be used for adding the label to a
    * container, and should not be used for any other purpose.
    */
    JLabel getLabel ();

    /**
    * Gets the underlying JComponent.
    * <p>This method is intended to be used for adding the component to a
    * container, and should not be used for any other purpose.
    */
    JComponent getComponent ();

    /**
    * Sets the minimum width of the component, specified in pixels.
    * <p>If the minimum width of the component is less than <code>width</code>,
    * it is set to <code>width</code>.
    * <p>If the preferred width of the component is less than
    * <p>The maximum width is set to the preferred width, so that the component
    * cannot get wider if its content is changed.
    * <code>width</code>, it is set to <code>width</code>.
    * @param width the minimum width in pixels.
    */
    void setWidth (int width);

    /**
    * Sets the minimum width of the component, specified in characters.
    * <p>This method converts the supplied number of characters to pixels,
    * using the width of the character '0' in the font of the component plus
    * any insets, and then calls {@link #setWidth}.
    * @param width the minimum width in characters.
    */
    void setWidthChars (int width);

    /**
     * Sets the horizontal alignment of any text in the component.
     * Valid parameter values are:
     * <ul>
     * <li><code>SwingConstants.LEFT</code>
     * <li><code>SwingConstants.CENTER</code>
     * <li><code>SwingConstants.RIGHT</code>
     * <li><code>SwingConstants.LEADING</code>
     * <li><code>SwingConstants.TRAILING</code>
     * </ul>
     * @param alignment the required alignment
     */
    void setAlignment (int alignment);

    /**
     * Sets whether or not this component is enabled.
     * @param enabled true if this component should be enabled, false otherwise
     */
    void setEnabled (boolean enabled);

    /**
     * Specifies a keycode that indicates a mnemonic key.
     * @param mnemonic the mnemonic keycode.
     */
    void setMnemonic (int mnemonic);

    /**
     * Specifies a keycode that indicates a mnemonic key.
     * Also provides a hint to the look and feel as to which character in the
     * text should be decorated to represent the mnemonic.
     * @param mnemonic the mnemonic keycode.
     * @param index index into the String to underline
     */
    void setMnemonic (int mnemonic, int index);

    /**
     * Registers the text to display in a tool tip.
     * The text displays when the cursor lingers over the component.
     * @param text  the string to display; if the text is <code>null</code>,
     *              the tool tip is turned off for this component
     */
    void setToolTipText (String text);

    /**
    * Registers text to be displayed as tooltips for individual values.
    * <p>This method is for use with components such as combo boxes and
    * radio button groups which have a pre-defined set of possible values.
    * It has no effect for other kinds of components.
    * @param text tooltip text array, in same order as the values that were
    * supplied to the component constructor.
    */
    void setToolTipText (String [] text);

    /**
    * Requests that this component gets the input focus.
    */
    void requestFocusInWindow ();

    /**
    * Specifies whether or not this component should be editable.
    * @param editable whether the component should be editable.
    */
    void setEditable (boolean editable);

    /**
    * Sets the field to be used to mirror the value of this component.
    * @param mirror the mirror field.
    */
    void setMirror (MirrorField mirror);

    /**
    * Sets the background colour of this component.
    * @param bg the desired background colour.
    */
    void setBackground (Color bg);
}

