I think DateFieldWidget is a good user experience for input date value,but it will more better if it can show a DatePicker like DateBox, So I stole some DateBox's code to make up a DateFieldPickerWidget, here is the class.
import java.util.Date;
import org.gwtiger.client.widget.field.DateFieldWidget;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.datepicker.client.CalendarUtil;
import com.google.gwt.user.datepicker.client.DatePicker;
public class DateFieldPickerWidget extends DateFieldWidget implements HasValue<Date> {
private final PopupPanel popup = new PopupPanel();
private final DatePicker picker = new DatePicker();
private boolean allowDPShow = true;
public DateFieldPickerWidget(String labelText) {
super(labelText);
popup.setAutoHideEnabled(true);
popup.addAutoHidePartner(textBox.getElement());
popup.setWidget(picker);
popup.setStyleName("dateBoxPopup");
DateBoxHandler handler = new DateBoxHandler();
picker.addValueChangeHandler(handler);
textBox.addFocusHandler(handler);
textBox.addBlurHandler(handler);
textBox.addClickHandler(handler);
textBox.addKeyDownHandler(handler);
popup.addCloseHandler(handler);
}
public DatePicker getDatePicker() {
return picker;
}
public void hideDatePicker() {
popup.hide();
}
public boolean isDatePickerShowing() {
return popup.isShowing();
}
public void showDatePicker() {
Date current = validate()?getDate():null;
if (current == null) {
current = new Date();
}
picker.setCurrentMonth(current);
popup.showRelativeTo(this);
}
private void preventDatePickerPopup() {
allowDPShow = false;
DeferredCommand.addCommand(new Command() {
public void execute() {
allowDPShow = true;
}
});
}
private void setValue(Date oldDate, Date date, boolean fireEvents) {
if (date != null) {
picker.setCurrentMonth(date);
}
picker.setValue(date, false);
super.setDate(date);
if (fireEvents) {
DateChangeEvent.fireIfNotEqualDates(this, oldDate, date);
}
}
private void updateDateFromTextBox() {
validate();
}
@Override
public HandlerRegistration addValueChangeHandler(
ValueChangeHandler<Date> handler) {
return addHandler(handler, ValueChangeEvent.getType());
}
@Override
public Date getValue() {
return super.getDate();
}
@Override
public void setValue(Date date, boolean fireEvents) {
setValue(picker.getValue(), date, fireEvents);
}
@Override
public void setValue(Date date) {
setValue(date, false);
}
public static class DateChangeEvent extends ValueChangeEvent<Date> {
protected DateChangeEvent(Date value) {
super(CalendarUtil.copyDate(value));
}
public static <S extends HasValueChangeHandlers<Date> & HasHandlers> void fireIfNotEqualDates(
S source, Date oldValue, Date newValue) {
if (ValueChangeEvent.shouldFire(source, oldValue, newValue)) {
source.fireEvent(new DateChangeEvent(newValue));
}
}
@Override
public Date getValue() {
return CalendarUtil.copyDate(super.getValue());
}
}
private class DateBoxHandler implements ValueChangeHandler<Date>,FocusHandler, BlurHandler,
ClickHandler, KeyDownHandler,CloseHandler<PopupPanel> {
@Override
public void onValueChange(ValueChangeEvent<Date> event) {
setValue(validate()?getDate():null, event.getValue(),true);
hideDatePicker();
preventDatePickerPopup();
textBox.setFocus(true);
}
@Override
public void onClick(ClickEvent event) {
showDatePicker();
}
@Override
public void onKeyDown(KeyDownEvent event) {
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_ENTER:
case KeyCodes.KEY_TAB:
updateDateFromTextBox();
// Deliberate fall through
case KeyCodes.KEY_ESCAPE:
case KeyCodes.KEY_UP:
hideDatePicker();
break;
case KeyCodes.KEY_DOWN:
showDatePicker();
break;
}
}
@Override
public void onBlur(BlurEvent event) {
if (isDatePickerShowing() == false) {
updateDateFromTextBox();
}
}
@Override
public void onClose(CloseEvent<PopupPanel> event) {
if (allowDPShow) {
updateDateFromTextBox();
}
}
@Override
public void onFocus(FocusEvent event) {
if (allowDPShow && isDatePickerShowing() == false) {
showDatePicker();
}
}
}
}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think DateFieldWidget is a good user experience for input date value,but it will more better if it can show a DatePicker like DateBox, So I stole some DateBox's code to make up a DateFieldPickerWidget, here is the class.
import java.util.Date;
import org.gwtiger.client.widget.field.DateFieldWidget;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.datepicker.client.CalendarUtil;
import com.google.gwt.user.datepicker.client.DatePicker;
public class DateFieldPickerWidget extends DateFieldWidget implements HasValue<Date> {
private final PopupPanel popup = new PopupPanel();
private final DatePicker picker = new DatePicker();
private boolean allowDPShow = true;
public DateFieldPickerWidget(String labelText) {
super(labelText);
popup.setAutoHideEnabled(true);
popup.addAutoHidePartner(textBox.getElement());
popup.setWidget(picker);
popup.setStyleName("dateBoxPopup");
DateBoxHandler handler = new DateBoxHandler();
picker.addValueChangeHandler(handler);
textBox.addFocusHandler(handler);
textBox.addBlurHandler(handler);
textBox.addClickHandler(handler);
textBox.addKeyDownHandler(handler);
popup.addCloseHandler(handler);
}
public DatePicker getDatePicker() {
return picker;
}
public void hideDatePicker() {
popup.hide();
}
public boolean isDatePickerShowing() {
return popup.isShowing();
}
public void showDatePicker() {
Date current = validate()?getDate():null;
if (current == null) {
current = new Date();
}
picker.setCurrentMonth(current);
popup.showRelativeTo(this);
}
private void preventDatePickerPopup() {
allowDPShow = false;
DeferredCommand.addCommand(new Command() {
public void execute() {
allowDPShow = true;
}
});
}
private void setValue(Date oldDate, Date date, boolean fireEvents) {
if (date != null) {
picker.setCurrentMonth(date);
}
picker.setValue(date, false);
super.setDate(date);
if (fireEvents) {
DateChangeEvent.fireIfNotEqualDates(this, oldDate, date);
}
}
private void updateDateFromTextBox() {
validate();
}
@Override
public HandlerRegistration addValueChangeHandler(
ValueChangeHandler<Date> handler) {
return addHandler(handler, ValueChangeEvent.getType());
}
@Override
public Date getValue() {
return super.getDate();
}
@Override
public void setValue(Date date, boolean fireEvents) {
setValue(picker.getValue(), date, fireEvents);
}
@Override
public void setValue(Date date) {
setValue(date, false);
}
public static class DateChangeEvent extends ValueChangeEvent<Date> {
protected DateChangeEvent(Date value) {
super(CalendarUtil.copyDate(value));
}
public static <S extends HasValueChangeHandlers<Date> & HasHandlers> void fireIfNotEqualDates(
S source, Date oldValue, Date newValue) {
if (ValueChangeEvent.shouldFire(source, oldValue, newValue)) {
source.fireEvent(new DateChangeEvent(newValue));
}
}
@Override
public Date getValue() {
return CalendarUtil.copyDate(super.getValue());
}
}
private class DateBoxHandler implements ValueChangeHandler<Date>,FocusHandler, BlurHandler,
ClickHandler, KeyDownHandler,CloseHandler<PopupPanel> {
@Override
public void onValueChange(ValueChangeEvent<Date> event) {
setValue(validate()?getDate():null, event.getValue(),true);
hideDatePicker();
preventDatePickerPopup();
textBox.setFocus(true);
}
@Override
public void onClick(ClickEvent event) {
showDatePicker();
}
@Override
public void onKeyDown(KeyDownEvent event) {
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_ENTER:
case KeyCodes.KEY_TAB:
updateDateFromTextBox();
// Deliberate fall through
case KeyCodes.KEY_ESCAPE:
case KeyCodes.KEY_UP:
hideDatePicker();
break;
case KeyCodes.KEY_DOWN:
showDatePicker();
break;
}
}
@Override
public void onBlur(BlurEvent event) {
if (isDatePickerShowing() == false) {
updateDateFromTextBox();
}
}
@Override
public void onClose(CloseEvent<PopupPanel> event) {
if (allowDPShow) {
updateDateFromTextBox();
}
}
@Override
public void onFocus(FocusEvent event) {
if (allowDPShow && isDatePickerShowing() == false) {
showDatePicker();
}
}
}
}