
package uk.co.wingpath.gui;

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


public class WDoubleField
    implements WComponent<Double>
{
    private final WTextField field;
    private double value;
    private final StatusBar statusBar;
    private final String label;
    private final double minValue;
    private final double maxValue;
    private final DoubleVerifier verifier;

    public WDoubleField (StatusBar statusBar, String label,
        double minValue, double maxValue, double initialValue)
    {
        Event.checkIsEventDispatchThread ();
        this.statusBar = statusBar;
        this.label = label;
        this.minValue = minValue;
        this.maxValue = maxValue;
        verifier = new DoubleVerifier ();
        field = new WTextField (statusBar, label);
        setValue (initialValue);
        field.setVerifier (verifier);
        field.addValueListener (new ValueListener ()
            {
                public void valueChanged (ValueEvent e)
                {
                    value = Double.parseDouble (field.getValue ().trim ());
                }
            });
    }

    public WDoubleField (StatusBar statusBar, String label)
    {
        this (statusBar, label, -Double.MAX_VALUE, Double.MAX_VALUE, 0.0);
    }

    public Double getValue ()
    {
        return value;
    }

    public void setValue (Double val)
    {
        Event.checkIsEventDispatchThread ();
        if (val < minValue || val > maxValue)
            throw new IllegalArgumentException ("Value out of range: " + val);

        // The order of the next two statements is important - we don't
        // want to fire a ValueEvent.
        value = val;
        field.setValue (Double.toString (value));
    }

    public boolean hasValueChanged (Double oldValue)
    {
        return field.hasValueChanged (Double.toString (oldValue));
    }

    public boolean checkValue ()
    {
        return field.checkValue ();
    }

    public void setAlignment (int alignment)
    {
        field.setAlignment (alignment);
    }

    public void setEditable (boolean editable)
    {
        field.setEditable (editable);
    }

    private class DoubleVerifier
        implements Verifier
    {
        private String rangeMessage ()
        {
            return "Must be a number in the range " + minValue +
                " to " + maxValue;
        }

        private void reportError (String msg)
        {
            if (label != null)
                msg = label + ": " + msg;
            statusBar.showError (msg);
        }

        public String verify (String str, boolean isChanging)
        {
            if (isChanging)
            {
                if (statusBar != null)
                    statusBar.clear ();
                return str;
            }
            if (str.equals (""))
            {
                reportError ("Value missing");
                return null;
            }

            try
            {
                double n = Double.parseDouble (str);
                if (n < minValue || n > maxValue)
                {
                    reportError (rangeMessage ());
                    return null;
                }
                if (statusBar != null)
                    statusBar.clear ();
                return Double.toString (n);
            }
            catch (NumberFormatException e)
            {
                reportError (rangeMessage ());
                return null;
            }
        }
    }

    public void setBackground (Color bg)
    {
        field.setBackground (bg);
    }

    public void requestFocusInWindow ()
    {
        field.requestFocusInWindow ();
    }

    public void setToolTipText (String text)
    {
        field.setToolTipText (text);
    }

    public void setToolTipText (String [] text)
    {
        field.setToolTipText (text);
    }

    public void setMnemonic (int mnemonic)
    {
        field.setMnemonic (mnemonic);
    }

    public void setMnemonic (int mnemonic, int index)
    {
        field.setMnemonic (mnemonic, index);
    }

    public void setEnabled (boolean enabled)
    {
        field.setEnabled (enabled);
    }

    public void setWidth (int width)
    {
        field.setWidth (width);
    }

    public void setWidthChars (int width)
    {
        field.setWidthChars (width);
    }

    public JComponent getComponent ()
    {
        return field.getComponent ();
    }

    public JLabel getLabel ()
    {
        return field.getLabel ();
    }

    public void setMirror (MirrorField mirror)
    {
        field.setMirror (mirror);
    }

    public void addValueListener (ValueListener l)
    {
        field.addValueListener (l);
    }

    public void removeValueListener (ValueListener l)
    {
        field.removeValueListener (l);
    }
}

