blob: c9c6f6fa8ea990d7c87cabb96a52147ffaf6a438 [file] [log] [blame]
/**
* 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;
}
}
}