This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 3489-temporal.editing.w.tz
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/3489-temporal.editing.w.tz by
this push:
new cc84f51394 CAUSEWAY-3489: introduces TemporalDecomposition
cc84f51394 is described below
commit cc84f51394ca1dd72fc9d413cfafbb853995286d
Author: Andi Huber <[email protected]>
AuthorDate: Wed Mar 13 15:41:55 2024 +0100
CAUSEWAY-3489: introduces TemporalDecomposition
- to handle temporal values with zone or offset information based on
existing widgets, that do not support zone or offset information
---
.../value/semantics/TemporalValueSemantics.java | 18 +--
.../scalars/ScalarPanelFormFieldAbstract.html | 4 +-
.../scalars/ScalarPanelTextFieldAbstract.java | 6 +
.../ScalarPanelTextFieldWithTemporalPicker.java | 87 +++++++-----
.../scalars/datepicker/TemporalDecomposition.java | 157 +++++++++++++++++++++
.../datepicker/TextFieldWithDateTimePicker.java | 18 +--
.../apache/causeway/viewer/wicket/ui/util/Wkt.java | 14 +-
.../ComponentFactoryRegistrarDefault.java | 7 +-
8 files changed, 249 insertions(+), 62 deletions(-)
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/value/semantics/TemporalValueSemantics.java
b/api/applib/src/main/java/org/apache/causeway/applib/value/semantics/TemporalValueSemantics.java
index 58cd36e0ad..7709ad1883 100644
---
a/api/applib/src/main/java/org/apache/causeway/applib/value/semantics/TemporalValueSemantics.java
+++
b/api/applib/src/main/java/org/apache/causeway/applib/value/semantics/TemporalValueSemantics.java
@@ -360,9 +360,9 @@ extends
*/
default List<ZoneId> getAvailableZoneIds() {
return ZoneId.getAvailableZoneIds().stream()
- .sorted()
- .map(ZoneId::of)
- .collect(Collectors.toList());
+ .sorted()
+ .map(ZoneId::of)
+ .collect(Collectors.toList());
}
/**
@@ -370,12 +370,12 @@ extends
*/
default List<ZoneOffset> getAvailableOffsets() {
val now = LocalDateTime.now();
- return ZoneId.getAvailableZoneIds().stream()
- .map(ZoneId::of)
- .map(ZoneId::getRules)
-
.flatMap(zoneIdRules->zoneIdRules.getValidOffsets(now).stream())
- .sorted()
- .collect(Collectors.toList());
+ return getAvailableZoneIds().stream()
+ .map(ZoneId::getRules)
+ .flatMap(zoneIdRules->zoneIdRules.getValidOffsets(now).stream())
+ .sorted()
+ .distinct()
+ .collect(Collectors.toList());
}
}
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelFormFieldAbstract.html
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelFormFieldAbstract.html
index 0c76f8cda7..32317d95ae 100644
---
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelFormFieldAbstract.html
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelFormFieldAbstract.html
@@ -157,7 +157,7 @@
<input wicket:id="scalarValue"
type="text" name="scalarValue"
class="form-control form-control-sm scalarValue
fragment-input-date"/>
- <div class="input-group">
+ <div class="input-group input-group-sm">
<span class="input-group-text">Offset:</span>
<select class="form-control"
wicket:id="timeoffset" name="timeoffset" data-noreset="true" style="width:
auto;" />
</div>
@@ -167,7 +167,7 @@
<input wicket:id="scalarValue"
type="text" name="scalarValue"
class="form-control form-control-sm scalarValue
fragment-input-date"/>
- <div class="input-group">
+ <div class="input-group input-group-sm">
<span class="input-group-text">Zone:</span>
<select class="form-control"
wicket:id="timezone" name="timezone" data-noreset="true" style="width: auto;" />
</div>
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
index e21130573d..2824b22b52 100644
---
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
@@ -26,6 +26,7 @@ import org.apache.wicket.model.IModel;
import org.apache.wicket.util.convert.IConverter;
import org.apache.causeway.commons.internal.assertions._Assert;
+import org.apache.causeway.commons.internal.exceptions._Exceptions;
import org.apache.causeway.viewer.commons.model.components.UiString;
import org.apache.causeway.viewer.wicket.model.models.ScalarModel;
import
org.apache.causeway.viewer.wicket.ui.components.scalars.ScalarFragmentFactory.InputFragment;
@@ -66,6 +67,11 @@ extends ScalarPanelFormFieldAbstract<T> {
*/
protected abstract Optional<IConverter<T>> converter();
+ protected final IConverter<T> converterElseFail() {
+ return converter().orElseThrow(()->
+ _Exceptions.illegalState("framework bug: %s requires a converter",
this.getClass().getSimpleName()));
+ }
+
// --
/**
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldWithTemporalPicker.java
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldWithTemporalPicker.java
index 4ec5611bc3..bd066180a6 100644
---
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldWithTemporalPicker.java
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldWithTemporalPicker.java
@@ -20,6 +20,7 @@ package
org.apache.causeway.viewer.wicket.ui.components.scalars;
import java.time.ZoneId;
import java.time.ZoneOffset;
+import java.time.temporal.Temporal;
import java.util.Optional;
import org.apache.wicket.MarkupContainer;
@@ -30,27 +31,31 @@ import org.apache.wicket.model.PropertyModel;
import org.apache.causeway.applib.value.semantics.TemporalValueSemantics;
import
org.apache.causeway.applib.value.semantics.TemporalValueSemantics.OffsetCharacteristic;
+import
org.apache.causeway.applib.value.semantics.TemporalValueSemantics.TemporalCharacteristic;
+import org.apache.causeway.commons.internal.base._Casts;
import org.apache.causeway.commons.internal.exceptions._Exceptions;
import org.apache.causeway.core.metamodel.util.Facets;
import org.apache.causeway.viewer.wicket.model.models.ScalarModel;
+import
org.apache.causeway.viewer.wicket.model.value.ConverterBasedOnValueSemantics;
import
org.apache.causeway.viewer.wicket.ui.components.scalars.ScalarFragmentFactory.InputFragment;
+import
org.apache.causeway.viewer.wicket.ui.components.scalars.datepicker.TemporalDecomposition;
import
org.apache.causeway.viewer.wicket.ui.components.scalars.datepicker.TextFieldWithDateTimePicker;
import
org.apache.causeway.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
import org.apache.causeway.viewer.wicket.ui.util.Wkt;
import org.apache.causeway.viewer.wicket.ui.util.WktComponents;
-import lombok.Getter;
-import lombok.Setter;
import lombok.val;
/**
* Panel for rendering scalars representing dates, along with a date picker.
*/
-public class ScalarPanelTextFieldWithTemporalPicker<T>
+public class ScalarPanelTextFieldWithTemporalPicker<T extends Temporal>
extends ScalarPanelTextFieldWithValueSemantics<T> {
private static final long serialVersionUID = 1L;
+ private TemporalDecomposition<T> temporalDecomposition;
+
public ScalarPanelTextFieldWithTemporalPicker(
final String id, final ScalarModel scalarModel, final Class<T>
type) {
super(id, scalarModel, type);
@@ -63,38 +68,23 @@ extends ScalarPanelTextFieldWithValueSemantics<T> {
@Override
protected final TextField<T> createTextField(final String id) {
val scalarModel = scalarModel();
- val converter = converter().orElseThrow(()->
- _Exceptions.illegalArgument("framework bug:
ScalarPanelTextFieldWithTemporalPicker requires a converter"));
- val textField = new TextFieldWithDateTimePicker<T>(
- id, scalarModel, type, converter);
+ this.temporalDecomposition = TemporalDecomposition.create(type,
+ scalarModel,
+ temporalValueSemantics(),
+ (ConverterBasedOnValueSemantics<T>)converterElseFail());
- /* [CAUSEWAY-3201]
- * Adding OnChangeAjaxBehavior registers a JavaScript event listener
on change events.
- * Since OnChangeAjaxBehavior extends
AjaxFormComponentUpdatingBehavior the Ajax request
- * also updates the Wicket model for this form component on the server
side.
- */
- textField.add(new OnChangeAjaxBehavior() {
- private static final long serialVersionUID = 1L;
- @Override
- protected void onUpdate(final AjaxRequestTarget target) {
- // triggers update of dependent args (action prompt)
- ScalarPanelTextFieldWithTemporalPicker.this
- .getScalarModelChangeDispatcher().notifyUpdate(target);
- }
- });
+ val textField = new TextFieldWithDateTimePicker<T>(
+ id, scalarModel.unwrapped(type), type,
scalarModel.isRequired(),
+ temporalDecomposition,
+ temporalDecomposition.getEditingPattern());
- return textField;
+ return installUpdateNotifier(textField);
}
- @Getter @Setter
- private ZoneId zoneId;
-
- @Getter @Setter
- private ZoneOffset zoneOffset;
-
@Override
protected void onFormGroupCreated(final FormGroup formGroup) {
+ if(!scalarModel().isEditingMode()) return;
// find the scalarValue container, which we want to add the additional
fields to
var container = WktComponents.findById(formGroup,
"container-scalarValue", MarkupContainer.class)
@@ -104,14 +94,14 @@ extends ScalarPanelTextFieldWithValueSemantics<T> {
// create additional form fields that in combination with the main
field make up the value
switch (offsetCharacteristic()) {
case OFFSET:
- Wkt.dropDownChoiceAdd(container, "timeoffset",
- new
PropertyModel<ZoneOffset>(ScalarPanelTextFieldWithTemporalPicker.this,
"zoneOffset"),
+ Wkt.dropDownChoiceWithAjaxUpdateAdd(container, "timeoffset",
+ new PropertyModel<ZoneOffset>(temporalDecomposition,
"zoneOffset"),
temporalValueSemantics().getAvailableOffsets())
.setRequired(true);
break;
case ZONED:
- Wkt.dropDownChoiceAdd(container, "timezone",
- new
PropertyModel<ZoneId>(ScalarPanelTextFieldWithTemporalPicker.this, "zoneId"),
+ Wkt.dropDownChoiceWithAjaxUpdateAdd(container, "timezone",
+ new PropertyModel<ZoneId>(temporalDecomposition, "zoneId"),
temporalValueSemantics().getAvailableZoneIds())
.setRequired(true);
break;
@@ -144,16 +134,37 @@ extends ScalarPanelTextFieldWithValueSemantics<T> {
// -- HELPER
- private TemporalValueSemantics<?> temporalValueSemantics() {
- return Facets.valueTemporalSemantics(scalarModel().getElementType())
+ private TemporalValueSemantics<T> temporalValueSemantics() {
+ return
_Casts.uncheckedCast(Facets.valueTemporalSemantics(scalarModel().getElementType())
.orElseThrow(()->_Exceptions.illegalState("no (temporal) value
semantics found for %s",
- scalarModel().getElementType()));
+ scalarModel().getElementType())));
+ }
+
+ //TODO[CAUSEWAY-3489] unused
+ private TemporalCharacteristic temporalCharacteristic() {
+ return temporalValueSemantics().getTemporalCharacteristic();
}
private OffsetCharacteristic offsetCharacteristic() {
- return Facets.valueTemporalSemantics(scalarModel().getElementType())
- .map(TemporalValueSemantics::getOffsetCharacteristic)
- .orElse(OffsetCharacteristic.LOCAL);
+ return temporalValueSemantics().getOffsetCharacteristic();
+ }
+
+ private <X> TextField<X> installUpdateNotifier(final TextField<X>
textField) {
+ /* [CAUSEWAY-3201]
+ * Adding OnChangeAjaxBehavior registers a JavaScript event listener
on change events.
+ * Since OnChangeAjaxBehavior extends
AjaxFormComponentUpdatingBehavior the Ajax request
+ * also updates the Wicket model for this form component on the server
side.
+ */
+ textField.add(new OnChangeAjaxBehavior() {
+ private static final long serialVersionUID = 1L;
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ // triggers update of following args (action prompt)
+ ScalarPanelTextFieldWithTemporalPicker.this
+ .getScalarModelChangeDispatcher().notifyUpdate(target);
+ }
+ });
+ return textField;
}
}
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/datepicker/TemporalDecomposition.java
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/datepicker/TemporalDecomposition.java
new file mode 100644
index 0000000000..6e4cb8bd7e
--- /dev/null
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/datepicker/TemporalDecomposition.java
@@ -0,0 +1,157 @@
+/*
+ * 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.causeway.viewer.wicket.ui.components.scalars.datepicker;
+
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.temporal.Temporal;
+import java.util.Locale;
+
+import org.apache.wicket.util.convert.ConversionException;
+import org.apache.wicket.util.convert.IConverter;
+
+import org.apache.causeway.applib.value.semantics.TemporalValueSemantics;
+import
org.apache.causeway.applib.value.semantics.TemporalValueSemantics.OffsetCharacteristic;
+import
org.apache.causeway.applib.value.semantics.TemporalValueSemantics.TemporalCharacteristic;
+import org.apache.causeway.commons.internal.base._Temporals;
+import org.apache.causeway.core.metamodel.commons.ViewOrEditMode;
+import org.apache.causeway.core.metamodel.interactions.managed.ManagedValue;
+import org.apache.causeway.core.metamodel.object.MmUnwrapUtils;
+import org.apache.causeway.viewer.wicket.model.models.ScalarModel;
+import
org.apache.causeway.viewer.wicket.model.value.ConverterBasedOnValueSemantics;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Introduced to handle temporal values with zone or offset information
+ * based on existing widgets, that do not support zone or offset information.
+ */
+@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+public class TemporalDecomposition<T extends Temporal> implements
IConverter<T> {
+ private static final long serialVersionUID = 1L;
+
+ public static <T extends Temporal> TemporalDecomposition<T> create(final
Class<T> type,
+ final ScalarModel scalarModel,
+ final TemporalValueSemantics<T> temporalValueSemantics,
+ final ConverterBasedOnValueSemantics<T> fullConverter) {
+
+ var baseEditingPattern = fullConverter.getEditingPattern();
+ //TODO[CAUSEWAY-3489] switch on offsetCharacteristic and
temporalCharacteristic to do this properly
+ var editingPattern = scalarModel.isEditingMode()
+ ? "yyyy-MM-dd HH:mm:ss" // strip 'XXX' or 'VV';
+ : baseEditingPattern;
+
+ var tempDecomp = new TemporalDecomposition<>(type,
temporalValueSemantics, fullConverter,
+ scalarModel.getViewOrEditMode(),
+ editingPattern);
+ tempDecomp.initFrom(scalarModel.proposedValue());
+ return tempDecomp;
+ }
+
+ private final @NonNull Class<T> type;
+ private final @NonNull TemporalValueSemantics<T> temporalValueSemantics;
+ private final @NonNull ConverterBasedOnValueSemantics<T> fullConverter;
+ private final @NonNull ViewOrEditMode viewOrEditMode;
+
+ @Getter
+ private final String editingPattern;
+
+ private void initFrom(final ManagedValue proposedValue) {
+ var temporalValue =
MmUnwrapUtils.single(proposedValue.getValue().getValue());
+ if(temporalValue instanceof ZonedDateTime) {
+ var zonedDateTime = (ZonedDateTime) temporalValue;
+ this.zoneId = zonedDateTime.getZone();
+ } else if(temporalValue instanceof OffsetDateTime) {
+ var offsetDateTime = (OffsetDateTime) temporalValue;
+ this.zoneOffset = offsetDateTime.getOffset();
+ } else if(temporalValue instanceof OffsetTime) {
+ var offsetTime = (OffsetTime) temporalValue;
+ this.zoneOffset = offsetTime.getOffset();
+ }
+ }
+
+ @Override
+ public T convertToObject(final String noZoneValue, final Locale locale)
throws ConversionException {
+ var fullTemporalString = noZoneValue + getZoneOrOffsetSuffix();
+ return fullConverter.convertToObject(fullTemporalString, locale);
+ }
+ @Override
+ public String convertToString(final T value, final Locale locale) {
+ return fullConverter.convertToString(value, locale);
+ }
+
+ // -- SPECIALIZATION
+
+ private TemporalCharacteristic temporalCharacteristic() {
+ return temporalValueSemantics.getTemporalCharacteristic();
+ }
+
+ private OffsetCharacteristic offsetCharacteristic() {
+ return temporalValueSemantics.getOffsetCharacteristic();
+ }
+
+ private String getZoneOrOffsetSuffix() {
+ switch (offsetCharacteristic()) {
+ case OFFSET:
+ return " " + _Temporals.formatZoneId(zoneOffset==null
+ ? ZoneOffset.UTC
+ : zoneOffset,
+ _Temporals.ISO_OFFSET_ONLY_FORMAT);
+ case ZONED:
+ return " " + _Temporals.formatZoneId(zoneId==null
+ ? ZoneOffset.UTC
+ : zoneId);
+ default:
+ return "";
+ }
+ }
+
+ // -- PROPERTIES
+
+ private ZoneId zoneId;
+ public ZoneId getZoneId() {
+ //TODO[CAUSEWAY-3489] remove debug line
+ System.err.printf("getZoneId %s%n", zoneId);
+ return zoneId;
+ }
+ public void setZoneId(final ZoneId zoneId) {
+ this.zoneId = zoneId;
+ //TODO[CAUSEWAY-3489] remove debug line
+ System.err.printf("setZoneId %s%n", zoneId);
+ }
+
+ private ZoneOffset zoneOffset;
+ public ZoneOffset getZoneOffset() {
+ //TODO[CAUSEWAY-3489] remove debug line
+ System.err.printf("getZoneOffset %s%n", zoneOffset);
+ return zoneOffset;
+ }
+ public void setZoneOffset(final ZoneOffset zoneOffset) {
+ this.zoneOffset = zoneOffset;
+ //TODO[CAUSEWAY-3489] remove debug line
+ System.err.printf("setZoneOffset %s%n", zoneOffset);
+ }
+
+}
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/datepicker/TextFieldWithDateTimePicker.java
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/datepicker/TextFieldWithDateTimePicker.java
index befe2820df..d8219b430b 100644
---
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/datepicker/TextFieldWithDateTimePicker.java
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/datepicker/TextFieldWithDateTimePicker.java
@@ -27,12 +27,11 @@ import java.util.Optional;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.model.IModel;
import org.apache.wicket.util.convert.IConverter;
import org.apache.causeway.applib.locale.UserLocale;
import org.apache.causeway.core.metamodel.context.MetaModelContext;
-import org.apache.causeway.viewer.wicket.model.models.ScalarModel;
-import
org.apache.causeway.viewer.wicket.model.value.ConverterBasedOnValueSemantics;
import
org.apache.causeway.viewer.wicket.ui.components.text.TextFieldWithConverter;
import lombok.NonNull;
@@ -63,16 +62,17 @@ extends TextFieldWithConverter<T> {
public TextFieldWithDateTimePicker(
final @NonNull String id,
- final @NonNull ScalarModel scalarModel,
+ final @NonNull IModel<T> model,
final @NonNull Class<T> type,
- final @NonNull IConverter<T> converter) {
- super(id, scalarModel.unwrapped(type), type, Optional.of(converter));
+ final boolean isRequired,
+ final @NonNull IConverter<T> converter,
+ final @NonNull String editingPattern) {
+ super(id, model, type, Optional.of(converter));
setOutputMarkupId(true);
this.config = createDatePickerConfig(
- scalarModel.getMetaModelContext(),
- ((ConverterBasedOnValueSemantics<T>)
converter).getEditingPattern(),
- !scalarModel.isRequired());
+ editingPattern,
+ !isRequired);
/* debug
new IConverter<T>() {
@@ -132,10 +132,10 @@ extends TextFieldWithConverter<T> {
// -- HELPER
private DateTimeConfig createDatePickerConfig(
- final MetaModelContext mmc,
final String temporalPattern,
final boolean isInputNullable) {
val config = new DateTimeConfig();
+ val mmc = MetaModelContext.instanceElseFail();
config.useLocale(mmc.currentUserLocale()
.map(UserLocale::getLanguageLocale)
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/Wkt.java
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/Wkt.java
index ed7fb5de54..2bbf5569ee 100644
---
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/Wkt.java
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/Wkt.java
@@ -56,6 +56,7 @@ import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.FormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.upload.FileUpload;
@@ -619,12 +620,21 @@ public class Wkt {
return new DropDownChoice<T>(id, model, choices);
}
- public <T extends Serializable> DropDownChoice<T> dropDownChoiceAdd(
+ public <T extends Serializable> DropDownChoice<T>
dropDownChoiceWithAjaxUpdate(final String id,
+ final IModel<T> model,
+ final List<? extends T> choices) {
+ var component = dropDownChoice(id, model, choices);
+ component.setOutputMarkupId(true);
+ component.add(new FormComponentUpdatingBehavior());
+ return component;
+ }
+
+ public <T extends Serializable> DropDownChoice<T>
dropDownChoiceWithAjaxUpdateAdd(
final MarkupContainer container,
final String id,
final IModel<T> model,
final List<? extends T> choices) {
- return add(container, dropDownChoice(id, model, choices));
+ return add(container, dropDownChoiceWithAjaxUpdate(id, model,
choices));
}
// -- FILE DOWNLOAD
diff --git
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
index ade636d5ae..b0f1828f2c 100644
---
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
+++
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
@@ -19,6 +19,7 @@
package org.apache.causeway.viewer.wicket.viewer.registries.components;
import java.io.Serializable;
+import java.time.temporal.Temporal;
import java.util.List;
import java.util.stream.Collectors;
@@ -37,6 +38,7 @@ import
org.apache.causeway.applib.annotation.PriorityPrecedence;
import org.apache.causeway.applib.value.semantics.ValueSemanticsProvider;
import org.apache.causeway.applib.value.semantics.ValueSemanticsResolver;
import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.commons.internal.base._Casts;
import org.apache.causeway.commons.internal.base._NullSafe;
import org.apache.causeway.commons.internal.functions._Predicates;
import
org.apache.causeway.core.metamodel.tabular.simple.CollectionContentsExporter;
@@ -279,6 +281,7 @@ public class ComponentFactoryRegistrarDefault implements
ComponentFactoryRegistr
// -- UTILTIY
+ @SuppressWarnings({ "rawtypes", "unchecked" })
public static <T extends Serializable>
ComponentFactoryScalarTypeConstrainedAbstract
createForValueSemantics(final ValueSemanticsProvider<T> valueSemantics) {
@@ -287,7 +290,7 @@ public class ComponentFactoryRegistrarDefault implements
ComponentFactoryRegistr
}
if(valueSemantics.isTemporalType()) {
- return new
ScalarPanelFactoryForTemporalPicker<T>(valueSemantics.getCorrespondingClass());
+ return _Casts.uncheckedCast(new
ScalarPanelFactoryForTemporalPicker(valueSemantics.getCorrespondingClass()));
}
if(valueSemantics.isCompositeType()) {
@@ -330,7 +333,7 @@ public class ComponentFactoryRegistrarDefault implements
ComponentFactoryRegistr
}
}
- public static class ScalarPanelFactoryForTemporalPicker<T extends
Serializable>
+ public static class ScalarPanelFactoryForTemporalPicker<T extends
Serializable & Temporal>
extends ComponentFactoryScalarTypeConstrainedAbstract {
private final Class<T> valueTypeClass;