PL-6997 DatePicker component

This commit is contained in:
Nikita Petunin 2016-06-29 16:36:20 +04:00
parent a9f4fe7a29
commit b9bd4de614
9 changed files with 370 additions and 2 deletions

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* 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 com.haulmont.cuba.gui.components;
import java.util.Date;
public interface DatePicker extends Field {
String NAME = "datePicker";
enum Resolution {
DAY,
MONTH,
YEAR
}
/**
* Return resolution of the DatePicker.
*
* @return Resolution
*/
Resolution getResolution();
/**
* Set resolution of the DatePicker.
*
* @param resolution
*/
void setResolution(Resolution resolution);
/**
* Return start of range for a certain resolution.
*
* @return start of allowed range
*/
Date getRangeStart();
/**
* Set start of range. If the value is set before this
* date, the component will not validate.
*
* @param rangeStart
* - allowed start of range
*/
void setRangeStart(Date rangeStart);
/**
* Return end of range for a certain resolution.
*
* @return end of allowed range
*/
Date getRangeEnd();
/**
* Set end of range. If the value is set after this
* date, the component will not validate.
*
* @param rangeEnd
* - allowed end of range
*/
void setRangeEnd(Date rangeEnd);
}

View File

@ -639,6 +639,34 @@
<xs:attributeGroup ref="hasDatasource"/>
</xs:complexType>
<!-- DatePicker -->
<xs:complexType name="datePickerComponent">
<xs:attributeGroup ref="hasId"/>
<xs:attributeGroup ref="hasVisibility"/>
<xs:attributeGroup ref="hasEditable"/>
<xs:attributeGroup ref="hasEnableProp"/>
<xs:attributeGroup ref="hasCaption"/>
<xs:attributeGroup ref="hasStyle"/>
<xs:attributeGroup ref="hasAlign"/>
<xs:attributeGroup ref="hasSize"/>
<xs:attribute name="resolution">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="DAY"/>
<xs:enumeration value="MONTH"/>
<xs:enumeration value="YEAR"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="rangeStart" type="xs:string"/>
<xs:attribute name="rangeEnd" type="xs:string"/>
<xs:attributeGroup ref="hasDatasource"/>
</xs:complexType>
<!-- BaseField -->
<xs:complexType name="baseFieldComponent">
<xs:attributeGroup ref="hasId"/>
@ -1822,6 +1850,7 @@
<xs:element name="label" type="labelComponent"/>
<xs:element name="link" type="linkComponent"/>
<xs:element name="checkBox" type="checkBoxComponent"/>
<xs:element name="datePicker" type="datePickerComponent"/>
<xs:element name="textArea" type="textAreaComponent"/>
<xs:element name="textField" type="textFieldComponent"/>

View File

