123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- /*
- @ITMillApache2LicenseForJavaFiles@
- */
-
- package com.vaadin.terminal.gwt.client.ui;
-
- import com.google.gwt.event.dom.client.BlurEvent;
- import com.google.gwt.event.dom.client.BlurHandler;
- import com.google.gwt.event.dom.client.ChangeEvent;
- import com.google.gwt.event.dom.client.ChangeHandler;
- import com.google.gwt.event.dom.client.FocusEvent;
- import com.google.gwt.event.dom.client.FocusHandler;
- import com.google.gwt.i18n.client.DateTimeFormat;
- import com.google.gwt.user.client.DOM;
- import com.google.gwt.user.client.ui.TextBox;
- import com.vaadin.terminal.gwt.client.ApplicationConnection;
- import com.vaadin.terminal.gwt.client.BrowserInfo;
- import com.vaadin.terminal.gwt.client.ClientExceptionHandler;
- import com.vaadin.terminal.gwt.client.ContainerResizedListener;
- import com.vaadin.terminal.gwt.client.EventId;
- import com.vaadin.terminal.gwt.client.Focusable;
- import com.vaadin.terminal.gwt.client.LocaleNotLoadedException;
- import com.vaadin.terminal.gwt.client.LocaleService;
- import com.vaadin.terminal.gwt.client.Paintable;
- import com.vaadin.terminal.gwt.client.UIDL;
-
- public class VTextualDate extends VDateField implements Paintable, Field,
- ChangeHandler, ContainerResizedListener, Focusable {
-
- private static final String PARSE_ERROR_CLASSNAME = CLASSNAME
- + "-parseerror";
-
- private final TextBox text;
-
- private String formatStr;
-
- private String width;
-
- private boolean needLayout;
-
- protected int fieldExtraWidth = -1;
-
- private boolean lenient;
-
- private static final String CLASSNAME_PROMPT = "prompt";
- private static final String ATTR_INPUTPROMPT = "prompt";
- private String inputPrompt = "";
- private boolean prompting = false;
-
- public VTextualDate() {
-
- super();
- text = new TextBox();
- // use normal textfield styles as a basis
- text.setStyleName(VTextField.CLASSNAME);
- // add datefield spesific style name also
- text.addStyleName(CLASSNAME + "-textfield");
- text.addChangeHandler(this);
- text.addFocusHandler(new FocusHandler() {
- public void onFocus(FocusEvent event) {
- text.addStyleName(VTextField.CLASSNAME + "-"
- + VTextField.CLASSNAME_FOCUS);
- if (prompting) {
- text.setText("");
- setPrompting(false);
- }
- if (getClient() != null
- && getClient().hasEventListeners(VTextualDate.this,
- EventId.FOCUS)) {
- getClient()
- .updateVariable(getId(), EventId.FOCUS, "", true);
- }
- }
- });
- text.addBlurHandler(new BlurHandler() {
- public void onBlur(BlurEvent event) {
- text.removeStyleName(VTextField.CLASSNAME + "-"
- + VTextField.CLASSNAME_FOCUS);
- String value = getText();
- setPrompting(inputPrompt != null
- && (value == null || "".equals(value)));
- if (prompting) {
- text.setText(readonly ? "" : inputPrompt);
- }
- if (getClient() != null
- && getClient().hasEventListeners(VTextualDate.this,
- EventId.BLUR)) {
- getClient().updateVariable(getId(), EventId.BLUR, "", true);
- }
- }
- });
- add(text);
- }
-
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- int origRes = currentResolution;
- String oldLocale = currentLocale;
- super.updateFromUIDL(uidl, client);
- if (origRes != currentResolution || oldLocale != currentLocale) {
- // force recreating format string
- formatStr = null;
- }
- if (uidl.hasAttribute("format")) {
- formatStr = uidl.getStringAttribute("format");
- }
-
- inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT);
-
- lenient = !uidl.getBooleanAttribute("strict");
-
- buildDate();
- // not a FocusWidget -> needs own tabindex handling
- if (uidl.hasAttribute("tabindex")) {
- text.setTabIndex(uidl.getIntAttribute("tabindex"));
- }
-
- if (readonly) {
- text.addStyleDependentName("readonly");
- } else {
- text.removeStyleDependentName("readonly");
- }
-
- }
-
- protected String getFormatString() {
- if (formatStr == null) {
- if (currentResolution == RESOLUTION_YEAR) {
- formatStr = "yyyy"; // force full year
- } else {
-
- try {
- String frmString = LocaleService
- .getDateFormat(currentLocale);
- frmString = cleanFormat(frmString);
- String delim = LocaleService
- .getClockDelimiter(currentLocale);
-
- if (currentResolution >= RESOLUTION_HOUR) {
- if (dts.isTwelveHourClock()) {
- frmString += " hh";
- } else {
- frmString += " HH";
- }
- if (currentResolution >= RESOLUTION_MIN) {
- frmString += ":mm";
- if (currentResolution >= RESOLUTION_SEC) {
- frmString += ":ss";
- if (currentResolution >= RESOLUTION_MSEC) {
- frmString += ".SSS";
- }
- }
- }
- if (dts.isTwelveHourClock()) {
- frmString += " aaa";
- }
-
- }
-
- formatStr = frmString;
- } catch (LocaleNotLoadedException e) {
- ClientExceptionHandler.displayError(e);
- }
- }
- }
- return formatStr;
- }
-
- /**
- *
- */
- protected void buildDate() {
- removeStyleName(PARSE_ERROR_CLASSNAME);
- // Create the initial text for the textfield
- String dateText;
- if (date != null) {
- String formatStr = getFormatString();
-
- /*
- * Check if format contains the month name. If it does we need to
- * manually convert it to the month name since DateTimeFormat.format
- * always uses the current locale and will replace the month name
- * wrong if current locale is different from the locale set for the
- * DateField. Does not support abbreviated month names.
- */
- if (formatStr.contains("MMM")) {
- String monthName = getDateTimeService().getMonth(
- date.getMonth());
- if (monthName != null) {
- // Capitalize month name
- monthName = Character.toUpperCase(monthName.charAt(0))
- + monthName.substring(1);
-
- /*
- * Replace all month occurrences with the month name. All
- * strings with 3 or more M's are converted to the month
- * name as defined in
- * http://www.docjar.com/docs/api/com/google
- * /gwt/i18n/client/DateTimeFormat.html
- */
- formatStr = formatStr.replaceAll("[M]{3,}", "'" + monthName
- + "'");
- }
- }
-
- DateTimeFormat format = DateTimeFormat.getFormat(formatStr);
- dateText = format.format(date);
- } else {
- dateText = "";
- }
-
- setText(dateText);
- text.setEnabled(enabled);
- text.setReadOnly(readonly);
-
- if (readonly) {
- text.addStyleName("v-readonly");
- } else {
- text.removeStyleName("v-readonly");
- }
-
- }
-
- protected void setPrompting(boolean prompting) {
- this.prompting = prompting;
- if (prompting) {
- addStyleDependentName(CLASSNAME_PROMPT);
- } else {
- removeStyleDependentName(CLASSNAME_PROMPT);
- }
- }
-
- public void onChange(ChangeEvent event) {
- if (!text.getText().equals("")) {
- try {
- DateTimeFormat format = DateTimeFormat
- .getFormat(getFormatString());
- if (lenient) {
- date = format.parse(text.getText());
- if (date != null) {
- // if date value was leniently parsed, normalize text
- // presentation
- text.setValue(
- DateTimeFormat.getFormat(getFormatString())
- .format(date), false);
- }
- } else {
- date = format.parseStrict(text.getText());
- }
-
- long stamp = date.getTime();
- if (stamp == 0) {
- // If date parsing fails in firefox the stamp will be 0
- date = null;
- addStyleName(PARSE_ERROR_CLASSNAME);
- } else {
- // remove possibly added invalid value indication
- removeStyleName(PARSE_ERROR_CLASSNAME);
- }
- } catch (final Exception e) {
- ClientExceptionHandler.displayError(e.getMessage());
-
- addStyleName(PARSE_ERROR_CLASSNAME);
- // this is a hack that may eventually be removed
- getClient().updateVariable(getId(), "lastInvalidDateString",
- text.getText(), false);
- date = null;
- }
- } else {
- date = null;
- // remove possibly added invalid value indication
- removeStyleName(PARSE_ERROR_CLASSNAME);
- }
- // always send the date string
- getClient()
- .updateVariable(getId(), "dateString", text.getText(), false);
-
- // Update variables
- // (only the smallest defining resolution needs to be
- // immediate)
- getClient().updateVariable(getId(), "year",
- date != null ? date.getYear() + 1900 : -1,
- currentResolution == VDateField.RESOLUTION_YEAR && immediate);
- if (currentResolution >= VDateField.RESOLUTION_MONTH) {
- getClient().updateVariable(
- getId(),
- "month",
- date != null ? date.getMonth() + 1 : -1,
- currentResolution == VDateField.RESOLUTION_MONTH
- && immediate);
- }
- if (currentResolution >= VDateField.RESOLUTION_DAY) {
- getClient()
- .updateVariable(
- getId(),
- "day",
- date != null ? date.getDate() : -1,
- currentResolution == VDateField.RESOLUTION_DAY
- && immediate);
- }
- if (currentResolution >= VDateField.RESOLUTION_HOUR) {
- getClient().updateVariable(
- getId(),
- "hour",
- date != null ? date.getHours() : -1,
- currentResolution == VDateField.RESOLUTION_HOUR
- && immediate);
- }
- if (currentResolution >= VDateField.RESOLUTION_MIN) {
- getClient()
- .updateVariable(
- getId(),
- "min",
- date != null ? date.getMinutes() : -1,
- currentResolution == VDateField.RESOLUTION_MIN
- && immediate);
- }
- if (currentResolution >= VDateField.RESOLUTION_SEC) {
- getClient()
- .updateVariable(
- getId(),
- "sec",
- date != null ? date.getSeconds() : -1,
- currentResolution == VDateField.RESOLUTION_SEC
- && immediate);
- }
- if (currentResolution == VDateField.RESOLUTION_MSEC) {
- getClient().updateVariable(getId(), "msec",
- date != null ? getMilliseconds() : -1, immediate);
- }
-
- }
-
- private String cleanFormat(String format) {
- // Remove unnecessary d & M if resolution is too low
- if (currentResolution < VDateField.RESOLUTION_DAY) {
- format = format.replaceAll("d", "");
- }
- if (currentResolution < VDateField.RESOLUTION_MONTH) {
- format = format.replaceAll("M", "");
- }
-
- // Remove unsupported patterns
- // TODO support for 'G', era designator (used at least in Japan)
- format = format.replaceAll("[GzZwWkK]", "");
-
- // Remove extra delimiters ('/' and '.')
- while (format.startsWith("/") || format.startsWith(".")
- || format.startsWith("-")) {
- format = format.substring(1);
- }
- while (format.endsWith("/") || format.endsWith(".")
- || format.endsWith("-")) {
- format = format.substring(0, format.length() - 1);
- }
-
- // Remove duplicate delimiters
- format = format.replaceAll("//", "/");
- format = format.replaceAll("\\.\\.", ".");
- format = format.replaceAll("--", "-");
-
- return format.trim();
- }
-
- @Override
- public void setWidth(String newWidth) {
- if (!"".equals(newWidth) && (width == null || !newWidth.equals(width))) {
- if (BrowserInfo.get().isIE6()) {
- // in IE6 cols ~ min-width
- DOM.setElementProperty(text.getElement(), "size", "1");
- }
- needLayout = true;
- width = newWidth;
- super.setWidth(width);
- iLayout();
- if (newWidth.indexOf("%") < 0) {
- needLayout = false;
- }
- } else {
- if ("".equals(newWidth) && width != null && !"".equals(width)) {
- if (BrowserInfo.get().isIE6()) {
- // revert IE6 hack
- DOM.setElementProperty(text.getElement(), "size", "");
- }
- super.setWidth("");
- needLayout = true;
- iLayout();
- needLayout = false;
- width = null;
- }
- }
- }
-
- /**
- * Returns pixels in x-axis reserved for other than textfield content.
- *
- * @return extra width in pixels
- */
- protected int getFieldExtraWidth() {
- if (fieldExtraWidth < 0) {
- text.setWidth("0");
- fieldExtraWidth = text.getOffsetWidth();
- if (BrowserInfo.get().isFF3()) {
- // Firefox somehow always leaves the INPUT element 2px wide
- fieldExtraWidth -= 2;
- }
- }
- return fieldExtraWidth;
- }
-
- public void updateWidth() {
- needLayout = true;
- fieldExtraWidth = -1;
- iLayout();
- }
-
- public void iLayout() {
- if (needLayout) {
- text.setWidth((getOffsetWidth() - getFieldExtraWidth()) + "px");
- }
- }
-
- public void focus() {
- text.setFocus(true);
- }
-
- protected String getText() {
- if (prompting) {
- return "";
- }
- return text.getText();
- }
-
- protected void setText(String text) {
- if (inputPrompt != null && (text == null || "".equals(text))) {
- text = readonly ? "" : inputPrompt;
- setPrompting(true);
- } else {
- setPrompting(false);
- }
-
- this.text.setText(text);
- }
-
- }
|