Updated Branches: refs/heads/master e9d8e33ff -> 9de66fbf5
WICKET-4884 keep locale untouched but do custom conversion instead Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/9de66fbf Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/9de66fbf Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/9de66fbf Branch: refs/heads/master Commit: 9de66fbf5701de16d28cf6ea78a1c2a62065a987 Parents: e9d8e33 Author: svenmeier <[email protected]> Authored: Tue Nov 27 08:38:27 2012 +0100 Committer: svenmeier <[email protected]> Committed: Tue Nov 27 08:38:27 2012 +0100 ---------------------------------------------------------------------- .../wicket/markup/html/form/NumberTextField.java | 69 ++++---- .../markup/html/form/NumberTextFieldTest.java | 144 +++++++++++++++ 2 files changed, 177 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/9de66fbf/wicket-core/src/main/java/org/apache/wicket/markup/html/form/NumberTextField.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/NumberTextField.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/NumberTextField.java index ae3706b..0e88c7b 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/NumberTextField.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/NumberTextField.java @@ -16,14 +16,14 @@ */ package org.apache.wicket.markup.html.form; -import java.text.NumberFormat; import java.util.Locale; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.model.IModel; +import org.apache.wicket.util.convert.ConversionException; import org.apache.wicket.util.convert.IConverter; -import org.apache.wicket.util.convert.converter.AbstractDecimalConverter; import org.apache.wicket.util.lang.Numbers; +import org.apache.wicket.util.lang.Objects; import org.apache.wicket.util.value.IValueMap; import org.apache.wicket.validation.validator.RangeValidator; @@ -33,8 +33,8 @@ import org.apache.wicket.validation.validator.RangeValidator; * <p> * Automatically validates the input against the configured {@link #setMinimum(N) min} and * {@link #setMaximum(N) max} attributes. If any of them is <code>null</code> then respective - * MIN_VALUE or MAX_VALUE for the number type is used. If the number type has no minimum and/or maximum - * value then {@link Double#MIN_VALUE} and {@link Double#MAX_VALUE} are used respectfully. + * MIN_VALUE or MAX_VALUE for the number type is used. If the number type has no minimum and/or + * maximum value then {@link Double#MIN_VALUE} and {@link Double#MAX_VALUE} are used respectfully. * * @param <N> * the type of the number @@ -43,13 +43,6 @@ public class NumberTextField<N extends Number & Comparable<N>> extends TextField { private static final long serialVersionUID = 1L; - /** - * A special locale which is used to render decimal number formats that are HTML5 compliant. - * - * See <a href="http://dev.w3.org/html5/markup/datatypes.html#common.data.float">HTML5 number format</a> - */ - private static final Locale HTML5_LOCALE = new Locale("en", "", "wicket-html5"); - private RangeValidator<N> validator; private N minimum; @@ -149,7 +142,7 @@ public class NumberTextField<N extends Number & Comparable<N>> extends TextField else { Class<N> numberType = getNumberType(); - result = (N) Numbers.getMinValue(numberType); + result = (N)Numbers.getMinValue(numberType); } return result; } @@ -164,7 +157,7 @@ public class NumberTextField<N extends Number & Comparable<N>> extends TextField else { Class<N> numberType = getNumberType(); - result = (N) Numbers.getMaxValue(numberType); + result = (N)Numbers.getMaxValue(numberType); } return result; } @@ -174,7 +167,7 @@ public class NumberTextField<N extends Number & Comparable<N>> extends TextField Class<N> numberType = getType(); if (numberType == null && getModelObject() != null) { - numberType = (Class<N>) getModelObject().getClass(); + numberType = (Class<N>)getModelObject().getClass(); } return numberType; } @@ -188,8 +181,7 @@ public class NumberTextField<N extends Number & Comparable<N>> extends TextField if (minimum != null) { - IConverter<N> converter = getConverter(getNumberType()); - attributes.put("min", converter.convertToString(minimum, HTML5_LOCALE)); + attributes.put("min", Objects.stringValue(minimum)); } else { @@ -198,8 +190,7 @@ public class NumberTextField<N extends Number & Comparable<N>> extends TextField if (maximum != null) { - IConverter<N> converter = getConverter(getNumberType()); - attributes.put("max", converter.convertToString(maximum, HTML5_LOCALE)); + attributes.put("max", Objects.stringValue(maximum)); } else { @@ -214,34 +205,40 @@ public class NumberTextField<N extends Number & Comparable<N>> extends TextField } /** - * {@inheritDoc} + * The formatting for {@link Locale#ENGLISH} might not be compatible with HTML (e.g. group + * digits), thus use {@link Objects#stringValue(Object)} instead. * - * WICKET-3591 Browsers support only formatting in English + * @return value */ @Override - public Locale getLocale() + protected String getModelValue() { - return HTML5_LOCALE; + N value = getModelObject(); + if (value == null) + { + return ""; + } + else + { + return Objects.stringValue(value); + } } /** - * {@inheritDoc} - * - * WICKET-4501 NumberTextField<BigDecimal> renders its value in unsupported number format + * Always use {@link Locale#ENGLISH} to parse the input. */ @Override - public <C> IConverter<C> getConverter(Class<C> type) + protected void convertInput() { - IConverter<C> converter = super.getConverter(type); - if (converter instanceof AbstractDecimalConverter<?>) + IConverter<N> converter = getConverter(getNumberType()); + + try + { + setConvertedInput(converter.convertToObject(getInput(), Locale.ENGLISH)); + } + catch (ConversionException e) { - AbstractDecimalConverter<?> adc = (AbstractDecimalConverter<?>)converter; - NumberFormat numberFormat = adc.getNumberFormat(HTML5_LOCALE); - // do not use grouping for HTML5 number/range fields because - // it is not supported by browsers - numberFormat.setGroupingUsed(false); - adc.setNumberFormat(HTML5_LOCALE, numberFormat); + error(newValidationError(e)); } - return converter; } -} +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/wicket/blob/9de66fbf/wicket-core/src/test/java/org/apache/wicket/markup/html/form/NumberTextFieldTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/NumberTextFieldTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/NumberTextFieldTest.java new file mode 100644 index 0000000..44c0fa8 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/NumberTextFieldTest.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.wicket.markup.html.form; + +import java.math.BigDecimal; +import java.util.Locale; + +import org.apache.wicket.MarkupContainer; +import org.apache.wicket.WicketTestCase; +import org.apache.wicket.markup.IMarkupResourceStreamProvider; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.model.Model; +import org.apache.wicket.util.resource.IResourceStream; +import org.apache.wicket.util.resource.StringResourceStream; +import org.apache.wicket.util.tester.FormTester; +import org.junit.Test; + +/** + * Test for {@link NumberTextField}. + * + * @author svenmeier + */ +public class NumberTextFieldTest extends WicketTestCase +{ + + /** + * WICKET-4884, WICKET-3591 + */ + @Test + public void convertBigDecimal() + { + TestPage<BigDecimal> testPage = new TestPage<BigDecimal>(); + testPage.textField.setType(BigDecimal.class); + testPage.textField.setMinimum(new BigDecimal("0.00")); + testPage.textField.setMaximum(new BigDecimal("100.00")); + testPage.textField.setModelObject(new BigDecimal("0.00")); + tester.startPage(testPage); + + String response = tester.getLastResponseAsString(); + assertTrue(response.contains("<input wicket:id=\"number\" type=\"number\" value=\"0.00\" name=\"number\" min=\"0.00\" max=\"100.00\"/>")); + + FormTester formTester = tester.newFormTester(testPage.form.getId()); + formTester.setValue(testPage.textField.getId(), "50.50"); + formTester.submit(); + assertEquals(new BigDecimal("50.50"), testPage.textField.getDefaultModelObject()); + } + + /** + * WICKET-4884, WICKET-3591 + */ + @Test + public void convertDouble() + { + TestPage<Double> testPage = new TestPage<Double>(); + testPage.textField.setType(Double.class); + testPage.textField.setMinimum(new Double("0.0")); + testPage.textField.setMaximum(new Double("2000.0")); + testPage.textField.setModelObject(new Double("1000.0")); + tester.startPage(testPage); + + String response = tester.getLastResponseAsString(); + assertTrue(response.contains("<input wicket:id=\"number\" type=\"number\" value=\"1000.0\" name=\"number\" min=\"0.0\" max=\"2000.0\"/>")); + + FormTester formTester = tester.newFormTester(testPage.form.getId()); + formTester.setValue(testPage.textField.getId(), "2,000.00"); + formTester.submit(); + assertEquals(new Double("2000.00"), testPage.textField.getDefaultModelObject()); + } + + /** + * WICKET-4884, WICKET-3591 + */ + @Test + public void convertLong() + { + TestPage<Long> testPage = new TestPage<Long>(); + testPage.textField.setType(Long.class); + testPage.textField.setMinimum(new Long("0")); + testPage.textField.setMaximum(new Long("100")); + testPage.textField.setModelObject(new Long("0")); + tester.startPage(testPage); + + String response = tester.getLastResponseAsString(); + assertTrue(response.contains("<input wicket:id=\"number\" type=\"number\" value=\"0\" name=\"number\" min=\"0\" max=\"100\"/>")); + + FormTester formTester = tester.newFormTester(testPage.form.getId()); + formTester.setValue(testPage.textField.getId(), "50"); + formTester.submit(); + assertEquals(new Long("50"), testPage.textField.getDefaultModelObject()); + } + + /** + * @param <N> + * type parameter + */ + public static class TestPage<N extends Number & Comparable<N>> extends WebPage + implements + IMarkupResourceStreamProvider + { + private static final long serialVersionUID = 1L; + + Form<Void> form; + NumberTextField<N> textField; + + /** */ + public TestPage() + { + add(form = new Form<Void>("form") + { + private static final long serialVersionUID = 1L; + + @Override + public Locale getLocale() + { + return Locale.GERMAN; + } + }); + form.add(textField = new NumberTextField<N>("number", Model.of((N)null))); + } + + @Override + public IResourceStream getMarkupResourceStream(MarkupContainer container, + Class<?> containerClass) + { + return new StringResourceStream( + "<html><body>" + + "<form wicket:id=\"form\"><input wicket:id=\"number\" type=\"number\" /></form></body></html>"); + } + } +}