@ -74,6 +74,7 @@ public class LayoutLoaderConfig {
config.register(DateField.NAME, DateFieldLoader.class);
config.register(TimeField.NAME, TimeFieldLoader.class);
config.register(DatePicker.NAME, DatePickerLoader.class);
config.register(LookupField.NAME, LookupFieldLoader.class);
config.register(PickerField.NAME, PickerFieldLoader.class);
config.register(LookupPickerField.NAME, LookupPickerFieldLoader.class);

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* 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 com.haulmont.cuba.gui.xml.layout.loaders;
import com.haulmont.cuba.gui.GuiDevelopmentException;
import com.haulmont.cuba.gui.components.DatePicker;
import org.apache.commons.lang.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class DatePickerLoader extends AbstractFieldLoader<DatePicker> {
protected static final String DATE_PATTERN = "yyyy-MM-dd";
@Override
public void createComponent() {
resultComponent = (DatePicker) factory.createComponent(DatePicker.NAME);
loadId(resultComponent, element);
loadRangeStart();
loadRangeEnd();
loadResolution();
}
protected void loadResolution() {
final String resolution = element.attributeValue("resolution");
if (StringUtils.isNotEmpty(resolution)) {
DatePicker.Resolution res = DatePicker.Resolution.valueOf(resolution);
resultComponent.setResolution(res);
}
}
protected void loadRangeStart() {
String rangeStart = element.attributeValue("rangeStart");
if (StringUtils.isNotEmpty(rangeStart)) {
try {
SimpleDateFormat rangeDF = new SimpleDateFormat(DATE_PATTERN);
resultComponent.setRangeStart(rangeDF.parse(rangeStart));
} catch (ParseException e) {
throw new GuiDevelopmentException(
"'rangeStart' parsing error for date picker: " +
rangeStart, context.getFullFrameId(), "DatePicker ID", resultComponent.getId());
}
}
}
protected void loadRangeEnd() {
String rangeEnd = element.attributeValue("rangeEnd");
if (StringUtils.isNotEmpty(rangeEnd)) {
try {
SimpleDateFormat rangeDF = new SimpleDateFormat(DATE_PATTERN);
resultComponent.setRangeEnd(rangeDF.parse(rangeEnd));
} catch (ParseException e) {
throw new GuiDevelopmentException(
"'rangeEnd' parsing error for date picker: " +
rangeEnd, context.getFullFrameId(), "DatePicker ID", resultComponent.getId());
}
}
}
}

View File

@ -94,6 +94,7 @@ public class WebComponentsFactory implements ComponentsFactory {
classes.put(RowsCount.NAME, WebRowsCount.class);
classes.put(RelatedEntities.NAME, WebRelatedEntities.class);
classes.put(BulkEditor.NAME, WebBulkEditor.class);
classes.put(DatePicker.NAME, WebDatePicker.class);
classes.put(EntityLinkField.NAME, WebEntityLinkField.class);

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* 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 com.haulmont.cuba.web.gui.components;
import com.haulmont.bali.util.Preconditions;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaPropertyPath;
import com.haulmont.chile.core.model.utils.InstanceUtils;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.MessageTools;
import com.haulmont.cuba.core.global.Messages;
import com.haulmont.cuba.gui.components.DatePicker;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener;
import com.haulmont.cuba.gui.data.impl.WeakItemPropertyChangeListener;
import com.haulmont.cuba.web.gui.data.ItemWrapper;
import com.haulmont.cuba.web.gui.data.PropertyWrapper;
import com.haulmont.cuba.web.toolkit.ui.CubaDatePicker;
import com.vaadin.ui.InlineDateField;
import org.apache.commons.lang.StringUtils;
import java.util.Collection;
import java.util.Date;
public class WebDatePicker extends WebAbstractField<InlineDateField> implements DatePicker {
protected Resolution resolution = Resolution.DAY;
protected Datasource.ItemChangeListener itemChangeListener;
protected Datasource.ItemPropertyChangeListener itemPropertyChangeListener;
public WebDatePicker() {
this.component = new CubaDatePicker();
attachListener(component);
component.setImmediate(true);
component.setInvalidCommitted(true);
Messages messages = AppBeans.get(Messages.NAME);
component.setDateOutOfRangeMessage(messages.getMessage(WebAbstractTable.class, "datePicker.dateOutOfRangeMessage"));
}
@Override
protected ItemWrapper createDatasourceWrapper(Datasource datasource, Collection<MetaPropertyPath> propertyPaths) {
return new ItemWrapper(datasource, datasource.getMetaClass(), propertyPaths) {
@Override
protected PropertyWrapper createPropertyWrapper(Object item, MetaPropertyPath propertyPath) {
return new PropertyWrapper(item, propertyPath);
}
};
}
protected Date getEntityValue(Entity item) {
return InstanceUtils.getValueEx(item, metaPropertyPath.getPath());
}
@Override
public void setDatasource(Datasource datasource, String property) {
this.datasource = datasource;
MetaClass metaClass = datasource.getMetaClass();
resolveMetaPropertyPath(metaClass, property);
itemChangeListener = e -> {
Date value = getEntityValue(e.getItem());
this.setValue(value);
};
//noinspection unchecked
datasource.addItemChangeListener(new WeakItemChangeListener(datasource, itemChangeListener));
itemPropertyChangeListener = e -> {
if (e.getProperty().equals(metaPropertyPath.toString())) {
this.setValue(e.getValue());
}
};
//noinspection unchecked
datasource.addItemPropertyChangeListener(new WeakItemPropertyChangeListener(datasource, itemPropertyChangeListener));
if (datasource.getState() == Datasource.State.VALID && datasource.getItem() != null) {
if (property.equals(metaPropertyPath.toString())) {
Date value = getEntityValue(datasource.getItem());
this.setValue(value);
}
}
setRequired(metaProperty.isMandatory());
if (StringUtils.isEmpty(getRequiredMessage())) {
MessageTools messageTools = AppBeans.get(MessageTools.NAME);
setRequiredMessage(messageTools.getDefaultRequiredMessage(metaClass, property));
}
if (metaProperty.isReadOnly()) {
setEditable(false);
}
}
@Override
public Resolution getResolution() {
return resolution;
}
@Override
public void setResolution(Resolution resolution) {
Preconditions.checkNotNullArgument(resolution);
this.resolution = resolution;
com.vaadin.shared.ui.datefield.Resolution vResolution;
switch (resolution) {
case MONTH:
vResolution = com.vaadin.shared.ui.datefield.Resolution.MONTH;
break;
case YEAR:
vResolution = com.vaadin.shared.ui.datefield.Resolution.YEAR;
break;
case DAY:
vResolution = com.vaadin.shared.ui.datefield.Resolution.DAY;
break;
default:
vResolution = com.vaadin.shared.ui.datefield.Resolution.DAY;
break;
}
component.setResolution(vResolution);
}
@Override
public Date getRangeStart() {
return component.getRangeStart();
}
@Override
public void setRangeStart(Date rangeStart) {
component.setRangeStart(rangeStart);
}
@Override
public Date getRangeEnd() {
return component.getRangeEnd();
}
@Override
public void setRangeEnd(Date rangeEnd) {
component.setRangeEnd(rangeEnd);
}
}

View File

@ -16,4 +16,6 @@
tableSort.reset = Reset
tableSort.ascending = Ascending
tableSort.descending = Descending
tableSort.descending = Descending
datePicker.dateOutOfRangeMessage = Date out of range

View File

@ -16,4 +16,6 @@
tableSort.reset = Сбросить
tableSort.ascending = По возрастанию
tableSort.descending = По убыванию
tableSort.descending = По убыванию
datePicker.dateOutOfRangeMessage = Выбранная дата находится за пределами допустимых значений

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2008-2016 Haulmont.
*
* 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 com.haulmont.cuba.web.toolkit.ui;
import com.vaadin.ui.InlineDateField;
public class CubaDatePicker extends InlineDateField {
public CubaDatePicker() {
setValidationVisible(true);
setShowBufferedSourceException(false);
}
}