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 >> >> >
