/*
 * @(#)TextFieldView.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.filter.*;
import edu.neu.ccs.util.*;
import java.awt.*;
import java.awt.event.*;
import java.math.*;
import java.text.*;
import javax.swing.*;
import javax.swing.text.*;

/**
 * <P>A <CODE>{@link GeneralView GeneralView}</CODE> for input of
 * <CODE>{@link Stringable Stringable}</CODE> objects or elements
 * of the data state of a <CODE>Stringable</CODE> object.</P>
 *
 * @author  Jeff Raab
 * @author  Richard Rasala
 * @version 2.3.3
 * @since   1.0
 */
public class TextFieldView extends JTextField 
    implements GeneralView, Fragile, JPTConstants 
{
    
    /** Bound property name for the set preferred width property. */
    public static final String PREFERRED_WIDTH = "set.preferred.width";
    
    /** Bound property name for the auto select property. */
    public static final String AUTO_SELECT = "auto.select";
    
    
    /**
     * The default preferred width used in constructors if
     * there is no other data with which to set the width.
     */
    public static final int DEFAULT_WIDTH = 50;
    
    /**
     * <p>Extra width for setting the preferred width.</p>
     *
     * <p>If the preferred width is set with a sample string,
     * this value is added to the width of the sample string
     * to allow some extra space.</p>
     */
    public static final int EXTRA_WIDTH = 10;
    
    
    /**
     * The current preferred width if one is enabled or -1
     * if preferred width is disabled.
     */
    protected int preferredWidth = DEFAULT_WIDTH;
    
    
    /** Default autoselect policy for a text field view. */
    public static final boolean DEFAULT_AUTOSELECT_POLICY = true;
    
    /** Autoselect policy for this view. */
    protected boolean autoSelect = DEFAULT_AUTOSELECT_POLICY;
    
    
    /** The GeneralViewSupport object. */
    protected GeneralViewSupport delegate = null;
    
    
    //////////////////
    // Constructors //
    //////////////////
    
    /**
     * Constructs an empty text field view.
     *
     * <p>Other constructors:</p>
     *
     * <ul><code>
     *   <li>TextFieldView(int)
     *   <li>TextFieldView(String)
     *   <li>TextFieldView(String, int)
     *   <li>TextFieldView(String, String, String)
     *   <li>TextFieldView(String, String, String, int)
     *   <li>TextFieldView(String, String, String, String)
     *   <li>TextFieldView(String, String, String, String, int)
     *   <li>TextFieldView(Font)
     *   <li>TextFieldView(Font, int)
     *   <li>TextFieldView(String, Font)
     *   <li>TextFieldView(String, Font, int)
     *   <li>TextFieldView(String, String, String, Font)
     *   <li>TextFieldView(String, String, String, Font, int)
     *   <li>TextFieldView(String, String, String, String, Font)
     *   <li>TextFieldView(String, String, String, String, Font, int)
     *   <li>TextFieldView(Document)
     *   <li>TextFieldView(Document, int)
     *   <li>TextFieldView(Document, String, String)
     *   <li>TextFieldView(Document, String, String, int)
     *   <li>TextFieldView(Document, String, String, String)
     *   <li>TextFieldView(Document, String, String, String, int)
     * </code></ul>
     *
     * @since 1.1
     */
    public TextFieldView() {
        this("", null, null, null, null, 0);
    }
    
    
    /**
     * Constructs an empty text field view 
     * whose preferred width is the given width.
     *
     * @param width the minimum width of the text field
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(int width) {
        this("", null, null, null, null, width);
    }
    
    
    /**
     * Constructs a text field view with the given default text.
     *
     * @param text the default text for the text field
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(String text) {
        this(text, null, null, null, null, 0);
    }
    
    
    /**
     * Constructs a text field view with the given default text
     * whose preferred width is maximum of the given width and
     * the width of the default text.
     *
     * @param text  the default text for the text field
     * @param width the minimum width of the text field
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(String text, int width) {
        this(text, null, null, null, null, width);
    }
    
    
    /**
     * Constructs a text field view with the given default text,
     * for which the provided error prompt and dialog title 
     * will be used by the error recovery strategy.
     *
     * @param text        the default text for the text field
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(
        String text, 
        String errorPrompt, 
        String dialogTitle) 
    {
        this(text, errorPrompt, dialogTitle, null, null, 0);
    }
    
    
    /**
     * Constructs a text field view with the given default text,
     * for which the provided error prompt and dialog title 
     * will be used by the error recovery strategy
     * and whose preferred width is maximum of the given width
     * and the width of the default text.
     *
     * @param text        the default text for the text field
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param width       the minimum width of the text field
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(
        String text, 
        String errorPrompt, 
        String dialogTitle,
        int width) 
    {
        this(text, errorPrompt, dialogTitle, null, null, width);
    }
    
    
    /**
     * Constructs a text field view with the given default text,
     * for which the provided error prompt, dialog title, and 
     * suggestion will be used by the error recovery strategy.
     *
     * @param text        the default text for the text field
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param suggestion  the optional suggestion to use in error recovery
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(
        String text, 
        String errorPrompt, 
        String dialogTitle,
        String suggestion) 
    {
        this(text, errorPrompt, dialogTitle, suggestion, null, 0);
    }
    
    
    /**
     * Constructs a text field view with the given default text,
     * for which the provided error prompt, dialog title, and 
     * suggestion will be used by the error recovery strategy
     * and whose preferred width is maximum of the given width
     * and the width of the default text.
     *
     * @param text        the default text for the text field
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param suggestion  the optional suggestion to use in error recovery
     * @param width       the minimum width of the text field
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(
        String text, 
        String errorPrompt, 
        String dialogTitle,
        String suggestion,
        int width) 
    {
        this(text, errorPrompt, dialogTitle, suggestion, null, width);
    }
    
    
    /**
     * Constructs an empty text field view using the given font.
     *
     * @param font the font for the text field
     * @see #TextFieldView()
     * @since 2.3.3
     */
    public TextFieldView(Font font) {
        this("", null, null, null, font, 0);
    }
    
    
    /**
     * Constructs an empty text field view using the given font
     * whose preferred width is the given width.
     *
     * @param font the font for the text field
     * @param width the minimum width of the text field
     * @see #TextFieldView()
     * @since 2.3.3
     */
    public TextFieldView(Font font, int width) {
        this("", null, null, null, font, width);
    }
    
    
    /**
     * Constructs an empty text field view using the given font
     * with the given default text.
     *
     * @param text the default text for the text field
     * @param font the font for the text field
     * @see #TextFieldView()
     * @since 2.3.3
     */
    public TextFieldView(String text, Font font) {
        this(text, null, null, null, font, 0);
    }
    
    
    /**
     * Constructs an empty text field view using the given font
     * with the given default text
     * whose preferred width is maximum of the given width and
     * the width of the default text.
     *
     * @param text  the default text for the text field
     * @param font the font for the text field
     * @param width the minimum width of the text field
     * @see #TextFieldView()
     * @since 2.3.3
     */
    public TextFieldView(String text, Font font, int width) {
        this(text, null, null, null, font, width);
    }
    
    
    /**
     * Constructs an empty text field view using the given font
     * with the given default text,
     * for which the provided error prompt and dialog title 
     * will be used by the error recovery strategy.
     *
     * @param text        the default text for the text field
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param font the font for the text field
     * @see #TextFieldView()
     * @since 2.3.3
     */
    public TextFieldView(
        String text, 
        String errorPrompt, 
        String dialogTitle,
        Font font) 
    {
        this(text, errorPrompt, dialogTitle, null, font, 0);
    }
    
    
    /**
     * Constructs an empty text field view using the given font
     * with the given default text,
     * for which the provided error prompt and dialog title 
     * will be used by the error recovery strategy
     * and whose preferred width is maximum of the given width
     * and the width of the default text.
     *
     * @param text        the default text for the text field
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param font        the font for the text field
     * @param width       the minimum width of the text field
     * @see #TextFieldView()
     * @since 2.3.3
     */
    public TextFieldView(
        String text, 
        String errorPrompt, 
        String dialogTitle,
        Font font,
        int width) 
    {
        this(text, errorPrompt, dialogTitle, null, font, width);
    }
    
    
    /**
     * Constructs an empty text field view using the given font
     * with the given default text,
     * for which the provided error prompt, dialog title, and 
     * suggestion will be used by the error recovery strategy.
     *
     * @param text        the default text for the text field
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param suggestion  the optional suggestion to use in error recovery
     * @param font        the font for the text field
     * @see #TextFieldView()
     * @since 2.3.3
     */
    public TextFieldView(
        String text, 
        String errorPrompt, 
        String dialogTitle,
        String suggestion,
        Font font) 
    {
        this(text, errorPrompt, dialogTitle, suggestion, font, 0);
    }
    
    
    /**
     * Constructs an empty text field view using the given font
     * with the given default text,
     * for which the provided error prompt, dialog title, and 
     * suggestion will be used by the error recovery strategy
     * and whose preferred width is maximum of the given width
     * and the width of the default text.
     *
     * @param text        the default text for the text field
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param suggestion  the optional suggestion to use in error recovery
     * @param font        the font for the text field
     * @param width       the minimum width of the text field
     * @see #TextFieldView()
     * @since 2.3.3
     */
    public TextFieldView(
        String text, 
        String errorPrompt, 
        String dialogTitle,
        String suggestion,
        Font font,
        int width) 
    {
        super(text);
        initialize(errorPrompt, dialogTitle, suggestion, font, width);
    }
    
    
    /**
     * Constructs a text field view 
     * with the given document as its data model.
     *
     * @param document    the document to use as the data model
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(Document document) {
        this(document, null, null, null, 0);
    }
    
    
    /**
     * Constructs a text field view 
     * with the given document as its data model
     * and whose preferred width is the given width.
     *
     * @param document    the document to use as the data model
     * @param width       the minimum width of the text field
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(Document document, int width) {
        this(document, null, null, null, width);
    }
    
    
    /**
     * Constructs a text field view 
     * with the given document as its data model
     * for which the provided error prompt and dialog title 
     * will be used by the error recovery strategy.
     *
     * @param document    the document to use as the data model
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(
        Document document, 
        String errorPrompt, 
        String dialogTitle) 
    {
        this(document, errorPrompt, dialogTitle, null, 0);
    }
    
    
    /**
     * Constructs a text field view 
     * with the given document as its data model
     * for which the provided error prompt and dialog title
     * will be used by the error recovery strategy
     * and whose preferred width is the given width.
     *
     * @param document    the document to use as the data model
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param width       the minimum width of the text field
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(
        Document document, 
        String errorPrompt, 
        String dialogTitle,
        int width) 
    {
        this(document, errorPrompt, dialogTitle, null, width);
    }
    
    
    /**
     * Constructs a text field view 
     * with the given document as its data model
     * for which the provided error prompt, dialog title, and 
     * suggestion will be used by the error recovery strategy.
     *
     * @param document    the document to use as the data model
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param suggestion  the optional suggestion to use in error recovery
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(
        Document document, 
        String errorPrompt, 
        String dialogTitle,
        String suggestion) 
    {
        this(document, errorPrompt, dialogTitle, suggestion, 0);
    }
    
    
    /**
     * Constructs a text field view 
     * with the given document as its data model
     * for which the provided error prompt, dialog title, and 
     * suggestion will be used by the error recovery strategy
     * and whose preferred width is the given width.
     *
     * @param document    the document to use as the data model
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param suggestion  the optional suggestion to use in error recovery
     * @param width       the minimum width of the text field
     * @see #TextFieldView()
     * @since 1.1
     */
    public TextFieldView(
        Document document, 
        String errorPrompt, 
        String dialogTitle,
        String suggestion,
        int width) 
    {
        super(document, null, 0);
        initialize(errorPrompt, dialogTitle, suggestion, null, width);
    }
    
    
    /**
     * Performs the tasks common for constructors of this class.
     *
     * @param errorPrompt the prompt to use in error recovery
     * @param dialogTitle the dialog title to use in error recovery
     * @param suggestion  the optional suggestion to use in error recovery
     * @param font        the font for the text field
     * @param width       the minimum width of the text field
     * @since 2.3.3
     */
    private void initialize(
        String errorPrompt,
        String dialogTitle,
        String suggestion,
        Font font,
        int width) 
    {
        delegate = new GeneralViewSupport(
            this,
            this.listenerList,
            null,
            errorPrompt,
            dialogTitle,
            suggestion       );
        
        String text = getText();
        
        setDefaultViewState(text);
        
        if (font != null)
            super.setFont(font);
        
        setPreferredWidth(width, text);
        
        installFocusActions();
    }
    
    
    ////////////////
    // Public API //
    ////////////////
    
    /**
     * <p>Returns the preferred size of this view.</p>
     *
     * <p>This method proceeds as follows.</p>
     *
     * <p>The preferred size is calculated by the super class
     * method.  Then, if the preferred width set in this class
     * is positive, it is used to replace the width field of
     * the dimension returned by the super class method.  Then,
     * the revised preferred size is returned.</p>
     *
     * @return the value of the preferredSize property
     */
    public Dimension getPreferredSize() {
        Dimension dimension = super.getPreferredSize();
        
        int width = getPreferredWidth();
        
        if (width > 0)
            dimension.width = width;
        
        return dimension;
    }
    
    
    /**
     * <p>Returns the preferred width setting of this view.</p>
     *
     * <p>The value returned is positive or -1.</p>
     *
     * <p>If the value is -1 then it is not used to compute the
     * preferred size.</p>
     *
     * @return the current preferred width of this view
     */
    public int getPreferredWidth() {
        return preferredWidth;
    }
    
    
    /**
     * <p>Sets the preferred width of the view to the given width if
     * the given width is positive.</p>
     *
     * <p>If the given width is equal to zero, then the preferred width
     * is set to DEFAULT_WIDTH.</p>
     *
     * <p>If the given width is less than zero, then the preferred width
     * is set to -1 and the preferred size of the view is computed
     * entirely from the data of the super class.</p>
     *
     * <p>Refreshes the component in its parent view.</p>
     *
     * <p>Fires property change PREFERRED_WIDTH.</p>
     *
     * @param width the desired preferred width
     */
    public void setPreferredWidth(int width) {
        int oldWidth = getPreferredWidth();
        
        if (width < 0)
            preferredWidth = -1;
        else
        if (width == 0)
            preferredWidth = DEFAULT_WIDTH;
        else
            preferredWidth = width;
        
        refreshComponent();

        // notify listeners of property change
        if (preferredWidth != oldWidth)
            firePropertyChange(PREFERRED_WIDTH, oldWidth, preferredWidth);
    }
    
    
    /**
     * <p>Sets the preferred width of the view using the given minimum
     * width and sample string.</p>
     *
     * <p>This method proceeds as follows.</p>
     *
     * <p>If the sample string is <code>null</code> or of length zero,
     * then the preferred width is set via the call:
     * <code>setPreferredWidth(minWidth)</code>.</p>
     *
     * <p>Otherwise, if minWidth is zero, it is set to DEFAULT_WIDTH.
     * Then, the method <code>getSampleWidth</code> is called using
     * the current font of the view and the sample string.  The
     * preferred width is then set to be the maximum of minWidth and
     * the sample width.</p>
     *
     * <p>Refreshes the component in its parent view.</p>
     *
     * <p>Fires property change PREFERRED_WIDTH.</p>
     *
     * @param minWidth the minimum preferred width
     * @param sample the sample string used to calculate the width
     */
    public void setPreferredWidth(int minWidth, String sample) {
        if ((sample == null) || (sample.length() == 0)) {
            setPreferredWidth(minWidth);
        }
        else {
            if (minWidth == 0)
                minWidth = DEFAULT_WIDTH;
            
            int width = getSampleWidth(getFont(), sample);
            
            setPreferredWidth(Math.max(minWidth, width));
        }
    }
    
    
    /**
     * <p>Returns the sample width of a <code>JLabel</code> constucted
     * using a sample string consisting of N instances of the given
     * character c; the value EXTRA_WIDTH is added to allow for
     * extra white space.</p>
     *
     * <p>Returns 0 if N is less than or equal to zero</p>
     *
     * @param N the number of zero characters to use in the sample
     */
    public static int getSampleWidth(int N, char c) {
        if (N <= 0)
            return 0;
        
        StringBuffer buffer = new StringBuffer(N);
        
        for (int i = 0; i < N; i++)
            buffer.append(c);
        
        String sample = buffer.toString();
        
        return getSampleWidth(null, sample);
    }
    
    
    /**
     * <p>Returns the width of a <code>JLabel</code> constucted
     * using the given sample string
     * with the value EXTRA_WIDTH
     * added to allow for extra white space.</p>
     *
     * <p>Returns 0 if the sample string is <code>null</code>
     * or is of length zero.</p>
     *
     * @param sample the sample string used to calculate the width
     */
    public static int getSampleWidth(String sample) {
        return getSampleWidth(null, sample);
    }
    
    
    /**
     * <p>Returns the width of a <code>JLabel</code> constucted
     * using the given font and sample string
     * with the value EXTRA_WIDTH
     * added to allow for extra white space.</p>
     *
     * <p>Returns 0 if the sample string is <code>null</code>
     * or is of length zero.</p>
     *
     * <p>Ignores the font if it is <code>null</code>.</p>
     *
     * @param font the font to use for the sample string
     * @param sample the sample string used to calculate the width
     */
    public static int getSampleWidth(Font font, String sample) {
        if ((sample == null) || (sample.length() == 0))
            return 0;
        
        JLabel test = new JLabel(sample);
        
        if (font != null)
            test.setFont(font);
        
        Dimension dimension = test.getPreferredSize();
        
        return dimension.width + EXTRA_WIDTH;
    }
    
    
    /**
     * <p>Returns the maximum sample width of the strings in the given
     * strings array.</p>
     *
     * <p>Returns 0 if strings is <code>null</code>, has no objects, or
     * only has objects that are <code>null</code> or of length 0.</p>
     *
     * @param strings the array of strings to measure for sample width
     */
    public static int getWidthEstimate(String[] strings) {
        return getWidthEstimate(null, strings);
    }
    
    
    /**
     * <p>Returns the maximum sample width of the strings in the given
     * strings array relative to the given font.</p>
     *
     * <p>Returns 0 if strings is <code>null</code>, has no objects, or
     * only has objects that are <code>null</code> or of length 0.</p>
     *
     * <p>Ignores the font if it is <code>null</code>.</p>
     *
     * @param font the font to use for the sample strings
     * @param strings the array of strings to measure for sample width
     */
    public static int getWidthEstimate(Font font, String[] strings) {
        int width = 0;
        
        if (strings == null)
            return width;
        
        int length = strings.length;
        
        for (int i = 0; i < length; i++)
            width = Math.max
                (width, getSampleWidth(font, strings[i]));
        
        return width;
    }
    
    
    /**
     * <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>Calls the super <code>setFont</code> method and
     * then refreshes the component in its parent view.</p>
     *
     * <p>Fires property change FONT.</p>
     *
     * @param font the font to set for this view
     */
    public void setFont(Font font) {
        if (font == null)
            font = getDefaultFont();
    
        super.setFont(font);
        
        refreshComponent();
        
        // notify listeners of property change
        firePropertyChange(FONT, null, null);
    }
    
    
    /**
     * Returns the default font for a JTextField.
     *
     * @since 2.3.3
     */
    public static Font getDefaultFont() {
        return new JTextField(" ").getFont();
    }
    
    
    /** Refreshes the component by repacking the parent window. */
    public void refreshComponent() {
        Refresh.packParentWindow(this);
    }
    
    
    /**
     * <p>Sets whether or not the contents of this field
     * will be selected when it gains focus.</p>
     *
     * <p>Fires property change AUTO_SELECT.</p>
     * 
     * @param b whether or not the contents of this field
     *      will be selected upon a gain of focus
     * @see #getAutoSelect()
     */
    public void setAutoSelect(boolean b) {
        boolean oldAuto = getAutoSelect();
    
        autoSelect = b;
        
        // if the property has changed
        if (getAutoSelect() != oldAuto) {
        
            // notify listeners of property change
            firePropertyChange(
                AUTO_SELECT, 
                oldAuto, 
                getAutoSelect());
        }                
    }
    
    
    /**
     * Returns whether or not the contents of this field
     * will be selected when it gains focus.
     * 
     * @see #setAutoSelect(boolean)
     */
    public boolean getAutoSelect() {
        return autoSelect;
    }
    
    
    ///////////////////////////////
    // GeneralView and TypedView //
    ///////////////////////////////
    
    /**
     * <P>Returns a new text field view with the same font, preferred width,
     * data type, view state, default view state, initial input properties,
     * stringable filter, and auto-select setting as this text field view.</P>
     *
     * <P>The new text field view has its own document model.</P>
     *
     * @return a copy of this text field view
     */
    public GeneralView makeCopy() {
        TextFieldView copy = new TextFieldView();
        
        // copy geometry
        copy.setFont            (getFont());
        copy.setPreferredWidth  (getPreferredWidth());
        
        // copy settings
        copy.setDataType        (getDataType());
        copy.setViewState       (getViewState());
        copy.setDefaultViewState(getDefaultViewState());
        copy.setInputProperties (new InputProperties(getInputProperties()));
        copy.setFilter          (getFilter());
        copy.setAutoSelect      (getAutoSelect());
        
        return copy;
    }
    
    
    public void setDataType(Class dataType) {
        delegate.setDataType(dataType);
    }
    
    
    public Class getDataType() {
        return delegate.getDataType();
    }
    
    
    public void setFilter(StringableFilter filter) {
        delegate.setFilter(filter);
    }
    
    
    public StringableFilter getFilter() {
        return delegate.getFilter();
    }
    
    
    public Stringable demandObject() {
        return delegate.demandObject();
    }
    
    
    public Stringable requestObject()
        throws CancelledException
    {
        return delegate.requestObject();
    }
    
    
    public Stringable demandObject(StringableFilter filter) {
        return delegate.demandObject(filter);
    }
    
    
    public Stringable requestObject(StringableFilter filter)
        throws CancelledException
    {
        return delegate.requestObject(filter);
    }
    
    
    public Stringable demandObject(Class dataType, StringableFilter filter) {
        return delegate.demandObject(dataType, filter);
    }
    
    
    public Stringable requestObject(Class dataType, StringableFilter filter)
        throws CancelledException
    {
        return delegate.requestObject(dataType, filter);
    }
    
    
    public void setInputProperties(InputProperties properties) {
        delegate.setInputProperties(properties);
    }
    
    
    public InputProperties getInputProperties() {
        return delegate.getInputProperties();
    }
    
    
    public void setErrorPromptTitleSuggestion(
        String errorPrompt,
        String dialogTitle,
        String suggestion )
    {
         delegate.setErrorPromptTitleSuggestion(errorPrompt, dialogTitle, suggestion );
    }
    
    
    /////////////////
    // Displayable //
    /////////////////
    
    public void setViewState(String data) {
        String oldData = getText();
        
        if (data == null)
            data = "";
        
        setText(data);

        // notify listeners of property change
        firePropertyChange(VIEW_STATE, oldData, data);
    }
    
    
    public String getViewState() {
        return getText();
    }
    
    
    public void setDefaultViewState(String data) {
        delegate.setDefaultViewState(data);
    }
    
    
    public String getDefaultViewState() {
        return delegate.getDefaultViewState();
    }
    
    
    public void reset() {
        delegate.reset();
    }
    
    
    /////////////
    // Fragile //
    /////////////
    
    public void addMalformedDataListener(MalformedDataListener l) {
        delegate.addMalformedDataListener(l);
    }
    
    
    public void removeMalformedDataListener(MalformedDataListener l) {
        delegate.removeMalformedDataListener(l);
    }
    
    
    /////////////////////////////////
    // Demand and request for byte //
    /////////////////////////////////
    
    /**
     * Returns a <CODE>byte</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandByte(StringableFilter)
     * @see #demandByteAsHex()
     * @see #demandByteAsHex(StringableFilter)
     * @see #requestByte()
     * @see #requestByte(StringableFilter)
     * @see #requestByteAsHex()
     * @see #requestByteAsHex(StringableFilter)
     */
    public byte demandByte() {
        return demandByte(null);
    }
    
    
    /**
     * Returns a <CODE>byte</CODE> extracted from the field
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandByte()
     * @see #demandByteAsHex()
     * @see #demandByteAsHex(StringableFilter)
     * @see #requestByte()
     * @see #requestByte(StringableFilter)
     * @see #requestByteAsHex()
     * @see #requestByteAsHex(StringableFilter)
     */
    public byte demandByte(StringableFilter f) {
        XByte object = (XByte) demandObject(XByte.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>byte</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model.
     *
     * @see #demandByte()
     * @see #demandByte(StringableFilter)
     * @see #demandByteAsHex(StringableFilter)
     * @see #requestByte()
     * @see #requestByte(StringableFilter)
     * @see #requestByteAsHex()
     * @see #requestByteAsHex(StringableFilter)
     */
    public byte demandByteAsHex() {
        return demandByteAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>byte</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandByte()
     * @see #demandByte(StringableFilter)
     * @see #demandByteAsHex()
     * @see #requestByte()
     * @see #requestByte(StringableFilter)
     * @see #requestByteAsHex()
     * @see #requestByteAsHex(StringableFilter)
     */
    public byte demandByteAsHex(StringableFilter f) {
        HexXByte object = (HexXByte) demandObject(HexXByte.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>byte</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandByte()
     * @see #demandByte(StringableFilter)
     * @see #demandByteAsHex()
     * @see #demandByteAsHex(StringableFilter)
     * @see #requestByte(StringableFilter)
     * @see #requestByteAsHex()
     * @see #requestByteAsHex(StringableFilter)
     */
    public byte requestByte() throws CancelledException {
        return requestByte(null);
    }
    
    
    /**
     * Returns a <CODE>byte</CODE> extracted from the field
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandByte()
     * @see #demandByte(StringableFilter)
     * @see #demandByteAsHex()
     * @see #demandByteAsHex(StringableFilter)
     * @see #requestByte()
     * @see #requestByteAsHex()
     * @see #requestByteAsHex(StringableFilter)
     */
    public byte requestByte(StringableFilter f) throws CancelledException {
        XByte object = (XByte) requestObject(XByte.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>byte</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandByte()
     * @see #demandByte(StringableFilter)
     * @see #demandByteAsHex()
     * @see #demandByteAsHex(StringableFilter)
     * @see #requestByte()
     * @see #requestByte(StringableFilter)
     * @see #requestByteAsHex(StringableFilter)
     */
    public byte requestByteAsHex() throws CancelledException {
        return requestByteAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>byte</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandByte()
     * @see #demandByte(StringableFilter)
     * @see #demandByteAsHex()
     * @see #demandByteAsHex(StringableFilter)
     * @see #requestByte()
     * @see #requestByte(StringableFilter)
     * @see #requestByteAsHex()
     */
    public byte requestByteAsHex(StringableFilter f) throws CancelledException {
        HexXByte object = (HexXByte) requestObject(HexXByte.class, f);
        
        return object.getValue();
    }
    
    
    //////////////////////////////////
    // Demand and request for short //
    //////////////////////////////////
    
    /**
     * Returns a <CODE>short</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandShort(StringableFilter)
     * @see #demandShortAsHex()
     * @see #demandShortAsHex(StringableFilter)
     * @see #requestShort()
     * @see #requestShort(StringableFilter)
     * @see #requestShortAsHex()
     * @see #requestShortAsHex(StringableFilter)
     */
    public short demandShort() {
        return demandShort(null);
    }
    
    
    /**
     * Returns a <CODE>short</CODE> extracted from the field
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandShort()
     * @see #demandShortAsHex()
     * @see #demandShortAsHex(StringableFilter)
     * @see #requestShort()
     * @see #requestShort(StringableFilter)
     * @see #requestShortAsHex()
     * @see #requestShortAsHex(StringableFilter)
     */
    public short demandShort(StringableFilter f) {
        XShort object = (XShort) demandObject(XShort.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>short</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model.
     *
     * @see #demandShort()
     * @see #demandShort(StringableFilter)
     * @see #demandShortAsHex(StringableFilter)
     * @see #requestShort()
     * @see #requestShort(StringableFilter)
     * @see #requestShortAsHex()
     * @see #requestShortAsHex(StringableFilter)
     */
    public short demandShortAsHex() {
        return demandShortAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>short</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandShort()
     * @see #demandShort(StringableFilter)
     * @see #demandShortAsHex()
     * @see #requestShort()
     * @see #requestShort(StringableFilter)
     * @see #requestShortAsHex()
     * @see #requestShortAsHex(StringableFilter)
     */
    public short demandShortAsHex(StringableFilter f) {
        HexXShort object = (HexXShort) demandObject(HexXShort.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>short</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandShort()
     * @see #demandShort(StringableFilter)
     * @see #demandShortAsHex()
     * @see #demandShortAsHex(StringableFilter)
     * @see #requestShort(StringableFilter)
     * @see #requestShortAsHex()
     * @see #requestShortAsHex(StringableFilter)
     */
    public short requestShort() throws CancelledException {
        return requestShort(null);
    }
    
    
    /**
     * Returns a <CODE>short</CODE> extracted from the field
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandShort()
     * @see #demandShort(StringableFilter)
     * @see #demandShortAsHex()
     * @see #demandShortAsHex(StringableFilter)
     * @see #requestShort()
     * @see #requestShortAsHex()
     * @see #requestShortAsHex(StringableFilter)
     */
    public short requestShort(StringableFilter f) throws CancelledException {
        XShort object = (XShort) requestObject(XShort.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>short</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandShort()
     * @see #demandShort(StringableFilter)
     * @see #demandShortAsHex()
     * @see #demandShortAsHex(StringableFilter)
     * @see #requestShort()
     * @see #requestShort(StringableFilter)
     * @see #requestShortAsHex(StringableFilter)
     */
    public short requestShortAsHex() throws CancelledException {
        return requestShortAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>short</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandShort()
     * @see #demandShort(StringableFilter)
     * @see #demandShortAsHex()
     * @see #demandShortAsHex(StringableFilter)
     * @see #requestShort()
     * @see #requestShort(StringableFilter)
     * @see #requestShortAsHex()
     */
    public short requestShortAsHex(StringableFilter f) throws CancelledException {
        HexXShort object = (HexXShort) requestObject(HexXShort.class, f);
        
        return object.getValue();
    }
    
    
    ////////////////////////////////
    // Demand and request for int //
    ////////////////////////////////
    
    /**
     * Returns an <CODE>int</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandInt(StringableFilter)
     * @see #demandIntAsHex()
     * @see #demandIntAsHex(StringableFilter)
     * @see #requestInt()
     * @see #requestInt(StringableFilter)
     * @see #requestIntAsHex()
     * @see #requestIntAsHex(StringableFilter)
     */
    public int demandInt() {
        return demandInt(null);
    }
    
    
    /**
     * Returns an <CODE>int</CODE> extracted from the field
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandInt()
     * @see #demandIntAsHex()
     * @see #demandIntAsHex(StringableFilter)
     * @see #requestInt()
     * @see #requestInt(StringableFilter)
     * @see #requestIntAsHex()
     * @see #requestIntAsHex(StringableFilter)
     */
    public int demandInt(StringableFilter f) {
        XInt object = (XInt) demandObject(XInt.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns an <CODE>int</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model.
     *
     * @see #demandInt()
     * @see #demandInt(StringableFilter)
     * @see #demandIntAsHex(StringableFilter)
     * @see #requestInt()
     * @see #requestInt(StringableFilter)
     * @see #requestIntAsHex()
     * @see #requestIntAsHex(StringableFilter)
     */
    public int demandIntAsHex() {
        return demandIntAsHex(null);
    }
    
    
    /**
     * Returns an <CODE>int</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandInt()
     * @see #demandInt(StringableFilter)
     * @see #demandIntAsHex()
     * @see #requestInt()
     * @see #requestInt(StringableFilter)
     * @see #requestIntAsHex()
     * @see #requestIntAsHex(StringableFilter)
     */
    public int demandIntAsHex(StringableFilter f) {
        HexXInt object = (HexXInt) demandObject(HexXInt.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns an <CODE>int</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandInt()
     * @see #demandInt(StringableFilter)
     * @see #demandIntAsHex()
     * @see #demandIntAsHex(StringableFilter)
     * @see #requestInt(StringableFilter)
     * @see #requestIntAsHex()
     * @see #requestIntAsHex(StringableFilter)
     */
    public int requestInt() throws CancelledException {
        return requestInt(null);
    }
    
    
    /**
     * Returns an <CODE>int</CODE> extracted from the field
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandInt()
     * @see #demandInt(StringableFilter)
     * @see #demandIntAsHex()
     * @see #demandIntAsHex(StringableFilter)
     * @see #requestInt()
     * @see #requestIntAsHex()
     * @see #requestIntAsHex(StringableFilter)
     */
    public int requestInt(StringableFilter f) throws CancelledException {
        XInt object = (XInt) requestObject(XInt.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns an <CODE>int</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandInt()
     * @see #demandInt(StringableFilter)
     * @see #demandIntAsHex()
     * @see #demandIntAsHex(StringableFilter)
     * @see #requestInt()
     * @see #requestInt(StringableFilter)
     * @see #requestIntAsHex(StringableFilter)
     */
    public int requestIntAsHex() throws CancelledException {
        return requestIntAsHex(null);
    }
    
    
    /**
     * Returns an <CODE>int</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandInt()
     * @see #demandInt(StringableFilter)
     * @see #demandIntAsHex()
     * @see #demandIntAsHex(StringableFilter)
     * @see #requestInt()
     * @see #requestInt(StringableFilter)
     * @see #requestIntAsHex()
     */
    public int requestIntAsHex(StringableFilter f) throws CancelledException {
        HexXInt object = (HexXInt) requestObject(HexXInt.class, f);
        
        return object.getValue();
    }
    
    
    /////////////////////////////////
    // Demand and request for long //
    /////////////////////////////////
    
    /**
     * Returns a <CODE>long</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandLong(StringableFilter)
     * @see #demandLongAsHex()
     * @see #demandLongAsHex(StringableFilter)
     * @see #requestLong()
     * @see #requestLong(StringableFilter)
     * @see #requestLongAsHex()
     * @see #requestLongAsHex(StringableFilter)
     */
    public long demandLong() {
        return demandLong(null);
    }
    
    
    /**
     * Returns a <CODE>long</CODE> extracted from the field
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandLong()
     * @see #demandLongAsHex()
     * @see #demandLongAsHex(StringableFilter)
     * @see #requestLong()
     * @see #requestLong(StringableFilter)
     * @see #requestLongAsHex()
     * @see #requestLongAsHex(StringableFilter)
     */
    public long demandLong(StringableFilter f) {
        XLong object = (XLong) demandObject(XLong.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>long</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model.
     *
     * @see #demandLong()
     * @see #demandLong(StringableFilter)
     * @see #demandLongAsHex(StringableFilter)
     * @see #requestLong()
     * @see #requestLong(StringableFilter)
     * @see #requestLongAsHex()
     * @see #requestLongAsHex(StringableFilter)
     */
    public long demandLongAsHex() {
        return demandLongAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>long</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandLong()
     * @see #demandLong(StringableFilter)
     * @see #demandLongAsHex()
     * @see #requestLong()
     * @see #requestLong(StringableFilter)
     * @see #requestLongAsHex()
     * @see #requestLongAsHex(StringableFilter)
     */
    public long demandLongAsHex(StringableFilter f) {
        HexXLong object = (HexXLong) demandObject(HexXLong.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>long</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandLong()
     * @see #demandLong(StringableFilter)
     * @see #demandLongAsHex()
     * @see #demandLongAsHex(StringableFilter)
     * @see #requestLong(StringableFilter)
     * @see #requestLongAsHex()
     * @see #requestLongAsHex(StringableFilter)
     */
    public long requestLong() throws CancelledException {
        return requestLong(null);
    }
    
    
    /**
     * Returns a <CODE>long</CODE> extracted from the field
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandLong()
     * @see #demandLong(StringableFilter)
     * @see #demandLongAsHex()
     * @see #demandLongAsHex(StringableFilter)
     * @see #requestLong()
     * @see #requestLongAsHex()
     * @see #requestLongAsHex(StringableFilter)
     */
    public long requestLong(StringableFilter f) throws CancelledException {
        XLong object = (XLong) requestObject(XLong.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>long</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandLong()
     * @see #demandLong(StringableFilter)
     * @see #demandLongAsHex()
     * @see #demandLongAsHex(StringableFilter)
     * @see #requestLong()
     * @see #requestLong(StringableFilter)
     * @see #requestLongAsHex(StringableFilter)
     */
    public long requestLongAsHex() throws CancelledException {
        return requestLongAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>long</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandLong()
     * @see #demandLong(StringableFilter)
     * @see #demandLongAsHex()
     * @see #demandLongAsHex(StringableFilter)
     * @see #requestLong()
     * @see #requestLong(StringableFilter)
     * @see #requestLongAsHex()
     */
    public long requestLongAsHex(StringableFilter f) throws CancelledException {
        HexXLong object = (HexXLong) requestObject(HexXLong.class, f);
        
        return object.getValue();
    }
    
    
    /////////////////////////////////
    // Demand and request for float //
    /////////////////////////////////
    
    /**
     * Returns a <CODE>float</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandFloat(StringableFilter)
     * @see #demandFloatAsHex()
     * @see #demandFloatAsHex(StringableFilter)
     * @see #requestFloat()
     * @see #requestFloat(StringableFilter)
     * @see #requestFloatAsHex()
     * @see #requestFloatAsHex(StringableFilter)
     */
    public float demandFloat() {
        return demandFloat(null);
    }
    
    
    /**
     * Returns a <CODE>float</CODE> extracted from the field
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandFloat()
     * @see #demandFloatAsHex()
     * @see #demandFloatAsHex(StringableFilter)
     * @see #requestFloat()
     * @see #requestFloat(StringableFilter)
     * @see #requestFloatAsHex()
     * @see #requestFloatAsHex(StringableFilter)
     */
    public float demandFloat(StringableFilter f) {
        XFloat object = (XFloat) demandObject(XFloat.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>float</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model.
     *
     * @see #demandFloat()
     * @see #demandFloat(StringableFilter)
     * @see #demandFloatAsHex(StringableFilter)
     * @see #requestFloat()
     * @see #requestFloat(StringableFilter)
     * @see #requestFloatAsHex()
     * @see #requestFloatAsHex(StringableFilter)
     */
    public float demandFloatAsHex() {
        return demandFloatAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>float</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandFloat()
     * @see #demandFloat(StringableFilter)
     * @see #demandFloatAsHex()
     * @see #requestFloat()
     * @see #requestFloat(StringableFilter)
     * @see #requestFloatAsHex()
     * @see #requestFloatAsHex(StringableFilter)
     */
    public float demandFloatAsHex(StringableFilter f) {
        HexXFloat object = (HexXFloat) demandObject(HexXFloat.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>float</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandFloat()
     * @see #demandFloat(StringableFilter)
     * @see #demandFloatAsHex()
     * @see #demandFloatAsHex(StringableFilter)
     * @see #requestFloat(StringableFilter)
     * @see #requestFloatAsHex()
     * @see #requestFloatAsHex(StringableFilter)
     */
    public float requestFloat() throws CancelledException {
        return requestFloat(null);
    }
    
    
    /**
     * Returns a <CODE>float</CODE> extracted from the field
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandFloat()
     * @see #demandFloat(StringableFilter)
     * @see #demandFloatAsHex()
     * @see #demandFloatAsHex(StringableFilter)
     * @see #requestFloat()
     * @see #requestFloatAsHex()
     * @see #requestFloatAsHex(StringableFilter)
     */
    public float requestFloat(StringableFilter f) throws CancelledException {
        XFloat object = (XFloat) requestObject(XFloat.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>float</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandFloat()
     * @see #demandFloat(StringableFilter)
     * @see #demandFloatAsHex()
     * @see #demandFloatAsHex(StringableFilter)
     * @see #requestFloat()
     * @see #requestFloat(StringableFilter)
     * @see #requestFloatAsHex(StringableFilter)
     */
    public float requestFloatAsHex() throws CancelledException {
        return requestFloatAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>float</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandFloat()
     * @see #demandFloat(StringableFilter)
     * @see #demandFloatAsHex()
     * @see #demandFloatAsHex(StringableFilter)
     * @see #requestFloat()
     * @see #requestFloat(StringableFilter)
     * @see #requestFloatAsHex()
     */
    public float requestFloatAsHex(StringableFilter f) throws CancelledException {
        HexXFloat object = (HexXFloat) requestObject(HexXFloat.class, f);
        
        return object.getValue();
    }
    
    
    /////////////////////////////////
    // Demand and request for double //
    /////////////////////////////////
    
    /**
     * Returns a <CODE>double</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandDouble(StringableFilter)
     * @see #demandDoubleAsHex()
     * @see #demandDoubleAsHex(StringableFilter)
     * @see #requestDouble()
     * @see #requestDouble(StringableFilter)
     * @see #requestDoubleAsHex()
     * @see #requestDoubleAsHex(StringableFilter)
     */
    public double demandDouble() {
        return demandDouble(null);
    }
    
    
    /**
     * Returns a <CODE>double</CODE> extracted from the field
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandDouble()
     * @see #demandDoubleAsHex()
     * @see #demandDoubleAsHex(StringableFilter)
     * @see #requestDouble()
     * @see #requestDouble(StringableFilter)
     * @see #requestDoubleAsHex()
     * @see #requestDoubleAsHex(StringableFilter)
     */
    public double demandDouble(StringableFilter f) {
        XDouble object = (XDouble) demandObject(XDouble.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>double</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model.
     *
     * @see #demandDouble()
     * @see #demandDouble(StringableFilter)
     * @see #demandDoubleAsHex(StringableFilter)
     * @see #requestDouble()
     * @see #requestDouble(StringableFilter)
     * @see #requestDoubleAsHex()
     * @see #requestDoubleAsHex(StringableFilter)
     */
    public double demandDoubleAsHex() {
        return demandDoubleAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>double</CODE> extracted from the field
     * as hexidecimal data
     * using the mandatory model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandDouble()
     * @see #demandDouble(StringableFilter)
     * @see #demandDoubleAsHex()
     * @see #requestDouble()
     * @see #requestDouble(StringableFilter)
     * @see #requestDoubleAsHex()
     * @see #requestDoubleAsHex(StringableFilter)
     */
    public double demandDoubleAsHex(StringableFilter f) {
        HexXDouble object = (HexXDouble) demandObject(HexXDouble.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>double</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandDouble()
     * @see #demandDouble(StringableFilter)
     * @see #demandDoubleAsHex()
     * @see #demandDoubleAsHex(StringableFilter)
     * @see #requestDouble(StringableFilter)
     * @see #requestDoubleAsHex()
     * @see #requestDoubleAsHex(StringableFilter)
     */
    public double requestDouble() throws CancelledException {
        return requestDouble(null);
    }
    
    
    /**
     * Returns a <CODE>double</CODE> extracted from the field
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandDouble()
     * @see #demandDouble(StringableFilter)
     * @see #demandDoubleAsHex()
     * @see #demandDoubleAsHex(StringableFilter)
     * @see #requestDouble()
     * @see #requestDoubleAsHex()
     * @see #requestDoubleAsHex(StringableFilter)
     */
    public double requestDouble(StringableFilter f) throws CancelledException {
        XDouble object = (XDouble) requestObject(XDouble.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>double</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandDouble()
     * @see #demandDouble(StringableFilter)
     * @see #demandDoubleAsHex()
     * @see #demandDoubleAsHex(StringableFilter)
     * @see #requestDouble()
     * @see #requestDouble(StringableFilter)
     * @see #requestDoubleAsHex(StringableFilter)
     */
    public double requestDoubleAsHex() throws CancelledException {
        return requestDoubleAsHex(null);
    }
    
    
    /**
     * Returns a <CODE>double</CODE> extracted from the field
     * as hexidecimal data
     * using the optional model with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #demandDouble()
     * @see #demandDouble(StringableFilter)
     * @see #demandDoubleAsHex()
     * @see #demandDoubleAsHex(StringableFilter)
     * @see #requestDouble()
     * @see #requestDouble(StringableFilter)
     * @see #requestDoubleAsHex()
     */
    public double requestDoubleAsHex(StringableFilter f) throws CancelledException {
        HexXDouble object = (HexXDouble) requestObject(HexXDouble.class, f);
        
        return object.getValue();
    }
    
    
    /////////////////////////////////
    // Demand and request for char //
    /////////////////////////////////
    
    /**
     * Returns a <CODE>char</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandChar(StringableFilter)
     * @see #requestChar()
     * @see #requestChar(StringableFilter)
     */
    public char demandChar() {
        return demandChar(null);
    }
    
    
    /**
     * Returns a <CODE>char</CODE> extracted from the field
     * using the mandatory model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandChar()
     * @see #requestChar(StringableFilter)
     * @see #requestChar()
     */
    public char demandChar(StringableFilter f) {
        XChar object = (XChar) demandObject(XChar.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>char</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestChar(StringableFilter)
     * @see #demandChar()
     * @see #demandChar(StringableFilter)
     */
    public char requestChar() throws CancelledException {
        return requestChar(null);
    }
    
    
    /**
     * Returns a <CODE>char</CODE> extracted from the field
     * using the optional model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestChar()
     * @see #demandChar(StringableFilter)
     * @see #demandChar()
     */
    public char requestChar(StringableFilter f) 
        throws CancelledException 
    {
        XChar object = (XChar) requestObject(XChar.class, f);
        
        return object.getValue();
    }
    
    
    ////////////////////////////////////
    // Demand and request for boolean //
    ////////////////////////////////////
    
    /**
     * Returns a <CODE>boolean</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandBoolean(StringableFilter)
     * @see #requestBoolean()
     * @see #requestBoolean(StringableFilter)
     */
    public boolean demandBoolean() {
        return demandBoolean(null);
    }
    
    
    /**
     * Returns a <CODE>boolean</CODE> extracted from the field
     * using the mandatory model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandBoolean()
     * @see #requestBoolean(StringableFilter)
     * @see #requestBoolean()
     */
    public boolean demandBoolean(StringableFilter f) {
        XBoolean object = (XBoolean) demandObject(XBoolean.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>boolean</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestBoolean(StringableFilter)
     * @see #demandBoolean()
     * @see #demandBoolean(StringableFilter)
     */
    public boolean requestBoolean() throws CancelledException {
        return requestBoolean(null);
    }
    
    
    /**
     * Returns a <CODE>boolean</CODE> extracted from the field
     * using the optional model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestBoolean()
     * @see #demandBoolean(StringableFilter)
     * @see #demandBoolean()
     */
    public boolean requestBoolean(StringableFilter f) 
        throws CancelledException 
    {
        XBoolean object = (XBoolean) requestObject(XBoolean.class, f);
        
        return object.getValue();
    }
    
    
    ///////////////////////////////////
    // Demand and request for String //
    ///////////////////////////////////
    
    /**
     * Returns a <CODE>String</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandString(StringableFilter)
     * @see #requestString()
     * @see #requestString(StringableFilter)
     */
    public String demandString() {
        return demandString(null);
    }
    
    
    /**
     * Returns a <CODE>String</CODE> extracted from the field
     * using the mandatory model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandString()
     * @see #requestString(StringableFilter)
     * @see #requestString()
     */
    public String demandString(StringableFilter f) {
        XString object = (XString) demandObject(XString.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>String</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestString(StringableFilter)
     * @see #demandString()
     * @see #demandString(StringableFilter)
     */
    public String requestString() throws CancelledException {
        return requestString(null);
    }
    
    
    /**
     * Returns a <CODE>String</CODE> extracted from the field
     * using the optional model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestString()
     * @see #demandString(StringableFilter)
     * @see #demandString()
     */
    public String requestString(StringableFilter f) 
        throws CancelledException 
    {
        XString object = (XString) requestObject(XString.class, f);
        
        return object.getValue();
    }
    
    
    //////////////////////////////////
    // Demand and request for Color //
    //////////////////////////////////
    
    /**
     * <p>Returns a <CODE>Color</CODE> extracted from the field
     * using the mandatory model.</p>
     *
     * <p>Although the <code>Color</code> input methods are
     * available in this view, it is recommended that the
     * class <code>ColorView</code> be used for color input.</p>
     *
     * @see #demandColor(StringableFilter)
     * @see #requestColor()
     * @see #requestColor(StringableFilter)
     */
    public Color demandColor() {
        return demandColor(null);
    }
    
    
    /**
     * <p>Returns a <CODE>Color</CODE> extracted from the field
     * using the mandatory model, with the given filter.</p>
     *
     * <p>Although the <code>Color</code> input methods are
     * available in this view, it is recommended that the
     * class <code>ColorView</code> be used for color input.</p>
     *
     * @param f the filter to use for the input operation
     * @see #demandColor()
     * @see #requestColor(StringableFilter)
     * @see #requestColor()
     */
    public Color demandColor(StringableFilter f) {
        XColor object = (XColor) demandObject(XColor.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * <p>Returns a <CODE>Color</CODE> extracted from the field
     * using the optional model.</p>
     *
     * <p>Although the <code>Color</code> input methods are
     * available in this view, it is recommended that the
     * class <code>ColorView</code> be used for color input.</p>
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestColor(StringableFilter)
     * @see #demandColor()
     * @see #demandColor(StringableFilter)
     */
    public Color requestColor() throws CancelledException {
        return requestColor(null);
    }
    
    
    /**
     * <p>Returns a <CODE>Color</CODE> extracted from the field
     * using the optional model, with the given filter.</p>
     *
     * <p>Although the <code>Color</code> input methods are
     * available in this view, it is recommended that the
     * class <code>ColorView</code> be used for color input.</p>
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestColor()
     * @see #demandColor(StringableFilter)
     * @see #demandColor()
     */
    public Color requestColor(StringableFilter f) 
        throws CancelledException 
    {
        XColor object = (XColor) requestObject(XColor.class, f);
        
        return object.getValue();
    }
    
    
    ///////////////////////////////////////
    // Demand and request for BigInteger //
    ///////////////////////////////////////
    
    /**
     * Returns a <CODE>BigInteger</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandBigInteger(StringableFilter)
     * @see #requestBigInteger()
     * @see #requestBigInteger(StringableFilter)
     */
    public BigInteger demandBigInteger() {
        return demandBigInteger(null);
    }
    
    
    /**
     * Returns a <CODE>BigInteger</CODE> extracted from the field
     * using the mandatory model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandBigInteger()
     * @see #requestBigInteger(StringableFilter)
     * @see #requestBigInteger()
     */
    public BigInteger demandBigInteger(StringableFilter f) {
        XBigInteger object = (XBigInteger) demandObject(XBigInteger.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>BigInteger</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestBigInteger(StringableFilter)
     * @see #demandBigInteger()
     * @see #demandBigInteger(StringableFilter)
     */
    public BigInteger requestBigInteger() 
        throws CancelledException 
    {
        return requestBigInteger(null);
    }
    
    
    /**
     * Returns a <CODE>BigInteger</CODE> extracted from the field
     * using the optional model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestBigInteger()
     * @see #demandBigInteger(StringableFilter)
     * @see #demandBigInteger()
     */
    public BigInteger requestBigInteger(StringableFilter f) 
        throws CancelledException 
    {
        XBigInteger object = (XBigInteger) requestObject(XBigInteger.class, f);
        
        return object.getValue();
    }
    
    
    ///////////////////////////////////////
    // Demand and request for BigDecimal //
    ///////////////////////////////////////
    
    /**
     * Returns a <CODE>BigDecimal</CODE> extracted from the field
     * using the mandatory model.
     *
     * @see #demandBigDecimal(StringableFilter)
     * @see #requestBigDecimal()
     * @see #requestBigDecimal(StringableFilter)
     */
    public BigDecimal demandBigDecimal() {
        return demandBigDecimal(null);
    }
    
    
    /**
     * Returns a <CODE>BigDecimal</CODE> extracted from the field
     * using the mandatory model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #demandBigDecimal()
     * @see #requestBigDecimal(StringableFilter)
     * @see #requestBigDecimal()
     */
    public BigDecimal demandBigDecimal(StringableFilter f) {
        XBigDecimal object = (XBigDecimal) demandObject(XBigDecimal.class, f);
        
        return object.getValue();
    }
    
    
    /**
     * Returns a <CODE>BigDecimal</CODE> extracted from the field
     * using the optional model.
     *
     * @throws CancelledException
     *      if the user cancelled the input operation
     * @see #requestBigDecimal(StringableFilter)
     * @see #demandBigDecimal()
     * @see #demandBigDecimal(StringableFilter)
     */
    public BigDecimal requestBigDecimal() 
        throws CancelledException 
    {
        return requestBigDecimal(null);
    }
    
    
    /**
     * Returns a <CODE>BigDecimal</CODE> extracted from the field
     * using the optional model, with the given filter.
     *
     * @param f the filter to use for the input operation
     * @see #requestBigDecimal()
     * @see #demandBigDecimal(StringableFilter)
     * @see #demandBigDecimal()
     */
    public BigDecimal requestBigDecimal(StringableFilter f) 
        throws CancelledException 
    {
        XBigDecimal object = (XBigDecimal) requestObject(XBigDecimal.class, f);
        
        return object.getValue();
    }
    
    
    ///////////////////////
    // Protected methods //
    ///////////////////////
    
    /**
     * Installs a focus listener implementing
     * the autoselect functionality for this text field.
     */
    protected void installFocusActions() {
        FocusActionAdapter adapter = new FocusActionAdapter();
        
        adapter.addFocusGainedAction(new SimpleAction() {
            public void perform() {
                if (getAutoSelect())
                    selectAll();
            }
        });
        
        addFocusListener(adapter);
    }
    
}
