Skip to content

Commit

Permalink
#224 done (#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
vaadin-miki authored Sep 7, 2020
1 parent 9e1beea commit dbd540d
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 17 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ The author of the majority of the code is Miki, but this project would not be po
* Wolfgang Fischlein
* Jean-Christophe Gueriaud
* Holger Hähnel
* Matthias Hämmerle
* Gerald Koch
* Sebastian Kühnau
* Jean-François Lamy
Expand Down
14 changes: 1 addition & 13 deletions demo-v14/src/main/java/org/vaadin/miki/DemoComponentFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.component.textfield.TextFieldVariant;
import com.vaadin.flow.function.SerializableBiConsumer;
import com.vaadin.flow.function.SerializableConsumer;
import org.slf4j.LoggerFactory;
import org.vaadin.miki.events.state.StateChangeNotifier;
import org.vaadin.miki.events.text.TextSelectionNotifier;
Expand Down Expand Up @@ -59,7 +58,6 @@
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
Expand Down Expand Up @@ -104,8 +102,6 @@ private static Component generateDiv(Class<? extends Component> type, int row, i

private final Map<Class<?>, SerializableBiConsumer<Component, Consumer<Component[]>>> contentBuilders = new LinkedHashMap<>();

private final Map<Class<?>, SerializableConsumer<Object>> afterLocaleChange = new HashMap<>();

private DemoComponentFactory() {
this.components.put(SuperIntegerField.class, new SuperIntegerField(null, "Integer (6 digits):").withMaximumIntegerDigits(6));
this.components.put(SuperLongField.class, new SuperLongField(null, "Long (11 digits):").withMaximumIntegerDigits(11).withId("long"));
Expand Down Expand Up @@ -180,10 +176,6 @@ private DemoComponentFactory() {
this.contentBuilders.put(BlurNotifier.class, this::buildBlurNotifier);
this.contentBuilders.put(StateChangeNotifier.class, this::buildStateChangeNotifier);

this.afterLocaleChange.put(SuperIntegerField.class, o -> ((SuperIntegerField)o).setMaximumIntegerDigits(6));
this.afterLocaleChange.put(SuperLongField.class, o -> ((SuperLongField)o).setMaximumIntegerDigits(11));
this.afterLocaleChange.put(SuperDoubleField.class, o -> ((SuperDoubleField)o).withMaximumIntegerDigits(8).setMaximumFractionDigits(4));
this.afterLocaleChange.put(SuperBigDecimalField.class, o -> ((SuperBigDecimalField)o).withMaximumIntegerDigits(12).withMaximumFractionDigits(3).setMinimumFractionDigits(1));
}

private void buildAbstractSuperNumberField(Component component, Consumer<Component[]> callback) {
Expand Down Expand Up @@ -239,11 +231,7 @@ private void buildHasLocale(Component component, Consumer<Component[]> callback)
final ComboBox<Locale> locales = new ComboBox<>("Select locale:", new Locale("pl", "PL"), Locale.UK, Locale.FRANCE, Locale.GERMANY, Locale.CHINA);
locales.setItemLabelGenerator(locale -> locale.getDisplayCountry() + " / "+locale.getDisplayLanguage());
locales.setAllowCustomValue(false);
locales.addValueChangeListener(event -> {
((HasLocale) component).setLocale(event.getValue());
if(this.afterLocaleChange.containsKey(component.getClass()))
this.afterLocaleChange.get(component.getClass()).accept(component);
});
locales.addValueChangeListener(event -> ((HasLocale) component).setLocale(event.getValue()));
callback.accept(new Component[]{locales});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,25 @@ private DecimalFormat getFormat(Locale locale) {
/**
* Sets the locale of the component.
* The locale (or more precisely, its corresponding {@link NumberFormat}) is used to format how the number is displayed.
* Contrary to {@link #setDecimalFormat(DecimalFormat)} this method preserves the precision of the number.
* @param locale {@link Locale} to use. When {@code null}, {@link Locale#getDefault()} will be used.
* @see #setDecimalFormat(DecimalFormat)
*/
@Override
public void setLocale(Locale locale) {
// preserve information about precision
final int maxFraction = this.format.getMaximumFractionDigits();
final int minFraction = this.format.getMinimumFractionDigits();
final int maxInteger = this.format.getMaximumIntegerDigits();

final DecimalFormat newFormat = this.getFormat(locale);
newFormat.setMaximumFractionDigits(maxFraction);
newFormat.setMinimumFractionDigits(minFraction);
newFormat.setMaximumIntegerDigits(maxInteger);

// set locale and format
this.locale = locale;
this.setDecimalFormat(this.getFormat(locale));
this.setDecimalFormat(newFormat);
}

@Override
Expand All @@ -169,6 +181,8 @@ public Locale getLocale() {

/**
* Sets the format definition used to displaying the value.
* Note: subclasses may overwrite the data in the format to make sure it follows type-specific constraints.
* Also note: changes to the format object may result in unpredictable behaviour of this component.
* @param format {@link DecimalFormat} to use. When {@code null}, {@link NumberFormat#getNumberInstance()} will be used.
*/
public void setDecimalFormat(DecimalFormat format) {
Expand All @@ -178,7 +192,7 @@ public void setDecimalFormat(DecimalFormat format) {

/**
* Sets the minimum number of fraction digits displayed. Overwrites the value in the underlying {@link DecimalFormat}.
* Will be overwritten by calls to {@link #setLocale(Locale)} or {@link #setDecimalFormat(DecimalFormat)}.
* Will be overwritten by calls to {@link #setDecimalFormat(DecimalFormat)}. Calls to {@link #setLocale(Locale)} will preserve this value.
* @param digits Number of digits to use.
*/
protected void setMinimumFractionDigits(int digits) {
Expand All @@ -188,7 +202,7 @@ protected void setMinimumFractionDigits(int digits) {

/**
* Sets the maximum number of fraction digits displayed and allowed. Overwrites the value in the underlying {@link DecimalFormat}.
* Will be overwritten by calls to {@link #setLocale(Locale)} or {@link #setDecimalFormat(DecimalFormat)}.
* Will be overwritten by calls to {@link #setDecimalFormat(DecimalFormat)}. Calls to {@link #setLocale(Locale)} will preserve this value.
* Note: this has no effect on {@link #setValue(Object)}. If the value is set with more digits, it will stay there until input changes, even though the component shows less digits.
* @param digits Number of digits to use.
*/
Expand All @@ -199,7 +213,7 @@ protected void setMaximumFractionDigits(int digits) {

/**
* Sets the maximum number of integer digits (before decimal point) displayed and allowed. Overwrites the value in the underlying {@link DecimalFormat}.
* Will be overwritten by calls to {@link #setLocale(Locale)} or {@link #setDecimalFormat(DecimalFormat)}.
* Will be overwritten by calls to {@link #setDecimalFormat(DecimalFormat)}. Calls to {@link #setLocale(Locale)} will preserve this value.
* Note: this has no effect on {@link #setValue(Object)}. If the value is set with more digits, it will stay there until input changes, even though the component shows less digits.
* @param digits Number of digits to use.
*/
Expand Down Expand Up @@ -649,4 +663,32 @@ final void simulateFocus() {
final void simulateBlur() {
this.onFieldBlurred(new BlurNotifier.BlurEvent<>(this.field, false));
}

/**
* Returns the maximum number of fraction digits allowed by this component.
* For testing purposes mostly.
* @return The maximum number of fraction digits defined in this component's {@link DecimalFormat}.
*/
final int getMaximumFractionDigits() {
return this.format.getMaximumFractionDigits();
}

/**
* Returns the minimum number of fraction digits allowed by this component.
* For testing purposes mostly.
* @return The minimum number of fraction digits defined in this component's {@link DecimalFormat}.
*/
final int getMinimumFractionDigits() {
return this.format.getMinimumFractionDigits();
}

/**
* Returns the maximum number of integer digits allowed by this component.
* For testing purposes mostly.
* @return The maximum number of integer digits defined in this component's {@link DecimalFormat}.
*/
final int getMaximumIntegerDigits() {
return this.format.getMaximumIntegerDigits();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,10 @@ public SuperIntegerField(Integer defaultValue, String label, Locale locale) {
protected Integer parseRawValue(String rawValue, DecimalFormat format) throws ParseException {
return format.parse(rawValue).intValue();
}

@Override
public void setDecimalFormat(DecimalFormat format) {
format.setMaximumFractionDigits(0);
super.setDecimalFormat(format);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,10 @@ public SuperLongField(Long defaultValue, String label, Locale locale) {
protected Long parseRawValue(String rawValue, DecimalFormat format) throws ParseException {
return format.parse(rawValue).longValue();
}

@Override
public void setDecimalFormat(DecimalFormat format) {
format.setMaximumFractionDigits(0);
super.setDecimalFormat(format);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
Expand Down Expand Up @@ -258,4 +259,16 @@ public void testBlur() {
this.checkEventTriggered(this.getField()::addBlurListener, AbstractSuperNumberField::simulateBlur);
}

@Test
public void testChangesInLocaleDoNotAffectPrecision() {
this.field.setMaximumIntegerDigits(4);
final int maxFraction = this.field.getMaximumFractionDigits();
final int minFraction = this.field.getMinimumFractionDigits();
final int maxDigits = this.field.getMaximumIntegerDigits();
this.field.setLocale(Locale.GERMANY); // ticket #224 - any change in locale would trigger this
Assert.assertEquals("max fraction digits must not change when changing locale", maxFraction, this.field.getMaximumFractionDigits());
Assert.assertEquals("min fraction digits must not change when changing locale", minFraction, this.field.getMinimumFractionDigits());
Assert.assertEquals("max integer digits must not change when changing locale", maxDigits, this.field.getMaximumIntegerDigits());
}

}

0 comments on commit dbd540d

Please sign in to comment.