diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/DatePicker.java b/modules/javafx.controls/src/main/java/javafx/scene/control/DatePicker.java index 50deb75acfc..084888ce84f 100644 --- a/modules/javafx.controls/src/main/java/javafx/scene/control/DatePicker.java +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/DatePicker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,7 +106,15 @@ public class DatePicker extends ComboBoxBase { */ public DatePicker() { this(null); + } + /** + * Creates a DatePicker instance and sets the + * {@link #valueProperty() value} to the given date. + * + * @param localDate to be set as the currently selected date in the DatePicker. Can be null. + */ + public DatePicker(LocalDate localDate) { valueProperty().addListener(observable -> { LocalDate date = getValue(); Chronology chrono = getChronology(); @@ -115,7 +123,7 @@ public DatePicker() { lastValidDate = date; } else { System.err.println("Restoring value to " + - ((lastValidDate == null) ? "null" : getConverter().toString(lastValidDate))); + ((lastValidDate == null) ? "null" : getConverter().toString(lastValidDate))); setValue(lastValidDate); } }); @@ -132,6 +140,17 @@ public DatePicker() { setChronology(lastValidChronology); } }); + + setValue(localDate); + getStyleClass().add(DEFAULT_STYLE_CLASS); + setAccessibleRole(AccessibleRole.DATE_PICKER); + setEditable(true); + + focusedProperty().addListener(o -> { + if (!isFocused()) { + commitValue(); + } + }); } private boolean validateDate(Chronology chrono, LocalDate date) { @@ -146,25 +165,6 @@ private boolean validateDate(Chronology chrono, LocalDate date) { } } - /** - * Creates a DatePicker instance and sets the - * {@link #valueProperty() value} to the given date. - * - * @param localDate to be set as the currently selected date in the DatePicker. Can be null. - */ - public DatePicker(LocalDate localDate) { - setValue(localDate); - getStyleClass().add(DEFAULT_STYLE_CLASS); - setAccessibleRole(AccessibleRole.DATE_PICKER); - setEditable(true); - - focusedProperty().addListener(o -> { - if (!isFocused()) { - commitValue(); - } - }); - } - /* ************************************************************************* * * diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/DatePickerTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/DatePickerTest.java index 4901b1728bd..42a70ae86d3 100644 --- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/DatePickerTest.java +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/DatePickerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,12 @@ package test.javafx.scene.control; +import java.time.DateTimeException; import java.time.LocalDate; import java.time.chrono.*; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.ValueRange; import java.util.*; import javafx.scene.control.Button; @@ -620,6 +624,30 @@ public Node getDisplayNode() { sl.dispose(); } + @Test + public void testInvalidChronologyIsRestored() { + datePicker = new DatePicker(LocalDate.of(1998, 1, 23)); + datePicker.setChronology(IsoChronology.INSTANCE); + + assertEquals(IsoChronology.INSTANCE, datePicker.getChronology()); + + // This should restore the old set chronology (Iso) as the chronology is invalid. + datePicker.setChronology(new InvalidChronology()); + assertEquals(IsoChronology.INSTANCE, datePicker.getChronology()); + } + + @Test + public void testInvalidValueIsRestored() { + datePicker = new DatePicker(null); + assertNull(datePicker.getValue()); + + datePicker.setChronology(new InvalidChronology()); + // This should restore the old set value (null) as the chronology is invalid. + datePicker.setValue(LocalDate.of(1998, 1, 23)); + + assertNull(datePicker.getValue()); + } + @Test public void testCommitValue() { datePicker.setEditable(true); @@ -709,4 +737,51 @@ public void testFocusLost() { stageLoader.dispose(); } + private class InvalidChronology extends AbstractChronology { + @Override + public String getId() { + return null; + } + @Override + public String getCalendarType() { + return null; + } + @Override + public ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth) { + return null; + } + @Override + public ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear) { + return null; + } + @Override + public ChronoLocalDate dateEpochDay(long epochDay) { + return null; + } + @Override + public ChronoLocalDate date(TemporalAccessor temporal) { + throw new DateTimeException("Invalid"); + } + @Override + public boolean isLeapYear(long prolepticYear) { + return false; + } + @Override + public int prolepticYear(Era era, int yearOfEra) { + return 0; + } + @Override + public Era eraOf(int eraValue) { + return null; + } + @Override + public List eras() { + return null; + } + @Override + public ValueRange range(ChronoField field) { + return null; + } + } + }