All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.user.datepicker.client.DateBox Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * Copyright 2009 Google Inc.
 *
 * 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.google.gwt.user.datepicker.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.editor.client.adapters.TakesValueEditor;
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.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextBox;

import java.util.Date;

/**
 * A text box that shows a {@link DatePicker} when the user focuses on it.
 *
 * 

CSS Style Rules

* *
*
.gwt-DateBox
*
default style name
*
.dateBoxPopup
*
Applied to the popup around the DatePicker
*
.dateBoxFormatError
*
Default style for when the date box has bad input. Applied by * {@link DateBox.DefaultFormat} when the text does not represent a date that * can be parsed
*
* *

*

Example

* {@example com.google.gwt.examples.DateBoxExample} *

*/ public class DateBox extends Composite implements HasEnabled, HasValue, IsEditor> { /** * Default {@link DateBox.Format} class. The date is first parsed using the * {@link DateTimeFormat} supplied by the user, or * {@link PredefinedFormat#DATE_TIME_MEDIUM} by default. *

* If that fails, we then try to parse again using the default browser date * parsing. *

* If that fails, the dateBoxFormatError css style is applied to * the {@link DateBox}. The style will be removed when either a successful * {@link #parse(DateBox,String, boolean)} is called or * {@link #format(DateBox,Date)} is called. *

* Use a different {@link DateBox.Format} instance to change that behavior. *

*/ public static class DefaultFormat implements Format { private final DateTimeFormat dateTimeFormat; /** * Creates a new default format instance. */ @SuppressWarnings("deprecation") public DefaultFormat() { dateTimeFormat = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM); } /** * Creates a new default format instance. * * @param dateTimeFormat the {@link DateTimeFormat} to use with this * {@link Format}. */ public DefaultFormat(DateTimeFormat dateTimeFormat) { this.dateTimeFormat = dateTimeFormat; } public String format(DateBox box, Date date) { if (date == null) { return ""; } else { return dateTimeFormat.format(date); } } /** * Gets the date time format. * * @return the date time format */ public DateTimeFormat getDateTimeFormat() { return dateTimeFormat; } @SuppressWarnings("deprecation") public Date parse(DateBox dateBox, String dateText, boolean reportError) { Date date = null; try { if (dateText.length() > 0) { date = dateTimeFormat.parse(dateText); } } catch (IllegalArgumentException exception) { try { date = new Date(dateText); // We have parsed the text at higher resolution so do a round trip to get rid of extra: date = dateTimeFormat.parse(dateTimeFormat.format(date)); } catch (IllegalArgumentException e) { if (reportError) { dateBox.addStyleName(DATE_BOX_FORMAT_ERROR); } return null; } } return date; } public void reset(DateBox dateBox, boolean abandon) { dateBox.removeStyleName(DATE_BOX_FORMAT_ERROR); } } /** * Implemented by a delegate to handle the parsing and formating of date * values. The default {@link Format} uses a new {@link DefaultFormat} * instance. */ public interface Format { /** * Formats the provided date. Note, a null date is a possible input. * * @param dateBox the date box you are formatting * @param date the date to format * @return the formatted date as a string */ String format(DateBox dateBox, Date date); /** * Parses the provided string as a date. * * @param dateBox the date box * @param text the string representing a date * @param reportError should the formatter indicate a parse error to the * user? * @return the date created, or null if there was a parse error */ Date parse(DateBox dateBox, String text, boolean reportError); /** * If the format did any modifications to the date box's styling, reset them * now. * * @param abandon true when the current format is being replaced by another * @param dateBox the date box */ void reset(DateBox dateBox, boolean abandon); } private class DateBoxHandler implements ValueChangeHandler, FocusHandler, BlurHandler, ClickHandler, KeyDownHandler, CloseHandler { public void onBlur(BlurEvent event) { if (isDatePickerShowing() == false) { updateDateFromTextBox(); } } public void onClick(ClickEvent event) { showDatePicker(); } public void onClose(CloseEvent event) { // If we are not closing because we have picked a new value, make sure the // current value is updated. if (allowDPShow) { updateDateFromTextBox(); } } public void onFocus(FocusEvent event) { if (allowDPShow && isDatePickerShowing() == false) { showDatePicker(); } } 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; } } public void onValueChange(ValueChangeEvent event) { setValue(parseDate(false), normalize(event.getValue()), true, true); hideDatePicker(); preventDatePickerPopup(); box.setFocus(true); } // Round trips on render & parse to convert the date to our interpretation based on the format // See issue https://code.google.com/p/google-web-toolkit/issues/detail?id=4785 private Date normalize(Date date) { DateBox dateBox = DateBox.this; return getFormat().parse(dateBox, getFormat().format(dateBox, date), false); } } /** * Default style name added when the date box has a format error. */ private static final String DATE_BOX_FORMAT_ERROR = "dateBoxFormatError"; /** * Default style name. */ public static final String DEFAULT_STYLENAME = "gwt-DateBox"; private static final DefaultFormat DEFAULT_FORMAT = GWT.create(DefaultFormat.class); private final PopupPanel popup; private final TextBox box = new TextBox(); private final DatePicker picker; private LeafValueEditor editor; private Format format; private boolean allowDPShow = true; private boolean fireNullValues = false; /** * Create a date box with a new {@link DatePicker}. */ public DateBox() { this(new DatePicker(), null, DEFAULT_FORMAT); } /** * Create a new date box. * * @param date the default date. * @param picker the picker to drop down from the date box * @param format to use to parse and format dates */ public DateBox(DatePicker picker, Date date, Format format) { this.picker = picker; this.popup = new PopupPanel(true); assert format != null : "You may not construct a date box with a null format"; this.format = format; popup.addAutoHidePartner(box.getElement()); popup.setWidget(picker); popup.setStyleName("dateBoxPopup"); initWidget(box); setStyleName(DEFAULT_STYLENAME); DateBoxHandler handler = new DateBoxHandler(); picker.addValueChangeHandler(handler); box.addFocusHandler(handler); box.addBlurHandler(handler); box.addClickHandler(handler); box.addKeyDownHandler(handler); box.setDirectionEstimator(false); popup.addCloseHandler(handler); setValue(date); } public HandlerRegistration addValueChangeHandler( ValueChangeHandler handler) { return addHandler(handler, ValueChangeEvent.getType()); } /** * Returns a {@link TakesValueEditor} backed by the DateBox. */ public LeafValueEditor asEditor() { if (editor == null) { editor = TakesValueEditor.of(this); } return editor; } /** * Gets the current cursor position in the date box. * * @return the cursor position * */ public int getCursorPos() { return box.getCursorPos(); } /** * Gets the date picker. * * @return the date picker */ public DatePicker getDatePicker() { return picker; } /** * Returns true iff the date box will fire {@code ValueChangeEvents} with a * date value of {@code null} for invalid or empty string values. */ public boolean getFireNullValues() { return fireNullValues; } /** * Gets the format instance used to control formatting and parsing of this * {@link DateBox}. * * @return the format */ public Format getFormat() { return this.format; } /** * Gets the date box's position in the tab index. * * @return the date box's tab index */ public int getTabIndex() { return box.getTabIndex(); } /** * Get text box. * * @return the text box used to enter the formatted date */ public TextBox getTextBox() { return box; } /** * Get the date displayed, or null if the text box is empty, or cannot be * interpreted. * * @return the current date value */ public Date getValue() { return parseDate(true); } /** * Hide the date picker. */ public void hideDatePicker() { popup.hide(); } /** * Returns true if date picker is currently showing, false if not. */ public boolean isDatePickerShowing() { return popup.isShowing(); } /** * Returns true if the date box is enabled, false if not. */ public boolean isEnabled() { return box.isEnabled(); } /** * Sets the date box's 'access key'. This key is used (in conjunction with a * browser-specific modifier key) to automatically focus the widget. * * @param key the date box's access key */ public void setAccessKey(char key) { box.setAccessKey(key); } /** * Sets whether the date box is enabled. * * @param enabled is the box enabled */ public void setEnabled(boolean enabled) { box.setEnabled(enabled); } /** * Sets whether or not the date box will fire {@code ValueChangeEvents} with a * date value of {@code null} for invalid or empty string values. */ public void setFireNullValues(boolean fireNullValues) { this.fireNullValues = fireNullValues; } /** * Explicitly focus/unfocus this widget. Only one widget can have focus at a * time, and the widget that does will receive all keyboard events. * * @param focused whether this widget should take focus or release it */ public void setFocus(boolean focused) { box.setFocus(focused); } /** * 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(Format format) { assert format != null : "A Date box may not have a null format"; if (this.format != format) { Date date = getValue(); // This call lets the formatter do whatever other clean up is required to // switch formatters. // this.format.reset(this, true); // Now update the format and show the current date using the new format. this.format = format; setValue(date); } } /** * Sets the date box's position in the tab index. If more than one widget has * the same tab index, each such widget will receive focus in an arbitrary * order. Setting the tab index to -1 will cause this widget to * be removed from the tab order. * * @param index the date box's tab index */ public void setTabIndex(int index) { box.setTabIndex(index); } /** * Set the date. */ public void setValue(Date date) { setValue(date, false); } public void setValue(Date date, boolean fireEvents) { setValue(picker.getValue(), date, fireEvents, true); } /** * Parses the current date box's value and shows that date. */ public void showDatePicker() { Date current = parseDate(false); if (current == null) { current = new Date(); } picker.setCurrentMonth(current); popup.showRelativeTo(this); } private Date parseDate(boolean reportError) { if (reportError) { getFormat().reset(this, false); } String text = box.getText().trim(); return getFormat().parse(this, text, reportError); } private void preventDatePickerPopup() { allowDPShow = false; Scheduler.get().scheduleDeferred(new ScheduledCommand() { public void execute() { allowDPShow = true; } }); } private void setValue(Date oldDate, Date date, boolean fireEvents, boolean updateText) { if (date != null) { picker.setCurrentMonth(date); } picker.setValue(date, false); if (updateText) { format.reset(this, false); box.setText(getFormat().format(this, date)); } if (fireEvents) { DateChangeEvent.fireIfNotEqualDates(this, oldDate, date); } } private void updateDateFromTextBox() { Date parsedDate = parseDate(true); if (fireNullValues || (parsedDate != null)) { setValue(picker.getValue(), parsedDate, true, false); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy