All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dominokit.domino.ui.forms.TimeBox Maven / Gradle / Ivy

/*
 * Copyright © 2019 Dominokit
 *
 * 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 org.dominokit.domino.ui.forms;

import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.menu.direction.DropDirection.BEST_MIDDLE_DOWN_UP;
import static org.dominokit.domino.ui.utils.Domino.*;

import elemental2.dom.DomGlobal;
import elemental2.dom.HTMLInputElement;
import java.util.Date;
import java.util.Objects;
import org.dominokit.domino.ui.datepicker.*;
import org.dominokit.domino.ui.forms.validations.ValidationResult;
import org.dominokit.domino.ui.i18n.HasLabels;
import org.dominokit.domino.ui.i18n.TimePickerLabels;
import org.dominokit.domino.ui.menu.direction.DropDirection;
import org.dominokit.domino.ui.popover.Popover;
import org.dominokit.domino.ui.timepicker.TimeFormatter;
import org.dominokit.domino.ui.timepicker.TimePicker;
import org.dominokit.domino.ui.timepicker.TimePickerViewListener;
import org.dominokit.domino.ui.utils.*;
import org.gwtproject.i18n.shared.cldr.DateTimeFormatInfo;
import org.gwtproject.i18n.shared.cldr.impl.DateTimeFormatInfo_factory;

/**
 * Represents a time input form field with the capability to pick a time.
 *
 * 

Usage example: * *

 * TimeBox defaultTimeBox = TimeBox.create();
 * TimeBox labeledTimeBox = TimeBox.create("Choose a time:");
 * 
* * @see TextInputFormField * @see TimePickerViewListener */ public class TimeBox extends TextInputFormField implements HasLabels, TimePickerViewListener { private final Popover popover; private final TimePicker timePicker; private Date value; private TimeFormatter formatter = TimeFormatter.DEFAULT; private boolean openOnFocus = false; private boolean openOnClick = true; private boolean silentSelection = false; private String pattern; private boolean parseStrict; /** Constructs a TimeBox with the current date set. */ public TimeBox() { this(new Date()); } /** * Constructs a TimeBox with the given label and current date set. * * @param label the label for the time box */ public TimeBox(String label) { this(label, new Date()); } /** * Constructs a TimeBox with the specified date set. * * @param date the initial date to be set */ public TimeBox(Date date) { this(date, DateTimeFormatInfo_factory.create()); } /** * Constructs a TimeBox with the specified label and date. * * @param label the label for the time box * @param date the initial date to be set */ public TimeBox(String label, Date date) { this(label, date, DateTimeFormatInfo_factory.create()); } /** * Constructs a TimeBox with the specified label, date, and date format information. * * @param label the label for the time box * @param date the initial date to be set * @param dateTimeFormatInfo the date format information */ public TimeBox(String label, Date date, DateTimeFormatInfo dateTimeFormatInfo) { this(date, dateTimeFormatInfo); setLabel(label); } /** * Constructs a TimeBox with the specified date and date format information. * * @param date the initial date to be set * @param dateTimeFormatInfo the date format information */ public TimeBox(Date date, DateTimeFormatInfo dateTimeFormatInfo) { this.value = date; this.timePicker = TimePicker.create(date, dateTimeFormatInfo); this.pattern = dateTimeFormatInfo.timeFormatFull(); this.popover = Popover.create(this.getWrapperElement()) .setOpenCondition(() -> isEnabled() && !isReadOnly()) .setOpenOnClick(this.openOnClick) .setPosition(BEST_MIDDLE_DOWN_UP) .appendChild(this.timePicker) .addOnRemoveListener( popover -> { withOpenOnFocusToggleListeners(false, field -> focus()); }); onDetached(mutationRecord -> popover.close()); getInputElement() .onKeyPress(keyEvents -> keyEvents.onEnter(evt -> doOpen()).onSpace(evt -> doOpen())); addValidator( component -> { try { if (isEmptyIgnoreSpaces()) { return ValidationResult.valid(); } getFormattedValue(getStringValue()); return ValidationResult.valid(); } catch (IllegalArgumentException e) { return ValidationResult.invalid(getLabels().timePickerInvalidTimeFormat()); } }); getInputElement() .addEventListener( "change", evt -> { String value = getStringValue(); if (value.isEmpty()) { clear(); } else { try { withValue(getFormattedValue(value)); clearInvalid(); } catch (IllegalArgumentException ignored) { if (parseStrict) { invalidate("Unable to parse date value " + value); } DomGlobal.console.warn("Unable to parse date value " + value); } } }); appendChild( PrimaryAddOn.of( getConfig() .defaultDateBoxIcon() .get() .clickable() .addClickListener( evt -> { evt.stopPropagation(); doOpen(); }))); getInputElement() .addEventListener( "focus", evt -> { if (openOnFocus) { doOpen(); } }) .addEventListener( "click", evt -> { if (openOnClick) { doOpen(); } }); this.timePicker.bindTimePickerViewListener(this); setStringValue(value, this.timePicker.getDateTimeFormatInfo()); } /** * Factory method to create a new instance of {@link TimeBox} with the current date set. * * @return a new instance of TimeBox */ public static TimeBox create() { return new TimeBox(new Date()); } /** * Factory method to create a new instance of {@link TimeBox} with the specified label and current * date set. * * @param label the label for the time box * @return a new instance of TimeBox */ public static TimeBox create(String label) { return new TimeBox(label, new Date()); } /** * Factory method to create a new instance of {@link TimeBox} with the specified date. * * @param date the date to set * @return a new instance of TimeBox */ public static TimeBox create(Date date) { return new TimeBox(date, DateTimeFormatInfo_factory.create()); } /** * Factory method to create a new instance of {@link TimeBox} with the specified label and date. * * @param label the label for the time box * @param date the date to set * @return a new instance of TimeBox */ public static TimeBox create(String label, Date date) { return new TimeBox(label, date, DateTimeFormatInfo_factory.create()); } /** * Factory method to create a new instance of {@link TimeBox} with the specified date and date * format information. * * @param date the date to set * @param dateTimeFormatInfo the date format information * @return a new instance of TimeBox */ public static TimeBox create(Date date, DateTimeFormatInfo dateTimeFormatInfo) { return new TimeBox(date, dateTimeFormatInfo); } /** * Factory method to create a new instance of {@link TimeBox} with the specified date format * information. * * @param dateTimeFormatInfo the date format information * @return a new instance of TimeBox */ public static TimeBox create(DateTimeFormatInfo dateTimeFormatInfo) { return new TimeBox(new Date(), dateTimeFormatInfo); } /** * Factory method to create a new instance of {@link TimeBox} with the specified label and date * format information. * * @param label the label for the time box * @param dateTimeFormatInfo the date format information * @return a new instance of TimeBox */ public static TimeBox create(String label, DateTimeFormatInfo dateTimeFormatInfo) { return new TimeBox(label, new Date(), dateTimeFormatInfo); } /** * Factory method to create a new instance of {@link TimeBox} with the specified label, date, and * date format information. * * @param label the label for the time box * @param date the date to set * @param dateTimeFormatInfo the date format information * @return a new instance of TimeBox */ public static TimeBox create(String label, Date date, DateTimeFormatInfo dateTimeFormatInfo) { return new TimeBox(label, date, dateTimeFormatInfo); } private void doOpen() { if (isEnabled() && !isReadOnly()) { popover.open(); } } /** * Closes the associated popover. * * @return the current instance of {@link TimeBox} */ public TimeBox close() { popover.close(); return this; } /** * Sets the pattern for time formatting. * * @param pattern the {@link Pattern} to set * @return the current instance of {@link TimeBox} */ public TimeBox setPattern(Pattern pattern) { switch (pattern) { case FULL: return setPattern(this.timePicker.getDateTimeFormatInfo().timeFormatFull()); case LONG: return setPattern(this.timePicker.getDateTimeFormatInfo().timeFormatLong()); case MEDIUM: return setPattern(this.timePicker.getDateTimeFormatInfo().timeFormatMedium()); case SHORT: return setPattern(this.timePicker.getDateTimeFormatInfo().timeFormatShort()); default: return this; } } /** * Sets the custom pattern for time formatting. * * @param pattern the custom pattern string * @return the current instance of {@link TimeBox} */ public TimeBox setPattern(String pattern) { if (!Objects.equals(this.pattern, pattern)) { this.pattern = pattern; setStringValue(value, this.timePicker.getDateTimeFormatInfo()); } return this; } private void setStringValue(Date date, DateTimeFormatInfo dateTimeFormatInfo) { if (nonNull(date)) this.getInputElement().element().value = getFormatted(date, dateTimeFormatInfo); else this.getInputElement().element().value = ""; } private String getFormatted(Date date, DateTimeFormatInfo dateTimeFormatInfo) { return formatter.format(this.pattern, dateTimeFormatInfo, date); } @Override protected DominoElement createInputElement(String type) { return input(type).addCss(dui_field_input).toDominoElement(); } private Date getFormattedValue(String value) throws IllegalArgumentException { DateTimeFormatInfo dateTimeFormatInfo = this.timePicker.getDateTimeFormatInfo(); if (this.parseStrict) { return formatter.parseStrict(this.pattern, dateTimeFormatInfo, value); } return formatter.parse(this.pattern, dateTimeFormatInfo, value); } /** * Sets the position of the popover. * * @param position the {@link DropDirection} position * @return the current instance of {@link TimeBox} */ public TimeBox setPopoverPosition(DropDirection position) { if (nonNull(position)) { this.popover.setPosition(position); } return this; } /** * Temporarily toggles the "open on focus" state and applies the given handler. * * @param toggle desired temporary state * @param handler the handler to be applied * @return the current instance of {@link TimeBox} */ public TimeBox withOpenOnFocusToggleListeners(boolean toggle, Handler handler) { boolean oldState = this.openOnFocus; this.openOnFocus = toggle; try { handler.apply(this); } finally { this.openOnFocus = oldState; } return this; } /** * Temporarily toggles the "open on focus" state, applies the asynchronous handler, and then * reverts to the original state once the handler has completed. * * @param toggle desired temporary state * @param handler the asynchronous handler to be applied * @return the current instance of {@link TimeBox} */ public TimeBox withPausedOpenOnFocusListeners(boolean toggle, AsyncHandler handler) { boolean oldState = this.openOnFocus; this.openOnFocus = toggle; try { handler.apply(this, () -> this.openOnFocus = oldState); } catch (Exception e) { this.openOnFocus = oldState; throw e; } return this; } /** * Temporarily toggles the silent time selection and applies the given handler. * * @param toggle desired temporary state * @param handler the handler to be applied * @return the current instance of {@link TimeBox} */ private TimeBox withTimeSelectionToggleListeners(boolean toggle, Handler handler) { boolean oldState = this.silentSelection; this.silentSelection = toggle; try { handler.apply(this); } finally { this.silentSelection = oldState; } return this; } /** * Sets the value of the TimeBox and updates the visual display accordingly. * * @param value the date value to be set */ @Override protected void doSetValue(Date value) { this.value = value; if (nonNull(value)) { updateStringValue(); } else { getInputElement().element().value = ""; } withTimeSelectionToggleListeners( false, field -> { if (nonNull(this.value)) { this.timePicker.setDate(this.value); } }); } /** * Gets the formatted string representation of the current time value. * * @return the formatted time string */ private void updateStringValue() { getInputElement().element().value = getFormatted(this.value, this.timePicker.getDateTimeFormatInfo()); } /** * Retrieves the string representation of the current value in the input field. * * @return the string value */ @Override public String getStringValue() { return getInputElement().element().value; } /** * Retrieves the type of the input field. * * @return the string "text" */ @Override public String getType() { return "text"; } /** * Retrieves the current date value set in the TimeBox. * * @return the current date value */ @Override public Date getValue() { return this.value; } /** * Handles changes in time selection. * * @param date the newly selected date */ @Override public void onTimeSelectionChanged(Date date) { if (!isDisabled() && !isReadOnly()) { if (silentSelection == false) { clearInvalid(); withValue(date); } } } /** * Retrieves the current date-time format information. * * @return the current {@link DateTimeFormatInfo} */ public DateTimeFormatInfo getDateTimeFormat() { return this.timePicker.getDateTimeFormatInfo(); } /** * Sets the date-time format information for the TimeBox. * * @param dateTimeFormatInfo the {@link DateTimeFormatInfo} to set * @return the current instance of {@link TimeBox} */ public TimeBox setDateTimeFormat(DateTimeFormatInfo dateTimeFormatInfo) { this.timePicker.setDateTimeFormatInfo(dateTimeFormatInfo); return this; } /** * Handles changes in the date-time format information and updates the string value. * * @param dateTimeFormatInfo the updated {@link DateTimeFormatInfo} */ @Override public void onDateTimeFormatInfoChanged(DateTimeFormatInfo dateTimeFormatInfo) { updateStringValue(); } /** * Checks if the TimeBox is set to open on focus. * * @return true if set to open on focus, false otherwise. */ public boolean isOpenOnFocus() { return openOnFocus; } /** * Configures the TimeBox to open on focus. * * @param openOnFocus true to open on focus, false otherwise. * @return the current instance of {@link TimeBox} */ public TimeBox setOpenOnFocus(boolean openOnFocus) { this.openOnFocus = openOnFocus; return this; } /** * Checks if parsing is strict. * * @return true if strict parsing, false otherwise. */ public boolean isParseStrict() { return parseStrict; } /** * Configures whether parsing should be strict. * * @param parseStrict true for strict parsing, false otherwise. * @return the current instance of {@link TimeBox} */ public TimeBox setParseStrict(boolean parseStrict) { this.parseStrict = parseStrict; return this; } /** * Checks if the TimeBox is set to open on click. * * @return true if the TimeBox opens on click, false otherwise. */ public boolean isOpenOnClick() { return openOnClick; } /** * Sets the behavior of the TimeBox to open on click or not. * * @param openOnClick true if the TimeBox should open on click, false otherwise. * @return the current instance of {@link TimeBox} */ public TimeBox setOpenOnClick(boolean openOnClick) { this.openOnClick = openOnClick; this.popover.setOpenOnClick(this.openOnClick); return this; } /** * Applies a handler to the {@link TimePicker} associated with this TimeBox. * * @param handler the handler to be applied to the {@link TimePicker} * @return the current instance of {@link TimeBox} */ public TimeBox withTimePicker(ChildHandler handler) { handler.apply(this, this.timePicker); return this; } /** * Applies a handler to the {@link Popover} associated with this TimeBox. * * @param handler the handler to be applied to the {@link Popover} * @return the current instance of {@link TimeBox} */ public TimeBox withPopover(ChildHandler handler) { handler.apply(this, this.popover); return this; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy