I made a minor additional change to paint the caret the same color as the text
(white) when the text is invalid.
On Monday, March 23, 2009, at 01:52PM, "Todd Volkert" <[email protected]>
wrote:
>Just noticed and changed one other thing:
>
>* Although we didn't have support for validations until this change,
>the original graphic design mock-ups did include such a state, and it
>had the background of the text input red, with the foreground white,
>so I changed TerraTextInputSkin to match the original mock-ups. We
>generally try not to augment the color palette's base colors, as the
>original graphic designs (they came from within VMware) managed with
>just 8 base colors.
>
>-T
>
>On Mon, Mar 23, 2009 at 1:17 PM, Todd Volkert <[email protected]> wrote:
>> 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
>>>
>>>
>>
>
>