From 84e02a024a1e415132170c7addace0fe7a77271b Mon Sep 17 00:00:00 2001 From: Jouni Koivuviita Date: Wed, 11 Jul 2007 11:46:43 +0000 Subject: [PATCH] IDateField text style parsing more robust and supports more locales. Default popup-calendar style fixes. Feature-browser DateField demo now allows user to select a locale from a dropdown list. ISelect fixes and optimazations. svn changeset:1842/svn branch:trunk --- .../demo/features/FeatureDateField.java | 36 +++++----- .../gwt/client/ui/IOptionGroupBase.java | 6 +- .../gwt/client/ui/IPopupCalendar.java | 1 + .../terminal/gwt/client/ui/ISelect.java | 5 +- .../terminal/gwt/client/ui/ITextualDate.java | 36 +++++++++- .../toolkit/terminal/gwt/client/ui/ITime.java | 69 ++++++++++++++----- .../gwt/gwtwidgets/util/SimpleDateParser.java | 3 +- .../textfield/css/textfield.css | 8 ++- .../terminal/web/AjaxApplicationManager.java | 16 +++-- src/com/itmill/toolkit/ui/Select.java | 4 +- 10 files changed, 131 insertions(+), 53 deletions(-) diff --git a/src/com/itmill/toolkit/demo/features/FeatureDateField.java b/src/com/itmill/toolkit/demo/features/FeatureDateField.java index b372bb08a2..dae5ca2573 100644 --- a/src/com/itmill/toolkit/demo/features/FeatureDateField.java +++ b/src/com/itmill/toolkit/demo/features/FeatureDateField.java @@ -31,18 +31,22 @@ package com.itmill.toolkit.demo.features; import java.util.Locale; import com.itmill.toolkit.data.util.IndexedContainer; -import com.itmill.toolkit.ui.*; +import com.itmill.toolkit.data.util.MethodProperty; +import com.itmill.toolkit.ui.Component; +import com.itmill.toolkit.ui.DateField; +import com.itmill.toolkit.ui.Form; +import com.itmill.toolkit.ui.Label; +import com.itmill.toolkit.ui.OrderedLayout; +import com.itmill.toolkit.ui.Select; public class FeatureDateField extends Feature { - static private IndexedContainer localeContainer; + static private String[] localeNames; static { - localeContainer = new IndexedContainer(); - localeContainer.addContainerProperty("name", String.class, ""); Locale[] locales = Locale.getAvailableLocales(); - for (int i = 0; i < locales.length; i++) - localeContainer.addItem(locales[i]).getItemProperty("name") - .setValue(locales[i].getDisplayName()); + localeNames = new String[locales.length]; + for (int i = 0; i < locales.length; i++) + localeNames[i] = locales[i].getDisplayName(); } public FeatureDateField() { @@ -53,28 +57,18 @@ public class FeatureDateField extends Feature { OrderedLayout l = new OrderedLayout(); - l.addComponent(new Label("Your locale is: " + l.addComponent(new Label("Your default locale is: " + this.getApplication().getLocale().toString() .replace('_', '-'))); DateField df = new DateField(); df.setValue(new java.util.Date()); l.addComponent(df); - - // Create locale selector - // TODO: see #244 (broken for AJAX mode), known issue exists - /* - * DISABLE UNTIL WORKS Select selector = new Select("Application - * Locale", localeContainer); selector.setItemCaptionPropertyId("name"); - * selector.setImmediate(true); selector.setPropertyDataSource(new - * MethodProperty( this.getApplication(), "locale")); - * l.addComponent(selector); - */ - + // Properties propertyPanel = new PropertyPanel(df); Form ap = propertyPanel - .createBeanPropertySet(new String[] { "resolution" }); + .createBeanPropertySet(new String[] { "resolution", "locale" }); ap.replaceWithSelect("resolution", new Object[] { new Integer(DateField.RESOLUTION_YEAR), new Integer(DateField.RESOLUTION_MONTH), @@ -85,8 +79,10 @@ public class FeatureDateField extends Feature { new Integer(DateField.RESOLUTION_MSEC) }, new Object[] { "Year", "Month", "Day", "Hour", "Minute", "Second", "Millisecond" }); + ap.replaceWithSelect("locale", Locale.getAvailableLocales(), localeNames); ap.getField("resolution").setValue( new Integer(DateField.RESOLUTION_DAY)); + ap.getField("locale").setValue(Locale.getDefault()); Select themes = (Select) propertyPanel.getField("style"); themes.addItem("text").getItemProperty( themes.getItemCaptionPropertyId()).setValue("text"); diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOptionGroupBase.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOptionGroupBase.java index 854c45ad48..8ddf6502c0 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOptionGroupBase.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOptionGroupBase.java @@ -77,6 +77,7 @@ abstract class IOptionGroupBase extends Composite implements Paintable, ClickLis readonly = uidl.getBooleanAttribute("readonly"); disabled = uidl.getBooleanAttribute("disabled"); multiselect = "multi".equals(uidl.getStringAttribute("selectmode")); + immediate = uidl.getBooleanAttribute("immediate"); UIDL ops = uidl.getChildUIDL(0); @@ -138,8 +139,9 @@ abstract class IOptionGroupBase extends Composite implements Paintable, ClickLis protected abstract Object[] getSelectedItems(); protected Object getSelectedItem() { - if(getSelectedItems().length > 0) - return getSelectedItems()[0]; + Object[] sel = getSelectedItems(); + if(sel.length > 0) + return sel[0]; else return null; } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupCalendar.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupCalendar.java index 78ea84d9ae..99a1a6b95b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupCalendar.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupCalendar.java @@ -34,6 +34,7 @@ public class IPopupCalendar extends ITextualDate implements Paintable, ClickList public void updateFromUIDL(UIDL uidl, Client client) { super.updateFromUIDL(uidl, client); calendar.updateCalendar(); + calendarToggle.setEnabled(enabled); } public void onClick(Widget sender) { diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISelect.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISelect.java index 6076305bb5..99d25f75e5 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ISelect.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ISelect.java @@ -24,7 +24,10 @@ public class ISelect extends IOptionGroupBase { protected void buildOptions(UIDL uidl) { select.setMultipleSelect(multiselect); - if(multiselect) select.setVisibleItemCount(VISIBLE_COUNT); + if(multiselect) + select.setVisibleItemCount(VISIBLE_COUNT); + else + select.setVisibleItemCount(1); select.setEnabled(!disabled && !readonly); select.clear(); for (Iterator i = uidl.getChildIterator(); i.hasNext();) { diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java index 368d4f37bb..f7945f163b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java @@ -40,7 +40,7 @@ public class ITextualDate extends IDateField implements Paintable, ChangeListene else if(currentResolution >= IDateField.RESOLUTION_DAY) DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_DAY; - format = new SimpleDateFormat(dts.getDateFormat()); + format = new SimpleDateFormat(verifyFormat(dts.getDateFormat())); format.setLocale(dl); String dateText = format.format(date); @@ -68,6 +68,12 @@ public class ITextualDate extends IDateField implements Paintable, ChangeListene dateText += " " + (date.getHours()<12? dts.getAmPmStrings()[0] : dts.getAmPmStrings()[1]); text.setText(dateText); + text.setEnabled(enabled&&!readonly); + + if(readonly) + text.addStyleName("i-readonly"); + else + text.removeStyleName("i-readonly"); } public void onChange(Widget sender) { @@ -80,7 +86,7 @@ public class ITextualDate extends IDateField implements Paintable, ChangeListene else if(currentResolution == IDateField.RESOLUTION_DAY) DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_DAY; - String f = dts.getDateFormat(); + String f = verifyFormat(dts.getDateFormat()); if(currentResolution >= IDateField.RESOLUTION_HOUR) f += " " + (dts.isTwelveHourClock()? @@ -132,5 +138,29 @@ public class ITextualDate extends IDateField implements Paintable, ChangeListene buildTime(); } } - + + private String verifyFormat(String format) { + // Remove unnecessary d & M if resolution is too low + if(currentResolution < IDateField.RESOLUTION_DAY) + format = format.replaceAll("d", ""); + if(currentResolution < IDateField.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(); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITime.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITime.java index f9207b0cf9..4cc6d99c32 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITime.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITime.java @@ -75,24 +75,6 @@ public class ITime extends FlowPanel implements ChangeListener { msec.addChangeListener(this); } - // Update times - if(thc) { - int h = datefield.date.getHours(); - ampm.setSelectedIndex(h<12? 0 : 1); - h -= ampm.getSelectedIndex()*12; - hours.setSelectedIndex(h); - } else - hours.setSelectedIndex(datefield.date.getHours()); - if(datefield.currentResolution >= IDateField.RESOLUTION_MIN) - mins.setSelectedIndex(datefield.date.getMinutes()); - if(datefield.currentResolution >= IDateField.RESOLUTION_SEC) - sec.setSelectedIndex(datefield.date.getSeconds()); - if(datefield.currentResolution == IDateField.RESOLUTION_MSEC) - msec.setSelectedIndex(datefield.getMilliseconds()); - if(thc) - ampm.setSelectedIndex(datefield.date.getHours()<12?0:1); - - String delimiter = datefield.dts.getClockDelimeter(); boolean ro = datefield.readonly; @@ -139,6 +121,57 @@ public class ITime extends FlowPanel implements ChangeListener { if(ro) return; } + // Update times + if(thc) { + int h = datefield.date.getHours(); + ampm.setSelectedIndex(h<12? 0 : 1); + h -= ampm.getSelectedIndex()*12; + hours.setSelectedIndex(h); + } else + hours.setSelectedIndex(datefield.date.getHours()); + if(datefield.currentResolution >= IDateField.RESOLUTION_MIN) + mins.setSelectedIndex(datefield.date.getMinutes()); + if(datefield.currentResolution >= IDateField.RESOLUTION_SEC) + sec.setSelectedIndex(datefield.date.getSeconds()); + if(datefield.currentResolution == IDateField.RESOLUTION_MSEC) + msec.setSelectedIndex(datefield.getMilliseconds()); + if(thc) + ampm.setSelectedIndex(datefield.date.getHours()<12?0:1); + + if(datefield.readonly && !redraw) { + // Do complete redraw when in read-only status + clear(); + String delimiter = datefield.dts.getClockDelimeter(); + + int h = datefield.date.getHours(); + if(thc) h -= h<12? 0 : 12; + add(new ILabel(h<10? "0"+h : ""+h)); + + if(datefield.currentResolution >= IDateField.RESOLUTION_MIN) { + add(new ILabel(delimiter)); + int m = mins.getSelectedIndex(); + add(new ILabel(m<10? "0"+m : ""+m)); + } + if(datefield.currentResolution >= IDateField.RESOLUTION_SEC) { + add(new ILabel(delimiter)); + int s = sec.getSelectedIndex(); + add(new ILabel(s<10? "0"+s : ""+s)); + } + if(datefield.currentResolution == IDateField.RESOLUTION_MSEC) { + add(new ILabel(".")); + int m = datefield.getMilliseconds(); + String ms = m<100? "0"+m : ""+m; + add(new ILabel(m<10? "0"+ms : ms)); + } + if(datefield.currentResolution == IDateField.RESOLUTION_HOUR) { + add(new ILabel(delimiter+"00")); // o'clock + } + if(thc) { + add(new ILabel(" ")); + add(new ILabel(ampm.getItemText(datefield.date.getHours()<12? 0 : 1))); + } + } + boolean enabled = datefield.enabled; hours.setEnabled(enabled); if(mins != null) mins.setEnabled(enabled); diff --git a/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateParser.java b/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateParser.java index 90fdb22644..8f3a53b1b9 100644 --- a/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateParser.java +++ b/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateParser.java @@ -2,7 +2,6 @@ package com.itmill.toolkit.terminal.gwt.gwtwidgets.util; import java.util.Date; -import com.itmill.toolkit.terminal.gwt.client.DateTimeService; import com.itmill.toolkit.terminal.gwt.gwtwidgets.util.regex.Pattern; /** @@ -112,7 +111,7 @@ public class SimpleDateParser { int h = Integer.parseInt(text); String token = com.itmill.toolkit.terminal.gwt.client.DateLocale.getPM(); String which = input.substring(input.length() - token.length()); // Assumes both AM and PM tokens have same length - if(which.equals(token)) + if(which.equalsIgnoreCase(token)) h += 12; date.setHours(h); } diff --git a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/textfield/css/textfield.css b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/textfield/css/textfield.css index 5ea043f5f1..da7bbf32d7 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/textfield/css/textfield.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/textfield/css/textfield.css @@ -1,4 +1,4 @@ -.i-textfield{ +.i-textfield { font-size: 1.1em; color: #444; background: #fff url(../img/bg.png) repeat-x; @@ -19,4 +19,10 @@ .i-textfield-error { background: #ff9999; +} + +.i-textfield.i-readonly { + background: transparent; + color: #222; + border: none; } \ No newline at end of file diff --git a/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java b/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java index bf59c5ca76..0b7d7f361e 100644 --- a/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java @@ -486,14 +486,22 @@ public class AjaxApplicationManager implements // Force our locale as JVM default for a while (SimpleDateFormat uses JVM default) Locale.setDefault(l); String df = new SimpleDateFormat().toPattern(); - // TODO we suppose all formats separate date and time with a whitespace - String dateformat = df.substring(0,df.indexOf(" ")); - outWriter.print("\"df\":\"" + dateformat + "\","); + int timeStart = df.indexOf("H"); + if(timeStart < 0) + timeStart = df.indexOf("h"); + int ampm_first = df.indexOf("a"); + // E.g. in Korean locale AM/PM is before h:mm + // TODO should take that into consideration on client-side as well, now always h:mm a + if(ampm_first > 0 && ampm_first < timeStart) + timeStart = ampm_first; + String dateformat = df.substring(0, timeStart-1); + + outWriter.print("\"df\":\"" + dateformat.trim() + "\","); /* * Time formatting (24 or 12 hour clock and AM/PM suffixes) */ - String timeformat = df.substring(df.indexOf(" ")+1, df.length()); // Doesn't return second or milliseconds + String timeformat = df.substring(timeStart, df.length()); // Doesn't return second or milliseconds // We use timeformat to determine 12/24-hour clock boolean twelve_hour_clock = timeformat.contains("a"); // TODO there are other possibilities as well, like 'h' in french (ignore them, too complicated) diff --git a/src/com/itmill/toolkit/ui/Select.java b/src/com/itmill/toolkit/ui/Select.java index 88120ca810..a2ac194e12 100644 --- a/src/com/itmill/toolkit/ui/Select.java +++ b/src/com/itmill/toolkit/ui/Select.java @@ -430,7 +430,7 @@ public class Select extends AbstractField implements Container, newsel = new HashSet(newsel); newsel.removeAll(visible); newsel.addAll(s); - super.setValue(newsel); + setValue(newsel, true); } } @@ -550,7 +550,7 @@ public class Select extends AbstractField implements Container, * * @param newValue * the New selected item or collection of selected items. - * @param repaintIsNotNeeded True iff caller is sure that repaint is not needed. + * @param repaintIsNotNeeded True if caller is sure that repaint is not needed. * @see com.itmill.toolkit.ui.AbstractField#setValue(java.lang.Object, java.lang.Boolean) */ protected void setValue(Object newValue, boolean repaintIsNotNeeded) throws Property.ReadOnlyException, -- 2.39.5