/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.eas.widgets.boxes; import java.util.Date; import com.eas.core.XElement; import com.eas.ui.CommonResources; import com.eas.ui.HasDecorations; import com.eas.ui.HasDecorationsWidth; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.editor.client.IsEditor; import com.google.gwt.editor.client.LeafValueEditor; 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.HasAllKeyHandlers; import com.google.gwt.event.dom.client.HasBlurHandlers; import com.google.gwt.event.dom.client.HasFocusHandlers; import com.google.gwt.event.dom.client.HasKeyDownHandlers; import com.google.gwt.event.dom.client.HasKeyPressHandlers; import com.google.gwt.event.dom.client.HasKeyUpHandlers; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; 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.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Focusable; import com.google.gwt.user.client.ui.HasName; import com.google.gwt.user.client.ui.HasText; import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.datepicker.client.CalendarUtil; import com.google.gwt.user.datepicker.client.DateBox; /** * * @author mg */ public class DateTimeBox extends Composite implements RequiresResize, HasValue<Date>, HasText, HasValueChangeHandlers<Date>, IsEditor<LeafValueEditor<Date>>, Focusable, HasAllKeyHandlers, HasFocusHandlers, HasBlurHandlers, HasDecorations, HasDecorationsWidth, HasName { private static final DateBox.DefaultFormat DEFAULT_FORMAT = GWT.create(DateBox.DefaultFormat.class); protected FlowPanel container = new FlowPanel(); protected DateBox field; protected SimplePanel right = new SimplePanel(); protected int decorationsWidth; protected PopupPanel popup = new PopupPanel() { @Override public void setPopupPosition(int popupLeft, int popupTop) { super.setPopupPosition(popupLeft, popupTop); if (datePicker != null) { int rightAbsoluteLeft = right.getElement().getAbsoluteLeft(); datePicker.shown(rightAbsoluteLeft - popupLeft <= 30); } } }; private TextBox box; private DateTimePicker datePicker; private TimePicker timePicker; private Date value; protected boolean settingValueFromJs; protected boolean settingValueToJs; protected boolean dateShown = true; protected boolean timeShown = true; protected AutoCloseBox autoCloseParent; public DateTimeBox() { this(new DateTimePicker(), null, DEFAULT_FORMAT); } public DateTimeBox(DateTimePicker aPicker, Date date, DateBox.Format format) { initWidget(container); datePicker = aPicker; timePicker = aPicker.getTimePicker(); container.getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK); container.getElement().getStyle().setPosition(Style.Position.RELATIVE); container.getElement().addClassName("date-time-field"); field = new CustomDateBox(datePicker, date, format); field.setFireNullValues(true); field.setStyleName("form-control"); box = field.getTextBox(); box.getElement().getStyle().setOutlineStyle(Style.OutlineStyle.NONE); field.addValueChangeHandler(new ValueChangeHandler<Date>() { @Override public void onValueChange(ValueChangeEvent<Date> event) { Date newValue = event.getValue(); if (value == null ? newValue != null : !value.equals(newValue)) { value = newValue; timePicker.setValue(value, false); datePicker.setValue(value, false); ValueChangeEvent.fire(DateTimeBox.this, newValue); } } }); datePicker.addValueChangeHandler(new ValueChangeHandler<Date>() { @Override public void onValueChange(ValueChangeEvent<Date> event) { Date datePart = event.getValue(); Date timePart = timePicker.getValue(); if (value == null && (new Date(0)).equals(timePart)) { Date currentTime = new Date(); Date currentDate = new Date(currentTime.getTime()); CalendarUtil.resetTime(currentDate); timePart = new Date(currentTime.getTime() - currentDate.getTime()); } Date newValue; if (timePart == null) { newValue = datePart; } else { newValue = new Date(datePart.getTime() + timePart.getTime()); } if (value == null ? newValue != null : !value.equals(newValue)) { value = newValue; field.setValue(value, false); timePicker.setValue(value, false); ValueChangeEvent.fire(DateTimeBox.this, newValue); } } }); timePicker.addValueChangeHandler(new ValueChangeHandler<Date>() { @Override public void onValueChange(ValueChangeEvent<Date> event) { Date timePart = timePicker.getValue(); Date datePart = field.getValue(); CalendarUtil.resetTime(datePart); value = new Date(datePart.getTime() + timePart.getTime()); field.setValue(value, false); datePicker.setValue(value, false); ValueChangeEvent.fire(DateTimeBox.this, value); } }); CommonResources.INSTANCE.commons().ensureInjected(); field.getElement().addClassName(CommonResources.INSTANCE.commons().borderSized()); field.getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK); field.getElement().getStyle().setPosition(Style.Position.ABSOLUTE); field.getElement().getStyle().setTop(0, Style.Unit.PX); field.getElement().getStyle().setHeight(100, Style.Unit.PCT); field.getElement().getStyle().setBottom(0, Style.Unit.PX); field.getElement().getStyle().setLeft(0, Style.Unit.PX); field.getElement().getStyle().setWidth(100, Style.Unit.PCT); field.getElement().getStyle().setMargin(0, Style.Unit.PX); field.getElement().getStyle().setBackgroundColor("inherit"); field.getElement().getStyle().setColor("inherit"); field.getElement().addClassName("date-time-box"); right.getElement().addClassName("date-select"); right.getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK); right.getElement().getStyle().setHeight(100, Style.Unit.PCT); right.getElement().getStyle().setPosition(Style.Position.RELATIVE); CommonResources.INSTANCE.commons().ensureInjected(); right.getElement().addClassName(CommonResources.INSTANCE.commons().unselectable()); popup.setStyleName("date-box-popup"); popup.setAutoHideEnabled(true); container.add(field); container.add(right); right.addDomHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (!isReadonly()) { datePicker.setCurrentMonth(value != null ? value : new Date()); popup.setWidget(datePicker); popup.showRelativeTo(right); } } }, ClickEvent.getType()); redecorate(); getElement().<XElement> cast().addResizingTransitionEnd(this); if (field.getTextBox() instanceof HasKeyDownHandlers) { ((HasKeyDownHandlers) field.getTextBox()).addKeyDownHandler(new KeyDownHandler() { @Override public void onKeyDown(KeyDownEvent event) { KeyDownEvent.fireNativeEvent(event.getNativeEvent(), DateTimeBox.this); } }); } if (field.getTextBox() instanceof HasKeyUpHandlers) { ((HasKeyUpHandlers) field.getTextBox()).addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { KeyUpEvent.fireNativeEvent(event.getNativeEvent(), DateTimeBox.this); } }); } if (field.getTextBox() instanceof HasKeyPressHandlers) { ((HasKeyPressHandlers) field.getTextBox()).addKeyPressHandler(new KeyPressHandler() { @Override public void onKeyPress(KeyPressEvent event) { KeyPressEvent.fireNativeEvent(event.getNativeEvent(), DateTimeBox.this); } }); } if (field.getTextBox() instanceof HasFocusHandlers) { ((HasFocusHandlers) field.getTextBox()).addFocusHandler(new FocusHandler() { @Override public void onFocus(FocusEvent event) { FocusEvent.fireNativeEvent(event.getNativeEvent(), DateTimeBox.this); } }); } if (field.getTextBox() instanceof HasBlurHandlers) { ((HasBlurHandlers) field.getTextBox()).addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent event) { BlurEvent.fireNativeEvent(event.getNativeEvent(), DateTimeBox.this); } }); } changeViewPresentation(); } public boolean isDateVisible() { return dateShown; } public void setDateVisible(boolean value) { dateShown = value; changeViewPresentation(); } public boolean isTimeVisible() { return timeShown; } public void setTimeVisible(boolean value) { timeShown = value; changeViewPresentation(); } private void changeViewPresentation() { if (dateShown && timeShown) { right.getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK); datePicker.setDateAndTimeView(); right.getElement().removeClassName("time-select"); right.getElement().addClassName("date-select"); redecorate(); } else if (dateShown) { right.getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK); datePicker.setDateView(); right.getElement().removeClassName("time-select"); right.getElement().addClassName("date-select"); redecorate(); } else if (timeShown) { right.getElement().getStyle().setDisplay(Style.Display.INLINE_BLOCK); datePicker.setTimeView(); right.getElement().removeClassName("date-select"); right.getElement().addClassName("time-select"); redecorate(); } else { right.getElement().getStyle().setDisplay(Display.NONE); redecorate(); } } @Override public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) { return super.addHandler(handler, KeyDownEvent.getType()); } @Override public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) { return super.addHandler(handler, KeyPressEvent.getType()); } public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) { return super.addHandler(handler, KeyUpEvent.getType()); } @Override public HandlerRegistration addFocusHandler(FocusHandler handler) { return addHandler(handler, FocusEvent.getType()); } @Override public HandlerRegistration addBlurHandler(BlurHandler handler) { return addHandler(handler, BlurEvent.getType()); } @Override public void setDecorationsWidth(int aDecorationsWidth) { decorationsWidth = aDecorationsWidth; redecorate(); } @Override public HasWidgets getContainer() { return container; } protected void redecorate() { if (isAttached()) { int paddingRight = right.getElement().getOffsetWidth() + decorationsWidth; field.getElement().getStyle().setPaddingRight(paddingRight, Style.Unit.PX); } } @Override public void setFocus(boolean focused) { field.setFocus(focused); } @Override public void setAccessKey(char key) { field.setAccessKey(key); } @Override public int getTabIndex() { return field.getTabIndex(); } @Override public void setTabIndex(int index) { field.setTabIndex(index); } @Override public Date getValue() { return value; } @Override public void setValue(Date value) { setValue(value, false); } @Override public void setValue(Date aValue, boolean fireEvents) { if (value == null ? aValue != null : !value.equals(aValue)) { value = aValue; field.setValue(aValue, false); timePicker.setValue(value, false); datePicker.setValue(value, false); if (fireEvents) { ValueChangeEvent.fire(DateTimeBox.this, value); } } } public String getText() { return field.getTextBox().getText(); } @Override public void setText(String text) { Date newValue = field.getFormat().parse(field, text, false); if (newValue != null) { setValue(newValue, true); } } @Override public String getName() { return box.getName(); } @Override public void setName(String name) { box.setName(name); } /** * Gets the format instance used to control formatting and parsing of this * {@link DateBox}. * * @return the format */ public DateBox.Format getFormat() { return field.getFormat(); } /** * Sets the format used to control formatting and parsing of dates in this * {@link DateBox}. If this {@link DateBox} is not empty, the contents of * date box will be replaced with current contents in the new format. * * @param format * the new date format */ public void setFormat(DateBox.Format format) { field.setFormat(format); } @Override public LeafValueEditor<Date> asEditor() { return field.asEditor(); } @Override public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Date> handler) { return addHandler(handler, ValueChangeEvent.getType()); } @Override public void onResize() { redecorate(); } @Override protected void onAttach() { super.onAttach(); redecorate(); Widget lParent = getParent(); while (lParent != null && !(lParent instanceof AutoCloseBox)) { lParent = lParent.getParent(); } if (lParent instanceof AutoCloseBox) autoCloseParent = (AutoCloseBox) lParent; if (autoCloseParent != null) { autoCloseParent.addAutoHidePartner(popup.getElement()); } } @Override protected void onDetach() { if (autoCloseParent != null) { autoCloseParent.removeAutoHidePartner(popup.getElement()); } super.onDetach(); } public void setReadonly(boolean aValue) { box.getElement().setPropertyBoolean("readOnly", aValue); } public boolean isReadonly() { return box.getElement().getPropertyBoolean("readOnly"); } }