Created
October 28, 2016 23:45
-
-
Save kevzlou7979/1aa16ddc30b2594c2e6b2e50acf19538 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* #%L | |
* GwtMaterial | |
* %% | |
* Copyright (C) 2015 - 2016 GwtMaterialDesign | |
* %% | |
* 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. | |
* #L% | |
*/ | |
package gwt.material.design.client.ui; | |
import com.google.gwt.core.client.JsDate; | |
import com.google.gwt.core.client.Scheduler; | |
import com.google.gwt.core.client.ScriptInjector; | |
import com.google.gwt.dom.client.Document; | |
import com.google.gwt.dom.client.Element; | |
import com.google.gwt.dom.client.Style; | |
import com.google.gwt.event.dom.client.BlurEvent; | |
import com.google.gwt.event.dom.client.FocusEvent; | |
import com.google.gwt.event.logical.shared.*; | |
import com.google.gwt.event.shared.HandlerRegistration; | |
import com.google.gwt.user.client.DOM; | |
import gwt.material.design.client.base.*; | |
import gwt.material.design.client.base.mixin.CssNameMixin; | |
import gwt.material.design.client.base.mixin.ErrorMixin; | |
import gwt.material.design.client.base.mixin.ReadOnlyMixin; | |
import gwt.material.design.client.constants.*; | |
import gwt.material.design.client.js.JsDatePickerOptions; | |
import gwt.material.design.client.ui.html.DateInput; | |
import gwt.material.design.client.ui.html.Label; | |
import java.util.Date; | |
import static gwt.material.design.client.js.JsMaterialElement.$; | |
//@formatter:off | |
/** | |
* Material Date Picker will provide a visual calendar to your apps. | |
* <p/> | |
* <h3>UiBinder Usage:</h3> | |
* {@code | |
* <m:MaterialDatePicker ui:field="datePicker"> | |
* } | |
* <h3>Java Usage:</h3> | |
* {@code | |
* datePicker.setDate(new Date()); | |
* } | |
* | |
* @author kevzlou7979 | |
* @author Ben Dol | |
* @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#!pickers">Material Date Picker</a> | |
*/ | |
//@formatter:on | |
public class MaterialDatePicker extends AbstractValueWidget<Date> implements HasOrientation, HasPlaceholder, | |
HasOpenHandlers<MaterialDatePicker>, HasCloseHandlers<MaterialDatePicker>, HasIcon, HasReadOnly { | |
/** | |
* Enum for identifying various selection types for the picker. | |
*/ | |
public enum MaterialDatePickerType { | |
DAY, | |
MONTH_DAY, | |
YEAR_MONTH_DAY, | |
YEAR | |
} | |
private String placeholder; | |
private Date date; | |
private Date dateMin; | |
private Date dateMax; | |
private Date dateTemp; | |
private String format = "dd mmmm yyyy"; | |
private DateInput dateInput; | |
private Label label = new Label(); | |
private MaterialLabel lblPlaceholder = new MaterialLabel(); | |
private Element pickatizedDateInput; | |
private MaterialLabel lblError = new MaterialLabel(); | |
private DatePickerLanguage language; | |
private MaterialDatePickerType selectionType = MaterialDatePickerType.DAY; | |
private boolean initialize = false; | |
private MaterialIcon icon = new MaterialIcon(); | |
private ErrorMixin<AbstractValueWidget, MaterialLabel> errorMixin = new ErrorMixin<>(this, lblError, dateInput, lblPlaceholder); | |
private ReadOnlyMixin<MaterialDatePicker, DateInput> readOnlyMixin; | |
private CssNameMixin<MaterialDatePicker, Orientation> orientationMixin = new CssNameMixin<>(this); | |
private JsDatePickerOptions events = new JsDatePickerOptions(); | |
public MaterialDatePicker() { | |
super(Document.get().createDivElement(), CssName.INPUT_FIELD); | |
dateInput = new DateInput(); | |
add(dateInput); | |
label.add(lblPlaceholder); | |
add(label); | |
add(lblError); | |
} | |
public MaterialDatePicker(String placeholder) { | |
this(); | |
setPlaceholder(placeholder); | |
} | |
public MaterialDatePicker(String placeholder, Date value) { | |
this(placeholder); | |
setDate(value); | |
} | |
public MaterialDatePicker(String placeholder, Date value, MaterialDatePickerType selectionType) { | |
this(placeholder, value); | |
setSelectionType(selectionType); | |
} | |
@Override | |
public void onLoad() { | |
super.onLoad(); | |
if (!initialize) { | |
initialize(); | |
} else { | |
reinitialize(); | |
} | |
} | |
@Override | |
public void onUnload() { | |
super.onUnload(); | |
dateTemp = getValue(); | |
initialize = false; | |
$(pickatizedDateInput).pickadate("picker").off(events); | |
} | |
@Override | |
public void clear() { | |
if (initialize) { | |
clearErrorOrSuccess(); | |
label.removeStyleName(CssName.ACTIVE); | |
dateInput.removeStyleName(CssName.VALID); | |
dateInput.clear(); | |
} | |
} | |
/** | |
* Sets the type of selection options (date, month, year,...). | |
* | |
* @param type if <code>null</code>, {@link MaterialDatePickerType#DAY} will be used as fallback. | |
*/ | |
public void setDateSelectionType(MaterialDatePickerType type) { | |
if (type != null) { | |
this.selectionType = type; | |
} | |
} | |
protected void initHandlers(Element picker) { | |
events.open = this::onOpen; | |
events.close = () -> { | |
onClose(); | |
$(picker).blur(); | |
}; | |
events.set = thing -> { | |
if (thing.hasOwnProperty("clear")) { | |
onClear(); | |
} else if (thing.hasOwnProperty("select")) { | |
onSelect(); | |
} | |
}; | |
$(picker).pickadate("picker").on(events); | |
} | |
protected void onClose() { | |
CloseEvent.fire(this, this); | |
fireEvent(new BlurEvent() { | |
}); | |
} | |
protected void onOpen() { | |
label.addStyleName(CssName.ACTIVE); | |
dateInput.setFocus(true); | |
OpenEvent.fire(this, this); | |
fireEvent(new FocusEvent() { | |
}); | |
} | |
/** | |
* Programmatically close the date picker component | |
*/ | |
public void close() { | |
Scheduler.get().scheduleDeferred(() -> { | |
$(pickatizedDateInput).pickadate("picker").close(); | |
}); | |
} | |
/** | |
* Programmatically open the date picker component | |
*/ | |
public void open() { | |
Scheduler.get().scheduleDeferred(() -> { | |
$(pickatizedDateInput).pickadate("picker").open(); | |
}); | |
} | |
protected void onSelect() { | |
label.addStyleName(CssName.ACTIVE); | |
dateInput.addStyleName(CssName.VALID); | |
// Ensure the value change event is | |
// triggered on selecting a date. | |
ValueChangeEvent.fire(this, getValue()); | |
} | |
protected void onClear() { | |
clear(); | |
} | |
public String getPickerId() { | |
return $(pickatizedDateInput).pickadate("picker").get("id").toString(); | |
} | |
protected void initialize() { | |
JsDatePickerOptions options = new JsDatePickerOptions(); | |
options.container = "body"; | |
options.format = getFormat(); | |
switch (getSelectionType()) { | |
case MONTH_DAY: | |
options.selectMonths = true; | |
break; | |
case YEAR_MONTH_DAY: | |
options.selectYears = true; | |
options.selectMonths = true; | |
break; | |
case YEAR: | |
options.selectYears = true; | |
break; | |
} | |
pickatizedDateInput = $(dateInput.getElement()).pickadate(options).asElement(); | |
initialize = true; | |
label.getElement().setAttribute("for", getPickerId()); | |
setDate(this.date); | |
setDateMin(dateMin); | |
setDateMax(dateMax); | |
setPlaceholder(this.placeholder); | |
initHandlers(pickatizedDateInput); | |
} | |
/** | |
* Sets the current date of the picker. | |
* | |
* @param date - must not be <code>null</code> | |
*/ | |
public void setDate(Date date) { | |
setValue(date); | |
} | |
/** | |
* Get the minimum date limit. | |
*/ | |
public Date getDateMin() { | |
return dateMin; | |
} | |
/** | |
* Set the minimum date limit. | |
*/ | |
public void setDateMin(Date dateMin) { | |
this.dateMin = dateMin; | |
if (initialize && dateMin != null) { | |
$(pickatizedDateInput).pickadate("picker").set("min", JsDate.create((double) dateMin.getTime())); | |
} | |
} | |
/** | |
* Get the maximum date limit. | |
*/ | |
public Date getDateMax() { | |
return dateMax; | |
} | |
/** | |
* Set the maximum date limit. | |
*/ | |
public void setDateMax(Date dateMax) { | |
this.dateMax = dateMax; | |
if (initialize && dateMax != null) { | |
$(pickatizedDateInput).pickadate("picker").set("max", JsDate.create((double) dateMax.getTime())); | |
} | |
} | |
/** | |
* Set the pickers date. | |
*/ | |
public void setPickerDate(JsDate date, Element picker) { | |
$(picker).pickadate("picker").set("select", date, () -> { | |
DOM.createFieldSet().setPropertyObject("muted", true); | |
}); | |
} | |
/** | |
* Get the pickers date. | |
*/ | |
protected Date getPickerDate() { | |
try { | |
JsDate pickerDate = $(pickatizedDateInput).pickadate("picker").get("select").obj; | |
return new Date((long) pickerDate.getTime()); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
return null; | |
} | |
} | |
public Date getDate() { | |
return getPickerDate(); | |
} | |
/** | |
* Clears the values of the picker field. | |
*/ | |
public void clearValues() { | |
if (pickatizedDateInput != null) { | |
clearValues(pickatizedDateInput); | |
} | |
} | |
public void clearValues(Element picker) { | |
$(picker).pickadate("picker").clear(); | |
} | |
@Override | |
public String getPlaceholder() { | |
return placeholder; | |
} | |
@Override | |
public void setPlaceholder(String placeholder) { | |
this.placeholder = placeholder; | |
if (initialize && placeholder != null) { | |
lblPlaceholder.setText(placeholder); | |
} | |
} | |
/** | |
* Get the pickers selection type. | |
*/ | |
public MaterialDatePickerType getSelectionType() { | |
return selectionType; | |
} | |
/** | |
* Set the pickers selection type. | |
*/ | |
public void setSelectionType(MaterialDatePickerType selectionType) { | |
this.selectionType = selectionType; | |
} | |
/** | |
* @return the orientation | |
*/ | |
@Override | |
public Orientation getOrientation() { | |
return orientationMixin.getCssName(); | |
} | |
/** | |
* @param orientation the orientation to set : can be Vertical or Horizontal | |
*/ | |
@Override | |
public void setOrientation(Orientation orientation) { | |
orientationMixin.setCssName(orientation); | |
} | |
@Override | |
public void setError(String error) { | |
super.setError(error); | |
dateInput.addStyleName(CssName.INVALID); | |
dateInput.removeStyleName(CssName.VALID); | |
} | |
@Override | |
public void setSuccess(String success) { | |
super.setSuccess(success); | |
dateInput.addStyleName(CssName.VALID); | |
dateInput.removeStyleName(CssName.INVALID); | |
} | |
@Override | |
public void clearErrorOrSuccess() { | |
super.clearErrorOrSuccess(); | |
dateInput.removeStyleName(CssName.VALID); | |
dateInput.removeStyleName(CssName.INVALID); | |
} | |
public String getFormat() { | |
return format; | |
} | |
/** | |
* To call before initialization. | |
*/ | |
public void setFormat(String format) { | |
this.format = format; | |
} | |
@Override | |
public Date getValue() { | |
return getPickerDate(); | |
} | |
@Override | |
public void setValue(Date value, boolean fireEvents) { | |
if (value == null) { | |
return; | |
} | |
this.date = value; | |
if (initialize) { | |
setPickerDate(JsDate.create((double) value.getTime()), pickatizedDateInput); | |
label.addStyleName(CssName.ACTIVE); | |
} | |
super.setValue(value, fireEvents); | |
} | |
@Override | |
public HandlerRegistration addCloseHandler(final CloseHandler<MaterialDatePicker> handler) { | |
return addHandler(handler, CloseEvent.getType()); | |
} | |
@Override | |
public HandlerRegistration addOpenHandler(final OpenHandler<MaterialDatePicker> handler) { | |
return addHandler(handler, OpenEvent.getType()); | |
} | |
@Override | |
public void setEnabled(boolean enabled) { | |
super.setEnabled(enabled); | |
dateInput.setEnabled(enabled); | |
} | |
public DatePickerLanguage getLanguage() { | |
return language; | |
} | |
public void setLanguage(DatePickerLanguage language) { | |
this.language = language; | |
if (language.getJs() != null) { | |
ScriptInjector.fromString(language.getJs().getText()).setWindow(ScriptInjector.TOP_WINDOW).inject(); | |
} | |
stop(); | |
reinitialize(); | |
} | |
/** | |
* Re initialize the datepicker. | |
*/ | |
public void reinitialize() { | |
Scheduler.get().scheduleDeferred(() -> { | |
initialize(); | |
if (pickatizedDateInput != null) { | |
if (dateTemp != null) { | |
$(pickatizedDateInput).pickadate("picker").set("select", dateTemp, () -> { | |
DOM.createFieldSet().setPropertyObject("muted", true); | |
}); | |
} | |
} | |
}); | |
} | |
/** | |
* Stop the datepicker instance | |
*/ | |
public void stop() { | |
$(pickatizedDateInput).pickadate("picker").stop(); | |
} | |
protected void start() { | |
$(pickatizedDateInput).pickadate("picker").start(); | |
} | |
@Override | |
public MaterialIcon getIcon() { | |
return icon; | |
} | |
@Override | |
public void setIconType(IconType iconType) { | |
icon.setIconType(iconType); | |
icon.setIconPrefix(true); | |
lblError.setPaddingLeft(44); | |
insert(icon, 0); | |
} | |
@Override | |
public void setIconPosition(IconPosition position) { | |
icon.setIconPosition(position); | |
} | |
@Override | |
public void setIconSize(IconSize size) { | |
icon.setIconSize(size); | |
} | |
@Override | |
public void setIconFontSize(double size, Style.Unit unit) { | |
icon.setIconFontSize(size, unit); | |
} | |
@Override | |
public void setIconColor(Color iconColor) { | |
icon.setIconColor(iconColor); | |
} | |
@Override | |
public void setIconPrefix(boolean prefix) { | |
icon.setIconPrefix(prefix); | |
} | |
@Override | |
public boolean isIconPrefix() { | |
return icon.isIconPrefix(); | |
} | |
@Override | |
protected ErrorMixin<AbstractValueWidget, MaterialLabel> getErrorMixin() { | |
return errorMixin; | |
} | |
public ReadOnlyMixin<MaterialDatePicker, DateInput> getReadOnlyMixin() { | |
if (readOnlyMixin == null) { | |
readOnlyMixin = new ReadOnlyMixin<>(this, dateInput); | |
} | |
return readOnlyMixin; | |
} | |
@Override | |
public void setReadOnly(boolean value) { | |
getReadOnlyMixin().setReadOnly(value); | |
} | |
@Override | |
public boolean isReadOnly() { | |
return getReadOnlyMixin().isReadOnly(); | |
} | |
@Override | |
public void setToggleReadOnly(boolean toggle) { | |
getReadOnlyMixin().setToggleReadOnly(toggle); | |
} | |
@Override | |
public boolean isToggleReadOnly() { | |
return getReadOnlyMixin().isToggleReadOnly(); | |
} | |
public DateInput getDateInput() { | |
return dateInput; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment