Hi Noel,

I just submitted this patch - thanks!!  I did make a few minor
changes, mostly per our coding conventions, which I know you looked
for and couldn't find.  The substantive changes are listed below:

* I changed TextInputListener#textValidatorChanged() to pass the
previous validator instead of the current one.  We generally try not
to pass information in events that can be obtained via API calls
(whereas the value that got overwritten would be lost if not passed in
the event).

* I changed TextInputListener#textValidChanged() to not only pass one
argument.  Again, the isTextValid flag is superfluous since it can be
obtained via API, and the previous value is implied since it's a
boolean.

* I changed TextInput#setValidator() to not throw if the text is
currently in an invalid state, to maintain parity with the
steady-state validation behavior.  Namely, if you have a validator set
on the TextInput, and you change the text in such a way as to make it
invalid, you don't get an exception; you simply get a textValidChanged
event.

* I removed the repaint() call from TextInput#validateText().  The
event is sufficient.  It's the skin's job to trigger a repaint if it
wants to factor the validity of the text input into its paint() method
(which you were correctly doing in TerraTextInputSkin).

-T

On Mon, Mar 23, 2009 at 5:43 AM, Noel Grandin <[email protected]> wrote:
> Hi
>
> Apache ICLA sent to apache org.
>
> Applied changes from comments.
>
> Regards, Noel Grandin.
>
>
> Index: wtk-test/src/pivot/wtk/test/TextInputValidatorTest.java
> ===================================================================
> --- wtk-test/src/pivot/wtk/test/TextInputValidatorTest.java    (revision 0)
> +++ wtk-test/src/pivot/wtk/test/TextInputValidatorTest.java    (revision 0)
> @@ -0,0 +1,134 @@
> +/*
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package pivot.wtk.test;
> +
> +import pivot.collections.Dictionary;
> +import pivot.wtk.Application;
> +import pivot.wtk.Component;
> +import pivot.wtk.DesktopApplicationContext;
> +import pivot.wtk.Display;
> +import pivot.wtk.Label;
> +import pivot.wtk.TextInput;
> +import pivot.wtk.TextInputListener;
> +import pivot.wtk.Window;
> +import pivot.wtk.text.TextNode;
> +import pivot.wtk.text.validation.FloatRangeValidator;
> +import pivot.wtk.text.validation.IntRangeValidator;
> +import pivot.wtk.text.validation.RegexTextValidator;
> +import pivot.wtk.text.validation.Validator;
> +import pivot.wtkx.WTKXSerializer;
> +
> +public class TextInputValidatorTest implements Application {
> +    private Window window = null;
> +    private TextInput textinputFloatRange = null;
> +    private Label invalidLabel = null;
> +    private TextInput textinputIntRange = null;
> +    private TextInput textinputDateRegex = null;
> +    private TextInput textinputCustomBoolean = null;
> +
> +    public void startup(Display display, Dictionary<String, String>
> properties)
> +            throws Exception {
> +        WTKXSerializer wtkxSerializer = new WTKXSerializer();
> +        window = new Window((Component)
> wtkxSerializer.readObject(getClass()
> +                .getResource("textInputValidator_test.wtkx")));
> +        textinputFloatRange = (TextInput) wtkxSerializer
> +                .getObjectByName("textinputFloatRange");
> +        textinputIntRange = (TextInput) wtkxSerializer
> +                .getObjectByName("textinputIntRange");
> +        textinputDateRegex = (TextInput) wtkxSerializer
> +                .getObjectByName("textinputDateRegex");
> +        textinputCustomBoolean = (TextInput) wtkxSerializer
> +                .getObjectByName("textinputCustomBoolean");
> +
> +        // standard float range model
> +        textinputFloatRange.setText("0.5");
> +        textinputFloatRange.setValidator(new FloatRangeValidator(0.3f,
> +                2000f));
> +
> +        // test the listener by updating a label
> +        textinputFloatRange.getTextInputListeners().add(
> +                new TextInputListener() {
> +                    public void maximumLengthChanged(TextInput textInput,
> +                            int previousMaximumLength) {
> +                    }
> +
> +                    public void passwordChanged(TextInput textInput) {
> +                    }
> +
> +                    public void promptChanged(TextInput textInput,
> +                            String previousPrompt) {
> +                    }
> +
> +                    public void textKeyChanged(TextInput textInput,
> +                            String previousTextKey) {
> +                    }
> +
> +                    public void textNodeChanged(TextInput textInput,
> +                            TextNode previousTextNode) {
> +                    }
> +
> +                    public void textSizeChanged(TextInput textInput,
> +                            int previousTextSize) {
> +                    }
> +
> +                    public void textValidChanged(TextInput textInput,
> +                            boolean isTextValid) {
> +                        invalidLabel.setText(isTextValid ? "valid" :
> "invalid");
> +                    }
> +                    public void textValidatorChanged(TextInput textInput,
> +                            Validator validator) {
> +                    }
> +                });
> +
> +        invalidLabel = (Label)
> wtkxSerializer.getObjectByName("invalidLabel");
> +
> +        // standard int range model
> +        textinputIntRange.setText("0");
> +        textinputIntRange.setValidator(new IntRangeValidator(0, 100));
> +
> +        // validate using a date regex.
> +        textinputDateRegex.setText("2009-09-01");
> +        textinputDateRegex
> +                .setValidator(new RegexTextValidator(
> +                        "(19|20)\\d\\d[- /.](0[1-9]|1[012])[-
> /.](0[1-9]|[12][0-9]|3[01])"));
> +
> +        // creating a custom model that only accepts "true" or "false"
> +        textinputCustomBoolean.setText("true");
> +        textinputCustomBoolean.setValidator(new Validator() {
> +            public boolean isValid(String s) {
> +                return "true".equals(s) || "false".equals(s);
> +            }
> +        });
> +
> +        window.setTitle("Text Input Validator Test");
> +        window.setMaximized(true);
> +        window.open(display);
> +    }
> +
> +    public boolean shutdown(boolean optional) {
> +        window.close();
> +        return true;
> +    }
> +
> +    public void resume() {
> +    }
> +
> +    public void suspend() {
> +    }
> +
> +    public static void main(String[] args) throws Exception {
> +        DesktopApplicationContext
> +                .main(new String[] {
> TextInputValidatorTest.class.getName() });
> +    }
> +}
> Index: wtk-test/src/pivot/wtk/test/textInputValidator_test.wtkx
> ===================================================================
> --- wtk-test/src/pivot/wtk/test/textInputValidator_test.wtkx    (revision 0)
> +++ wtk-test/src/pivot/wtk/test/textInputValidator_test.wtkx    (revision 0)
> @@ -0,0 +1,42 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!--
> +Licensed under the Apache License, Version 2.0 (the "License");
> +you may not use this file except in compliance with the License.
> +You may obtain a copy of the License at
> +
> +    http://www.apache.org/licenses/LICENSE-2.0
> +
> +Unless required by applicable law or agreed to in writing, software
> +distributed under the License is distributed on an "AS IS" BASIS,
> +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +See the License for the specific language governing permissions and
> +limitations under the License.
> +-->
> +
> +<TablePane styles="{padding:6, verticalSpacing:8}"
> +    xmlns:wtkx="http://pivot-toolkit.org/wtkx/2008"; xmlns="pivot.wtk">
> +    <columns>
> +        <TablePane.Column width="-1"/>
> +        <TablePane.Column width="-1"/>
> +        <TablePane.Column width="-1"/>
> +    </columns>
> +    <rows>
> +        <TablePane.Row height="-1">
> +            <Label text="float range 0.3-2000"/>
> +            <TextInput wtkx:id="textinputFloatRange"/>
> +            <Label wtkx:id="invalidLabel"/>
> +        </TablePane.Row>
> +        <TablePane.Row height="-1">
> +            <Label text="int range 0-100"/>
> +            <TextInput wtkx:id="textinputIntRange"/>
> +        </TablePane.Row>
> +        <TablePane.Row height="-1">
> +            <Label text="date regex"/>
> +            <TextInput wtkx:id="textinputDateRegex"/>
> +        </TablePane.Row>
> +        <TablePane.Row height="-1">
> +            <Label text="custom boolean"/>
> +            <TextInput wtkx:id="textinputCustomBoolean"/>
> +        </TablePane.Row>
> +    </rows>
> +</TablePane>
> Index: wtk/src/pivot/wtk/TextInput.java
> ===================================================================
> --- wtk/src/pivot/wtk/TextInput.java    (revision 756338)
> +++ wtk/src/pivot/wtk/TextInput.java    (working copy)
> @@ -23,6 +23,7 @@
>  import pivot.wtk.text.Node;
>  import pivot.wtk.text.NodeListener;
>  import pivot.wtk.text.TextNode;
> +import pivot.wtk.text.validation.Validator;
>
>  /**
>  * A component that allows a user to enter a single line of unformatted
> text.
> @@ -71,6 +72,18 @@
>                 listener.textKeyChanged(textInput, previousTextKey);
>             }
>         }
> +
> +        public void textValidChanged(TextInput textInput, boolean
> isTextValid) {
> +          for (TextInputListener listener : this) {
> +            listener.textValidChanged(textInput, isTextValid);
> +          }
> +        }
> +
> +        public void textValidatorChanged(TextInput textInput, Validator
> validator) {
> +            for (TextInputListener listener : this) {
> +              listener.textValidatorChanged(textInput, validator);
> +            }
> +         }
>     }
>
>     /**
> @@ -132,7 +145,9 @@
>     private boolean password = false;
>     private String prompt = null;
>     private String textKey = null;
> -
> +    private Validator validator = null;
> +    private boolean textValid = true;
> +
>     private NodeListener textNodeListener = new NodeListener() {
>         public void parentChanged(Node node, Element previousParent) {
>         }
> @@ -151,6 +166,7 @@
>
>
> textInputCharacterListeners.charactersInserted(TextInput.this, offset,
> characterCount);
>             textInputTextListeners.textChanged(TextInput.this);
> +            validateText();
>         }
>
>         public void rangeRemoved(Node node, int offset, int
> characterCount) {
> @@ -164,6 +180,7 @@
>
>
> textInputCharacterListeners.charactersRemoved(TextInput.this, offset,
> characterCount);
>             textInputTextListeners.textChanged(TextInput.this);
> +            validateText();
>         }
>     };
>
> @@ -191,7 +208,7 @@
>         if (textNode.getCharacterCount() > maximumLength) {
>             throw new IllegalArgumentException("Text length is greater
> than maximum length.");
>         }
> -
> +
>         TextNode previousTextNode = this.textNode;
>
>         if (previousTextNode != textNode) {
> @@ -211,6 +228,7 @@
>
>             textInputListeners.textNodeChanged(this, previousTextNode);
>             textInputTextListeners.textChanged(this);
> +            validateText();
>         }
>     }
>
> @@ -603,6 +621,42 @@
>         }
>     }
>
> +    public boolean isTextValid() {
> +        return this.textValid;
> +    }
> +
> +    /**
> +     * set the validator for the text field.
> +     *
> +     * @exception IllegalStateException if the current text is invalid
> according to the new TextValidator
> +     */
> +    public void setValidator(Validator validator) {
> +        if (validator != null && !validator.isValid(getText())) {
> +            throw new IllegalStateException(
> +                    "cannot set a TextValidator (" + validator + ")
> that results in the current text (" + getText() + ") being invalid");
> +        }
> +        this.validator = validator;
> +        textInputListeners.textValidatorChanged(this, this.validator);
> +        if (!textValid) {
> +            textValid = true;
> +            textInputListeners.textValidChanged(this, textValid);
> +        }
> +    }
> +
> +    public Validator getValidator() {
> +        return this.validator;
> +    }
> +
> +    private void validateText() {
> +        String text = getText();
> +        boolean b = validator == null ? true : validator.isValid(text);
> +        if (b != this.textValid) {
> +            this.textValid = b;
> +            textInputListeners.textValidChanged(this, textValid);
> +            repaint();
> +        }
> +    }
> +
>     /**
>      * Returns the text input listener list.
>      */
> Index: wtk/src/pivot/wtk/TextInputListener.java
> ===================================================================
> --- wtk/src/pivot/wtk/TextInputListener.java    (revision 756338)
> +++ wtk/src/pivot/wtk/TextInputListener.java    (working copy)
> @@ -16,6 +16,7 @@
>  package pivot.wtk;
>
>  import pivot.wtk.text.TextNode;
> +import pivot.wtk.text.validation.Validator;
>
>  /**
>  * Text input listener interface.
> @@ -68,4 +69,17 @@
>      * @param previousTextKey
>      */
>     public void textKeyChanged(TextInput textInput, String
> previousTextKey);
> +
> +    /**
> +     * Called when the text changes validity.
> +     *
> +     * @param textInput
> +     * @param isTextValid is the text currently valid
> +     */
> +    public void textValidChanged(TextInput textInput, boolean isTextValid);
> +
> +    /**
> +     * Called when the validator changes..
> +     */
> +    public void textValidatorChanged(TextInput textInput, Validator
> validator);
>  }
> Index: wtk/src/pivot/wtk/skin/terra/TerraTextInputSkin.java
> ===================================================================
> --- wtk/src/pivot/wtk/skin/terra/TerraTextInputSkin.java    (revision
> 756338)
> +++ wtk/src/pivot/wtk/skin/terra/TerraTextInputSkin.java    (working copy)
> @@ -39,12 +39,13 @@
>  import pivot.wtk.Mouse;
>  import pivot.wtk.Platform;
>  import pivot.wtk.TextInput;
> -import pivot.wtk.TextInputListener;
>  import pivot.wtk.TextInputCharacterListener;
> +import pivot.wtk.TextInputListener;
>  import pivot.wtk.TextInputSelectionListener;
>  import pivot.wtk.Theme;
>  import pivot.wtk.skin.ComponentSkin;
>  import pivot.wtk.text.TextNode;
> +import pivot.wtk.text.validation.Validator;
>
>  /**
>  * Text input skin.
> @@ -233,6 +234,7 @@
>     private Color promptColor;
>     private Color backgroundColor;
>     private Color disabledBackgroundColor;
> +    private Color invalidTextBackgroundColor;
>     private Color borderColor;
>     private Color disabledBorderColor;
>     private Insets padding;
> @@ -256,6 +258,7 @@
>         disabledColor = theme.getColor(7);
>         backgroundColor = theme.getColor(11);
>         disabledBackgroundColor = theme.getColor(10);
> +        invalidTextBackgroundColor = theme.getColor(25);
>         borderColor = theme.getColor(7);
>         disabledBorderColor = theme.getColor(7);
>         padding = new Insets(2);
> @@ -346,6 +349,9 @@
>             borderColor = this.disabledBorderColor;
>             bevelColor = disabledBevelColor;
>         }
> +        if (!textInput.isTextValid()) {
> +            backgroundColor = invalidTextBackgroundColor;
> +        }
>
>         graphics.setStroke(new BasicStroke());
>
> @@ -609,6 +615,32 @@
>         setBackgroundColor(theme.getColor(color));
>     }
>
> +    public Color getInvalidTextBackgroundColor() {
> +        return invalidTextBackgroundColor;
> +    }
> +
> +    public void setInvalidTextBackgroundColor(Color color) {
> +        if (invalidTextBackgroundColor == null) {
> +            throw new
> IllegalArgumentException("invalidTextBackgroundColor is null.");
> +        }
> +
> +        this.invalidTextBackgroundColor = color;
> +        repaintComponent();
> +    }
> +
> +    public final void setInvalidTextBackgroundColor(String color) {
> +        if (color == null) {
> +            throw new
> IllegalArgumentException("invalidTextBackgroundColor is null.");
> +        }
> +
> +        setInvalidTextBackgroundColor(decodeColor(color));
> +    }
> +
> +    public final void setInvalidTextBackgroundColor(int color) {
> +        TerraTheme theme = (TerraTheme)Theme.getTheme();
> +        setInvalidTextBackgroundColor(theme.getColor(color));
> +    }
> +
>     public Color getDisabledBackgroundColor() {
>         return disabledBackgroundColor;
>     }
> @@ -635,7 +667,7 @@
>         TerraTheme theme = (TerraTheme)Theme.getTheme();
>         setDisabledBackgroundColor(theme.getColor(color));
>     }
> -
> +
>     public Color getBorderColor() {
>         return borderColor;
>     }
> @@ -1064,20 +1096,19 @@
>     public void focusedChanged(Component component, boolean temporary) {
>         super.focusedChanged(component, temporary);
>
> -        TextInput textInput = (TextInput)getComponent();
> +        TextInput textInput = (TextInput) getComponent();
>         TextNode textNode = textInput.getTextNode();
>
>         if (component.isFocused()) {
>             showCaret(textInput.getSelectionLength() == 0);
>
> -            if (!temporary
> -                && Mouse.getCapturer() != component) {
> +            if (!temporary && Mouse.getCapturer() != component) {
>                 textInput.setSelection(0, textNode.getCharacterCount());
>             }
>         } else {
>             if (!temporary) {
>                 textInput.setSelection(textInput.getSelectionStart()
> -                    + textInput.getSelectionLength(), 0);
> +                        + textInput.getSelectionLength(), 0);
>             }
>
>             showCaret(false);
> @@ -1110,7 +1141,15 @@
>     public void textKeyChanged(TextInput textInput, String
> previousTextKey) {
>         // No-op
>     }
> -
> +
> +    public void textValidChanged(TextInput textInput, boolean isValid) {
> +        repaintComponent();
> +    }
> +
> +    public void textValidatorChanged(TextInput textInput, Validator
> validator) {
> +        // No-op
> +    }
> +
>     // Text input character events
>     public void charactersInserted(TextInput textInput, int index, int
> count) {
>         updateSelection();
> @@ -1207,4 +1246,5 @@
>
>         repaintComponent();
>     }
> +
>  }
> Index: wtk/src/pivot/wtk/skin/terra/TerraTheme_default.json
> ===================================================================
> --- wtk/src/pivot/wtk/skin/terra/TerraTheme_default.json    (revision
> 756338)
> +++ wtk/src/pivot/wtk/skin/terra/TerraTheme_default.json    (working copy)
> @@ -9,6 +9,7 @@
>         "#2b5580",
>         "#3c77b2",
>         "#14538b",
> -        "#b0000f"
> +        "#b0000f",
> +        "#ffff00"
>     ]
>  }
> Index: wtk/src/pivot/wtk/text/validation/DecimalValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/DecimalValidator.java    (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/DecimalValidator.java    (revision 0)
> @@ -0,0 +1,36 @@
> +package pivot.wtk.text.validation;
> +
> +import java.text.DecimalFormat;
> +import java.text.NumberFormat;
> +import java.text.ParseException;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public abstract class DecimalValidator extends
> FormattedValidator<NumberFormat>
> +{
> +    protected DecimalValidator(DecimalFormat format)
> +    {
> +        super(format);
> +    }
> +
> +    protected DecimalValidator()
> +    {
> +        super(NumberFormat.getInstance());
> +    }
> +
> +    /** helper for textToObject */
> +    protected final Number parse(String text)
> +    {
> +        try
> +        {
> +            return format.parse(text);
> +        }
> +        catch (ParseException ex)
> +        {
> +            // this should never happen
> +            throw new RuntimeException(ex);
> +        }
> +    }
> +}
> \ No newline at end of file
> Index: wtk/src/pivot/wtk/text/validation/DoubleRangeValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/DoubleRangeValidator.java
> (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/DoubleRangeValidator.java
> (revision 0)
> @@ -0,0 +1,25 @@
> +package pivot.wtk.text.validation;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public class DoubleRangeValidator extends DoubleValidator
> +{
> +    private final double minValue, maxValue;
> +
> +    public DoubleRangeValidator(double minValue, double maxValue)
> +    {
> +        this.minValue = minValue;
> +        this.maxValue = maxValue;
> +    }
> +
> +   �...@override
> +    public boolean isValid(String text)
> +    {
> +        if (!super.isValid(text))
> +            return false;
> +        final double f = textToObject(text);
> +        return f >= minValue && f <= maxValue;
> +    }
> +}
> \ No newline at end of file
> Index: wtk/src/pivot/wtk/text/validation/DoubleValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/DoubleValidator.java    (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/DoubleValidator.java    (revision 0)
> @@ -0,0 +1,17 @@
> +package pivot.wtk.text.validation;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public class DoubleValidator extends DecimalValidator
> +{
> +    public DoubleValidator()
> +    {
> +    }
> +
> +    protected final Double textToObject(String text)
> +    {
> +        return parse(text).doubleValue();
> +    }
> +}
> \ No newline at end of file
> Index: wtk/src/pivot/wtk/text/validation/FloatRangeValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/FloatRangeValidator.java
> (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/FloatRangeValidator.java
> (revision 0)
> @@ -0,0 +1,25 @@
> +package pivot.wtk.text.validation;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public class FloatRangeValidator extends FloatValidator
> +{
> +    private final float minValue, maxValue;
> +
> +    public FloatRangeValidator(float minValue, float maxValue)
> +    {
> +        this.minValue = minValue;
> +        this.maxValue = maxValue;
> +    }
> +
> +   �...@override
> +    public boolean isValid(String text)
> +    {
> +        if (!super.isValid(text))
> +            return false;
> +        final float f = textToObject(text);
> +        return f >= minValue && f <= maxValue;
> +    }
> +}
> \ No newline at end of file
> Index: wtk/src/pivot/wtk/text/validation/FloatValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/FloatValidator.java    (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/FloatValidator.java    (revision 0)
> @@ -0,0 +1,17 @@
> +package pivot.wtk.text.validation;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public class FloatValidator extends DecimalValidator
> +{
> +    public FloatValidator()
> +    {
> +    }
> +
> +    protected final Float textToObject(String text)
> +    {
> +        return parse(text).floatValue();
> +    }
> +}
> \ No newline at end of file
> Index: wtk/src/pivot/wtk/text/validation/FormattedValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/FormattedValidator.java
> (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/FormattedValidator.java
> (revision 0)
> @@ -0,0 +1,26 @@
> +package pivot.wtk.text.validation;
> +
> +import java.text.ParsePosition;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public abstract class FormattedValidator<TFormat extends
> java.text.Format> implements Validator
> +{
> +    protected final TFormat format;
> +
> +    protected FormattedValidator(TFormat format)
> +    {
> +        this.format = format;
> +    }
> +
> +    public boolean isValid(String text)
> +    {
> +        final ParsePosition pos = new ParsePosition(0);
> +        Object obj = format.parseObject(text, pos);
> +        // the text is only valid is we successfully parsed ALL of it.
> Don't want trailing bits of
> +        // not-valid text.
> +        return obj != null && pos.getErrorIndex() == -1 &&
> pos.getIndex() == text.length();
> +    }
> +}
> \ No newline at end of file
> Index: wtk/src/pivot/wtk/text/validation/IntRangeValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/IntRangeValidator.java    (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/IntRangeValidator.java    (revision 0)
> @@ -0,0 +1,25 @@
> +package pivot.wtk.text.validation;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public class IntRangeValidator extends IntValidator
> +{
> +    private final int minValue, maxValue;
> +
> +    public IntRangeValidator(int minValue, int maxValue)
> +    {
> +        this.minValue = minValue;
> +        this.maxValue = maxValue;
> +    }
> +
> +   �...@override
> +    public boolean isValid(String text)
> +    {
> +        if (!super.isValid(text))
> +            return false;
> +        final int i = textToObject(text);
> +        return i >= minValue && i <= maxValue;
> +    }
> +}
> \ No newline at end of file
> Index: wtk/src/pivot/wtk/text/validation/IntValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/IntValidator.java    (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/IntValidator.java    (revision 0)
> @@ -0,0 +1,18 @@
> +package pivot.wtk.text.validation;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public class IntValidator extends DecimalValidator
> +{
> +    public IntValidator()
> +    {
> +        format.setParseIntegerOnly(true);
> +    }
> +
> +    protected final Integer textToObject(String text)
> +    {
> +        return parse(text).intValue();
> +    }
> +}
> \ No newline at end of file
> Index: wtk/src/pivot/wtk/text/validation/RegexTextValidator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/RegexTextValidator.java
> (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/RegexTextValidator.java
> (revision 0)
> @@ -0,0 +1,25 @@
> +package pivot.wtk.text.validation;
> +
> +import java.util.regex.Pattern;
> +
> +/**
> + *
> + * @author Noel Grandin
> + */
> +public class RegexTextValidator implements Validator {
> +
> +    private final Pattern p;
> +
> +    public RegexTextValidator(Pattern p) {
> +        this.p = p;
> +    }
> +
> +    public RegexTextValidator(String regexPattern) {
> +        this.p = Pattern.compile(regexPattern);
> +    }
> +
> +    public boolean isValid(String text) {
> +        return p.matcher(text).matches();
> +    }
> +
> +}
> Index: wtk/src/pivot/wtk/text/validation/Validator.java
> ===================================================================
> --- wtk/src/pivot/wtk/text/validation/Validator.java    (revision 0)
> +++ wtk/src/pivot/wtk/text/validation/Validator.java    (revision 0)
> @@ -0,0 +1,11 @@
> +package pivot.wtk.text.validation;
> +
> +/**
> + * Validation interface for TextInput widget.
> + *
> + * @author Noel Grandin
> + */
> +public interface Validator {
> +    /** Is the text value valid? */
> +    boolean isValid(String text);
> +}
> \ No newline at end of file
>
>

Reply via email to