| /** |
| * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Florian Pirchner - Initial implementation |
| */ |
| package org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.internal; |
| |
| import java.text.DateFormat; |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| import java.util.Locale; |
| |
| import org.eclipse.core.databinding.Binding; |
| import org.eclipse.core.databinding.observable.IObservable; |
| import org.eclipse.core.databinding.observable.value.IObservableValue; |
| import org.eclipse.emf.databinding.EMFObservables; |
| import org.eclipse.osbp.ecview.core.common.editpart.IElementEditpart; |
| import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableBindingEndpoint; |
| import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddableValueEndpoint; |
| import org.eclipse.osbp.ecview.core.common.model.datatypes.YDatatype; |
| import org.eclipse.osbp.ecview.core.emf.api.IDateFormatProvider; |
| import org.eclipse.osbp.ecview.core.emf.api.IDateFormatProvider.Info; |
| import org.eclipse.osbp.ecview.core.extension.model.datatypes.YDateTimeDatatype; |
| import org.eclipse.osbp.ecview.core.extension.model.datatypes.YDateTimeFormat; |
| import org.eclipse.osbp.ecview.core.extension.model.datatypes.YDateTimeResolution; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.ExtensionModelPackage; |
| import org.eclipse.osbp.ecview.core.extension.model.extension.YDateTime; |
| import org.eclipse.osbp.ecview.core.ui.core.editparts.extension.IDateTimeEditpart; |
| import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common.AbstractFieldWidgetPresenter; |
| import org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.internal.util.Util; |
| |
| import com.vaadin.data.util.ObjectProperty; |
| import com.vaadin.server.ErrorMessage; |
| import com.vaadin.server.FontAwesome; |
| import com.vaadin.shared.ui.datefield.Resolution; |
| import com.vaadin.ui.Button; |
| import com.vaadin.ui.Component; |
| import com.vaadin.ui.ComponentContainer; |
| import com.vaadin.ui.DateField; |
| import com.vaadin.ui.Field; |
| import com.vaadin.ui.HorizontalLayout; |
| import com.vaadin.ui.UI; |
| import com.vaadin.ui.themes.ValoTheme; |
| |
| /** |
| * This presenter is responsible to render a text area on the given layout. |
| */ |
| public class DateTimePresentation extends AbstractFieldWidgetPresenter<Component> { |
| |
| /** The model access. */ |
| private final ModelAccess modelAccess; |
| |
| /** The date field. */ |
| private CustomField dateField; |
| |
| /** The binding_value to ui. */ |
| private Binding binding_valueToUI; |
| |
| /** The property. */ |
| private ObjectProperty<Date> property; |
| |
| /** The format info. */ |
| private Info formatInfo; |
| |
| /** |
| * Constructor. |
| * |
| * @param editpart |
| * The editpart of that presenter |
| */ |
| public DateTimePresentation(IElementEditpart editpart) { |
| super((IDateTimeEditpart) editpart); |
| this.modelAccess = new ModelAccess((YDateTime) editpart.getModel()); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Component doCreateWidget(Object parent) { |
| if (dateField == null) { |
| dateField = new CustomField(); |
| dateField.initField(); |
| dateField.addStyleName(CSS_CLASS_CONTROL); |
| dateField.setImmediate(true); |
| setupComponent(dateField.field, getCastedModel()); |
| |
| associateWidget(dateField.field, modelAccess.yField); |
| if (modelAccess.isCssIdValid()) { |
| dateField.setId(modelAccess.getCssID()); |
| } else { |
| dateField.setId(getEditpart().getId()); |
| } |
| |
| property = new ObjectProperty<>(null, Date.class); |
| dateField.setPropertyDataSource(property); |
| |
| // creates the binding for the field |
| createBindings(modelAccess.yField, dateField); |
| |
| if (modelAccess.isCssClassValid()) { |
| dateField.addStyleName(modelAccess.getCssClass()); |
| } |
| |
| doApplyDatatype(modelAccess.yField.getDatatype()); |
| |
| applyCaptions(); |
| |
| initializeField(dateField); |
| } |
| return dateField; |
| } |
| |
| /** |
| * Applies the datatype options to the field. |
| * |
| * @param yDt |
| * the y dt |
| */ |
| @Override |
| protected void doApplyDatatype(YDatatype yDt) { |
| if (dateField == null) { |
| return; |
| } |
| |
| IDateFormatProvider service = getViewContext().getService(IDateFormatProvider.class.getName()); |
| YDateTimeDatatype yDatatype = (YDateTimeDatatype) yDt; |
| if (service != null) { |
| formatInfo = service.getInfo(yDatatype, UI.getCurrent().getLocale()); |
| } else { |
| formatInfo = new DefaultDateFormatProvider().getInfo(yDatatype, UI.getCurrent().getLocale()); |
| } |
| if ( yDatatype != null ) { |
| dateField.setShowISOWeekNumber(yDatatype.isShowISOWeekNumbersActive()); |
| } else { |
| dateField.setShowISOWeekNumber(false); |
| } |
| dateField.setDateFormat(formatInfo.getDateFormat()); |
| dateField.setResolution(mapToVaadin(formatInfo.getResolution())); |
| } |
| |
| /** |
| * Map to vaadin. |
| * |
| * @param resolution |
| * the resolution |
| * @return the resolution |
| */ |
| private Resolution mapToVaadin(YDateTimeResolution resolution) { |
| switch (resolution) { |
| case YEAR: |
| return Resolution.YEAR; |
| case MONTH: |
| return Resolution.MONTH; |
| case DAY: |
| return Resolution.DAY; |
| case HOUR: |
| return Resolution.HOUR; |
| case MINUTE: |
| return Resolution.MINUTE; |
| case SECOND: |
| return Resolution.SECOND; |
| case UNDEFINED: |
| return Resolution.DAY; |
| } |
| |
| return Resolution.DAY; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common. |
| * AbstractVaadinWidgetPresenter#doUpdateLocale(java.util.Locale) |
| */ |
| @Override |
| protected void doUpdateLocale(Locale locale) { |
| // need to refresh the locale datetime pattern |
| doApplyDatatype(modelAccess.yField.getDatatype()); |
| // update the captions |
| applyCaptions(); |
| } |
| |
| /** |
| * Applies the labels to the widgets. |
| */ |
| protected void applyCaptions() { |
| Util.applyCaptions(getI18nService(), modelAccess.getLabel(), modelAccess.getLabelI18nKey(), getLocale(), |
| dateField); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common. |
| * AbstractFieldWidgetPresenter#doGetField() |
| */ |
| @Override |
| protected Field<?> doGetField() { |
| return dateField; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.osbp.runtime.web.ecview.presentation.vaadin.common. |
| * AbstractVaadinWidgetPresenter#internalGetObservableEndpoint(org.eclipse. |
| * osbp.ecview.core.common.model.core.YEmbeddableBindingEndpoint) |
| */ |
| @Override |
| protected IObservable internalGetObservableEndpoint(YEmbeddableBindingEndpoint bindableValue) { |
| if (bindableValue == null) { |
| throw new IllegalArgumentException("BindableValue must not be null!"); |
| } |
| |
| if (bindableValue instanceof YEmbeddableValueEndpoint) { |
| return internalGetValueEndpoint(); |
| } |
| throw new IllegalArgumentException("Not a valid input: " + bindableValue); |
| } |
| |
| /** |
| * Returns the observable to observe value. |
| * |
| * @return the i observable value |
| */ |
| protected IObservableValue internalGetValueEndpoint() { |
| // return the observable value for text |
| return EMFObservables.observeValue(castEObject(getModel()), ExtensionModelPackage.Literals.YDATE_TIME__VALUE); |
| } |
| |
| /** |
| * Creates the bindings for the given values. |
| * |
| * @param yField |
| * the y field |
| * @param customfield |
| * the field |
| */ |
| protected void createBindings(YDateTime yField, CustomField customfield) { |
| // create the model binding from widget to ECView-model |
| binding_valueToUI = createBindingsValue(castEObject(getModel()), |
| ExtensionModelPackage.Literals.YDATE_TIME__VALUE, customfield.field, null, null); |
| registerBinding(binding_valueToUI); |
| |
| super.createBindings(yField, customfield.field, null); |
| } |
| |
| |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation# |
| * getWidget() |
| */ |
| @Override |
| public Component getWidget() { |
| return dateField; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.core.common.presentation.IWidgetPresentation# |
| * isRendered() |
| */ |
| @Override |
| public boolean isRendered() { |
| return dateField != null; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void doUnrender() { |
| if (dateField != null) { |
| |
| // unbind all active bindings |
| unbind(); |
| |
| Component parent = (dateField.getParent()); |
| if (parent != null && parent instanceof ComponentContainer) { |
| ((ComponentContainer) parent).removeComponent(dateField); |
| } |
| |
| // remove assocations |
| unassociateWidget(dateField); |
| |
| dateField = null; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected void internalDispose() { |
| try { |
| unrender(); |
| } finally { |
| super.internalDispose(); |
| } |
| |
| if (binding_valueToUI != null) { |
| binding_valueToUI.dispose(); |
| binding_valueToUI = null; |
| } |
| } |
| |
| /** |
| * A helper class. |
| */ |
| private static class ModelAccess { |
| |
| /** The y field. */ |
| private final YDateTime yField; |
| |
| /** |
| * Instantiates a new model access. |
| * |
| * @param yField |
| * the y field |
| */ |
| public ModelAccess(YDateTime yField) { |
| super(); |
| this.yField = yField; |
| } |
| |
| /** |
| * Gets the css class. |
| * |
| * @return the css class |
| * @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssClass() |
| */ |
| public String getCssClass() { |
| return yField.getCssClass(); |
| } |
| |
| /** |
| * Returns true, if the css class is not null and not empty. |
| * |
| * @return true, if is css class valid |
| */ |
| public boolean isCssClassValid() { |
| return getCssClass() != null && !getCssClass().equals(""); |
| } |
| |
| /** |
| * Gets the css id. |
| * |
| * @return the css id |
| * @see org.eclipse.osbp.ecview.core.ui.core.model.core.YCssAble#getCssID() |
| */ |
| public String getCssID() { |
| return yField.getCssID(); |
| } |
| |
| /** |
| * Returns true, if the css id is not null and not empty. |
| * |
| * @return true, if is css id valid |
| */ |
| public boolean isCssIdValid() { |
| return getCssID() != null && !getCssID().equals(""); |
| } |
| |
| /** |
| * Returns the label. |
| * |
| * @return the label |
| */ |
| public String getLabel() { |
| return yField.getDatadescription() != null ? yField.getDatadescription().getLabel() : null; |
| } |
| |
| /** |
| * Returns the label. |
| * |
| * @return the label i18n key |
| */ |
| public String getLabelI18nKey() { |
| return yField.getDatadescription() != null ? yField.getDatadescription().getLabelI18nKey() : null; |
| } |
| |
| /** |
| * Returns true, if the date format is valid. |
| * |
| * @return true, if is dateformat valid |
| */ |
| @SuppressWarnings("unused") |
| public boolean isDateformatValid() { |
| return yField.getDatadescription() != null && yField.getDatatype().getFormat() != null; |
| } |
| } |
| |
| /** |
| * The Class CustomField. |
| */ |
| @SuppressWarnings("serial") |
| private class CustomField extends com.vaadin.ui.CustomField<Date> { |
| private DateField field; |
| private Button resetDate; |
| private ObjectProperty<Date> property; |
| private boolean showISOWeekNumber; |
| |
| @Override |
| protected Component initContent() { |
| field.setShowISOWeekNumbers(showISOWeekNumber); |
| property.addValueChangeListener(e -> { |
| super.setValue((Date) e.getProperty().getValue()); |
| }); |
| resetDate = new Button(); |
| resetDate.setIcon(FontAwesome.CALENDAR_CHECK_O); |
| resetDate.addClickListener(e -> { |
| property.setValue(new Date(System.currentTimeMillis())); |
| super.focus(); |
| }); |
| |
| setFocusDelegate(field); |
| |
| resetDate.setVisible(field.isVisible()); |
| resetDate.setEnabled(field.isEnabled()); |
| if(field.isReadOnly()){ |
| resetDate.setVisible(false); |
| } |
| |
| HorizontalLayout layout = new HorizontalLayout(field, resetDate); |
| layout.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP); |
| return layout; |
| } |
| |
| public void setShowISOWeekNumber(boolean value) { |
| showISOWeekNumber = value; |
| } |
| |
| void initField(){ |
| field = new DateField(); |
| } |
| |
| public void setResolution(Resolution res) { |
| field.setResolution(res); |
| } |
| |
| public void setDateFormat(String dateFormat) { |
| field.setDateFormat(dateFormat); |
| } |
| |
| public void setPropertyDataSource(ObjectProperty<Date> property){ |
| this.property = property; |
| field.setPropertyDataSource(property); |
| } |
| |
| @Override |
| public Class<Date> getType() { |
| return Date.class; |
| } |
| |
| @Override |
| protected void setInternalValue(Date newValue) { |
| super.setInternalValue(newValue); |
| |
| if (property != null) { |
| property.setValue(newValue); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.vaadin.ui.AbstractField#getErrorMessage() |
| */ |
| @Override |
| public ErrorMessage getErrorMessage() { |
| if (isDisposed()) { |
| // after disposal, Vaadin will call this method once. |
| return null; |
| } |
| |
| ErrorMessage message = super.getErrorMessage(); |
| reportValidationError(message); |
| return message; |
| } |
| } |
| |
| /** |
| * The Class DefaultDateFormatProvider. |
| */ |
| private static class DefaultDateFormatProvider implements IDateFormatProvider { |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.osbp.ecview.core.emf.api.IDateFormatProvider#getInfo(org. |
| * eclipse.osbp.ecview.core.extension.model.datatypes.YDateTimeDatatype, |
| * java.util.Locale) |
| */ |
| @Override |
| public Info getInfo(YDateTimeDatatype yDt, Locale locale) { |
| |
| if (yDt == null) { |
| DateFormat formatter = DateFormat.getDateInstance(DateFormat.DEFAULT, locale); |
| return new IDateFormatProvider.Info(((SimpleDateFormat) formatter).toPattern(), |
| YDateTimeResolution.DAY); |
| } |
| |
| DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, locale); |
| String pattern = ((SimpleDateFormat) formatter).toPattern(); |
| |
| String dateFormat = null; |
| String rightpattern = null; |
| YDateTimeResolution resolution = calcResolution(yDt); |
| YDateTimeFormat yFormat = yDt.getFormat(); |
| if (yFormat != null) { |
| switch (yFormat) { |
| case DATE: |
| switch (resolution) { |
| case YEAR: |
| dateFormat = filterFormat(pattern, "yyyy"); |
| break; |
| case MONTH: |
| dateFormat = filterFormat(pattern, "yyyy.MM"); |
| break; |
| case DAY: |
| dateFormat = filterFormat(pattern, "yyyy.MM.dd"); |
| break; |
| default: |
| throw new IllegalArgumentException(resolution + " is not a valid resolution for " + yFormat); |
| } |
| break; |
| case DATE_TIME: |
| switch (resolution) { |
| case YEAR: |
| dateFormat = filterFormat(pattern, "yyyy"); |
| break; |
| case MONTH: |
| dateFormat = filterFormat(pattern, "yyyy.MM"); |
| break; |
| case DAY: |
| dateFormat = filterFormat(pattern, "yyyy.MM.dd"); |
| break; |
| case HOUR: |
| rightpattern = pattern.contains("a") ? "yyyy.MM.dd hhHH a" : "yyyy.MM.dd hhHH"; |
| dateFormat = filterFormat(pattern, rightpattern); |
| break; |
| case MINUTE: |
| rightpattern = pattern.contains("a") ? "yyyy.MM.dd hhHH:mm a" : "yyyy.MM.dd hhHH:mm"; |
| dateFormat = filterFormat(pattern, rightpattern); |
| break; |
| case SECOND: |
| rightpattern = pattern.contains("a") ? "yyyy.MM.dd hhHH:mm:ss a" : "yyyy.MM.dd hhHH:mm:ss"; |
| dateFormat = filterFormat(pattern, rightpattern); |
| break; |
| default: |
| throw new IllegalArgumentException(resolution + " is not a valid resolution for " + yFormat); |
| } |
| break; |
| case TIME: |
| switch (resolution) { |
| case HOUR: |
| rightpattern = pattern.contains("a") ? "hhHH a" : "hhHH"; |
| dateFormat = filterFormat(pattern, rightpattern); |
| break; |
| case MINUTE: |
| rightpattern = pattern.contains("a") ? "hhHH:mm a" : "hhHH:mm"; |
| dateFormat = filterFormat(pattern, rightpattern); |
| break; |
| case SECOND: |
| rightpattern = pattern.contains("a") ? "hhHH:mm:ss a" : "hhHH:mm:ss"; |
| dateFormat = filterFormat(pattern, rightpattern); |
| break; |
| default: |
| throw new IllegalArgumentException(resolution + " is not a valid resolution for " + yFormat); |
| } |
| break; |
| } |
| } |
| return new IDateFormatProvider.Info(dateFormat, resolution); |
| } |
| |
| /** |
| * filters from any localized date-time pattern the desired subset |
| * defined by filterPattern without destroying the original localized |
| * pattern . |
| * |
| * @param localizedPattern |
| * the localized full date-time pattern |
| * @param filterPattern |
| * the subset of desired date-time formatter patterns |
| * @return the string |
| */ |
| private String filterFormat(String localizedPattern, String filterPattern) { |
| // remove any multiple characters sequences and remove all separator |
| // signs from filterPattern |
| String filter = filterPattern.replaceAll("(.)\\1+", "$1").replaceAll("[^\\w\\s]", "") + ","; |
| // create a replacement pattern to remove unnecessary blanks |
| // disturbing the recognition of orphaned separators |
| // rule: each blank must be surrounded by any filter-letter to be |
| // valid |
| String invalidBlanks = "(?![" + filter + "])( )(?![" + filter + "])"; |
| // create a replacement pattern to remove remaining separators |
| // without formatting function |
| // rule: each separator must be surrounded by any filter-letter or |
| // blank to be valid |
| String invalidSeparators = "(?![" + filter + " ])([.:])(?![" + filter + " ])"; |
| |
| String dateFormat = localizedPattern.replaceAll("[^" + filter + ",.: ]", "").replaceAll(invalidBlanks, "").trim() |
| .replaceAll(invalidSeparators, ""); |
| if(dateFormat.startsWith(",") || dateFormat.startsWith(".")){ dateFormat = dateFormat.substring(1); } |
| return dateFormat; |
| } |
| |
| /** |
| * Calc resolution. |
| * |
| * @param yDt |
| * the y dt |
| * @return the y date time resolution |
| */ |
| private YDateTimeResolution calcResolution(YDateTimeDatatype yDt) { |
| YDateTimeFormat yFormat = yDt.getFormat(); |
| YDateTimeResolution resolution = null; |
| if (yFormat != null) { |
| YDateTimeResolution yResolution = yDt.getResolution(); |
| switch (yFormat) { |
| case DATE: |
| if (yResolution == YDateTimeResolution.UNDEFINED || yResolution == YDateTimeResolution.SECOND |
| || yResolution == YDateTimeResolution.MINUTE || yResolution == YDateTimeResolution.HOUR) { |
| resolution = YDateTimeResolution.DAY; |
| } |
| break; |
| case DATE_TIME: |
| if (yResolution == YDateTimeResolution.UNDEFINED || yResolution == YDateTimeResolution.DAY |
| || yResolution == YDateTimeResolution.MONTH || yResolution == YDateTimeResolution.YEAR) { |
| resolution = YDateTimeResolution.MINUTE; |
| } |
| break; |
| case TIME: |
| if (yResolution == YDateTimeResolution.UNDEFINED || yResolution == YDateTimeResolution.DAY |
| || yResolution == YDateTimeResolution.MONTH || yResolution == YDateTimeResolution.YEAR) { |
| resolution = YDateTimeResolution.MINUTE; |
| } |
| break; |
| } |
| } |
| |
| if (resolution == null) { |
| switch (yDt.getResolution()) { |
| case SECOND: |
| resolution = YDateTimeResolution.SECOND; |
| break; |
| case MINUTE: |
| resolution = YDateTimeResolution.MINUTE; |
| break; |
| case HOUR: |
| resolution = YDateTimeResolution.HOUR; |
| break; |
| case DAY: |
| resolution = YDateTimeResolution.DAY; |
| break; |
| case MONTH: |
| resolution = YDateTimeResolution.MONTH; |
| break; |
| case YEAR: |
| resolution = YDateTimeResolution.YEAR; |
| break; |
| case UNDEFINED: |
| resolution = YDateTimeResolution.MINUTE; |
| break; |
| default: |
| resolution = YDateTimeResolution.MINUTE; |
| } |
| } |
| |
| return resolution; |
| } |
| |
| } |
| } |