]> source.dussan.org Git - vaadin-framework.git/commitdiff
DateField text-style implemented.
authorJouni Koivuviita <jouni.koivuviita@itmill.com>
Tue, 10 Jul 2007 12:38:34 +0000 (12:38 +0000)
committerJouni Koivuviita <jouni.koivuviita@itmill.com>
Tue, 10 Jul 2007 12:38:34 +0000 (12:38 +0000)
svn changeset:1828/svn branch:trunk

src/com/itmill/toolkit/terminal/gwt/Client.gwt.xml
src/com/itmill/toolkit/terminal/gwt/client/DateLocale.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java
src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupCalendar.java
src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java
src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/DateLocale.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateFormat.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateParser.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/regex/Pattern.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/public/component-themes/textfield/css/textfield.css

index 2ecad6ba07441ce5536f98dae9bb5b297b1d6485..19fed850ce839421e7ceb91f6caaf185a9d83df9 100644 (file)
@@ -1,18 +1,22 @@
 <module>
 
-       <inherits name='com.google.gwt.user.User'/>
+       <inherits name="com.google.gwt.user.User"/>
 
-       <inherits name='com.google.gwt.http.HTTP'/>
+       <inherits name="com.google.gwt.http.HTTP"/>
 
-       <inherits name='com.google.gwt.xml.XML'/>
+       <inherits name="com.google.gwt.xml.XML"/>
 
-       <inherits name='com.google.gwt.json.JSON'/>
+       <inherits name="com.google.gwt.json.JSON"/>
+       
+       <source path="client"/>
+       
+       <source path="gwtwidgets"/>
        
        <!-- Component stylesheets                                -->
        
        <stylesheet src="component-themes/collection.css"/>
 
        <!-- Specify the app entry point class.                   -->
-       <entry-point class='com.itmill.toolkit.terminal.gwt.client.Client'/>
+       <entry-point class="com.itmill.toolkit.terminal.gwt.client.Client"/>
   
 </module>
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/DateLocale.java b/src/com/itmill/toolkit/terminal/gwt/client/DateLocale.java
new file mode 100644 (file)
index 0000000..f0b1ddc
--- /dev/null
@@ -0,0 +1,57 @@
+package com.itmill.toolkit.terminal.gwt.client;\r
+\r
+public class DateLocale extends com.itmill.toolkit.terminal.gwt.gwtwidgets.util.DateLocale {\r
+\r
+       private static String locale;\r
+       \r
+       public DateLocale() {\r
+               locale = LocaleService.getDefaultLocale();\r
+       }\r
+       \r
+       public static void setLocale(String l) {\r
+               if(LocaleService.getAvailableLocales().contains(locale))\r
+                       locale = l;\r
+               else // TODO redirect to console\r
+                       System.out.println("Tried to use an unloaded locale \""+locale+"\". Using default in stead ("+locale+")");\r
+       }\r
+       \r
+       public static String getAM() {\r
+               try {\r
+                       return LocaleService.getAmPmStrings(locale)[0];\r
+               } catch (LocaleNotLoadedException e) {\r
+                       // TODO redirect to console\r
+                       System.out.println("Tried to use an unloaded locale \""+locale+"\".");\r
+                       return "AM";\r
+               }\r
+       }\r
+       \r
+       public static String getPM() {\r
+               try {\r
+                       return LocaleService.getAmPmStrings(locale)[1];\r
+               } catch (LocaleNotLoadedException e) {\r
+                       // TODO redirect to console\r
+                       System.out.println("Tried to use an unloaded locale \""+locale+"\".");\r
+                       return "PM";\r
+               }\r
+       }\r
+       \r
+       public String[] getWEEKDAY_LONG() {\r
+               try {\r
+                       return LocaleService.getDayNames(locale);\r
+               } catch (LocaleNotLoadedException e) {\r
+                       // TODO redirect to console\r
+                       System.out.println("Tried to use an unloaded locale \""+locale+"\".");\r
+                       return null;\r
+               }\r
+       }\r
+       \r
+       public String[] getWEEKDAY_SHORT() {\r
+               try {\r
+                       return LocaleService.getShortDayNames(locale);\r
+               } catch (LocaleNotLoadedException e) {\r
+                       // TODO redirect to console\r
+                       System.out.println("Tried to use an unloaded locale \""+locale+"\".");\r
+                       return null;\r
+               }\r
+       }\r
+}\r
index 7e92ff80a39d888614d1328c4d92a2dd5bcf753c..77429b0a04b00d1de8aded2f9b81c87c3cf6b67a 100644 (file)
@@ -140,6 +140,16 @@ public class DateTimeService {
                return start;\r
        }\r
        \r
+       public String getDateFormat() {\r
+               try {\r
+                       return LocaleService.getDateFormat(currentLocale);\r
+               } catch (LocaleNotLoadedException e) {\r
+                       // TODO redirect to console\r
+                       System.out.println(e + ":" + e.getMessage());\r
+               }\r
+               return "M/d/yy";\r
+       }\r
+       \r
        public static int getNumberOfDaysInMonth(Date date){\r
                int month = date.getMonth();\r
                if(month == 1 && true == isLeapYear(date))\r
index 4d5933dce7b421c71a1aa8bea95a581b727d58cf..b2a70ed9fc6cd8f1420d3758104b805b3b580c39 100644 (file)
@@ -1,5 +1,58 @@
 package com.itmill.toolkit.terminal.gwt.client.ui;\r
 \r
-public class IPopupCalendar extends IDateField {\r
+import com.google.gwt.user.client.ui.ChangeListener;\r
+import com.google.gwt.user.client.ui.ClickListener;\r
+import com.google.gwt.user.client.ui.PopupListener;\r
+import com.google.gwt.user.client.ui.PopupPanel;\r
+import com.google.gwt.user.client.ui.Widget;\r
+import com.itmill.toolkit.terminal.gwt.client.Client;\r
+import com.itmill.toolkit.terminal.gwt.client.Paintable;\r
+import com.itmill.toolkit.terminal.gwt.client.UIDL;\r
+\r
+public class IPopupCalendar extends IDateField implements Paintable, ChangeListener, ClickListener {\r
+       \r
+       private ITextField text;\r
+       \r
+       private IButton calendarToggle;\r
+       \r
+       private ICalendarPanel calendar;\r
+       \r
+       private PopupPanel popup;\r
+       \r
+       public IPopupCalendar() {\r
+               super();\r
+               text = new ITextField();\r
+               text.addChangeListener(this);\r
+               calendarToggle = new IButton();\r
+               calendarToggle.setText("...");\r
+               calendarToggle.addClickListener(this);\r
+               calendar = new ICalendarPanel(this);\r
+               popup = new PopupPanel(true);\r
+               popup.setStyleName(IDateField.CLASSNAME+"-calendar");\r
+               popup.setWidget(calendar);\r
+               add(text);\r
+               add(calendarToggle);\r
+       }\r
+       \r
+       public void updateFromUIDL(UIDL uidl, Client client) {\r
+               super.updateFromUIDL(uidl, client);\r
+               \r
+               \r
+               \r
+               calendar.updateCalendar();\r
+       }\r
+\r
+       public void onChange(Widget sender) {\r
+               \r
+       }\r
+\r
+       public void onClick(Widget sender) {\r
+               if(sender == calendarToggle) {\r
+                               popup.setPopupPosition(calendarToggle.getAbsoluteLeft(), calendarToggle.getAbsoluteTop() + calendarToggle.getOffsetHeight() + 2);\r
+                               popup.show();\r
+                               popup.setWidth(calendar.getOffsetWidth() + "px");\r
+                               popup.setHeight(calendar.getOffsetHeight() + "px");\r
+               }\r
+       }\r
 \r
 }\r
index 73993bbd70ffdc3ef235f6ecb4a7581951d5e979..61d79ec6fdc01aa53a6419161ad447d9e9715b1b 100644 (file)
 package com.itmill.toolkit.terminal.gwt.client.ui;\r
 \r
-import java.util.Date;\r
 \r
+import com.google.gwt.user.client.Timer;\r
 import com.google.gwt.user.client.ui.ChangeListener;\r
-import com.google.gwt.user.client.ui.ListBox;\r
 import com.google.gwt.user.client.ui.Widget;\r
 import com.itmill.toolkit.terminal.gwt.client.Client;\r
+import com.itmill.toolkit.terminal.gwt.client.DateLocale;\r
 import com.itmill.toolkit.terminal.gwt.client.Paintable;\r
 import com.itmill.toolkit.terminal.gwt.client.UIDL;\r
+import com.itmill.toolkit.terminal.gwt.gwtwidgets.util.SimpleDateFormat;\r
 \r
 public class ITextualDate extends IDateField implements Paintable, ChangeListener {\r
        \r
-       private ListBox year;\r
+       private ITextField text;\r
        \r
-       private ListBox month;\r
+       private SimpleDateFormat format;\r
        \r
-       private ListBox day;\r
+       private DateLocale dl;\r
        \r
        public ITextualDate() {\r
-               \r
+               super();\r
+               text = new ITextField();\r
+               text.addChangeListener(this);\r
+               add(text);\r
        }\r
        \r
        public void updateFromUIDL(UIDL uidl, Client client) {\r
                super.updateFromUIDL(uidl, client);\r
+               buildTime();\r
+       }\r
+\r
+       private void buildTime() {\r
+               dl = new DateLocale();\r
+               DateLocale.setLocale(currentLocale);\r
                \r
-               if(uidl.hasVariable("year")) {\r
-                       int selectedYear = uidl.getIntVariable("year");\r
-                       int y = getWidgetIndex(year);\r
-                       if(y > -1 || !currentLocale.equals(uidl.getStringAttribute("locale"))) {\r
-                               year = (ListBox) getWidget(y);\r
-                               // Deselect old value\r
-                               year.setItemSelected(year.getSelectedIndex(), false);\r
-                               // and select new\r
-                               for(int i=0; i < year.getItemCount(); i++)\r
-                                       if(year.getValue(i).equals(""+selectedYear)) {\r
-                                               year.setSelectedIndex(i);\r
-                                               break;\r
-                                       }\r
-                       } else {\r
-                               year = new ListBox();\r
-                               year.setStyleName(ISelect.CLASSNAME);\r
-                               int today = 1900 + (new Date()).getYear();\r
-                               for(int i=1970; i<today+400; i++) {\r
-                                       year.addItem(""+i, ""+i);\r
-                                       if(i == selectedYear)\r
-                                               year.setSelectedIndex(year.getItemCount()-1);\r
-                               }\r
-                               year.addChangeListener(this);\r
-                               add(year);\r
-                       }\r
+               DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_YEAR;\r
+               if(currentResolution == IDateField.RESOLUTION_MONTH)\r
+                       DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_MONTH;\r
+               else if(currentResolution >= IDateField.RESOLUTION_DAY)\r
+                       DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_DAY;\r
+                       \r
+               format = new SimpleDateFormat(dts.getDateFormat());\r
+               format.setLocale(dl);\r
+               \r
+               String dateText = format.format(date);\r
+               \r
+               if(currentResolution >= IDateField.RESOLUTION_HOUR) {\r
+                       DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_ALL;\r
+                       int h = date.getHours();\r
+                       if(h > 11 && dts.isTwelveHourClock())\r
+                               h -= 12;\r
+                       int m = currentResolution > IDateField.RESOLUTION_HOUR? date.getMinutes() : 0;\r
+                       dateText += " " + (h<10?"0"+h:""+h) + dts.getClockDelimeter() + (m<10?"0"+m:""+m);\r
                }\r
-               if(uidl.hasVariable("month")) {\r
-                       int selectedMonth = uidl.getIntVariable("month");\r
-                       int y = getWidgetIndex(month);\r
-                       if(y > -1) {\r
-                               month = (ListBox) getWidget(y);\r
-                               // Deselect old value\r
-                               month.setItemSelected(month.getSelectedIndex(), false);\r
-                               // and select new\r
-                               for(int i=0; i < month.getItemCount(); i++)\r
-                                       if(month.getValue(i).equals(""+selectedMonth)) {\r
-                                               month.setSelectedIndex(i);\r
-                                               break;\r
-                                       }\r
-                       } else {\r
-                               month = new ListBox();\r
-                               month.setStyleName(ISelect.CLASSNAME);\r
-                               int today = (new Date()).getMonth();\r
-                               for(int i=0; i<12; i++) {\r
-                                       month.addItem(""+(i+1), ""+i);\r
-                                       if(i == selectedMonth)\r
-                                               month.setSelectedIndex(month.getItemCount()-1);\r
-                               }\r
-                               month.addChangeListener(this);\r
-                               add(month);\r
-                       }\r
+               if(currentResolution >= IDateField.RESOLUTION_SEC) {\r
+                       int s = date.getSeconds();\r
+                       dateText += dts.getClockDelimeter() + (s<10?"0"+s:""+s);\r
                }\r
-               if(uidl.hasVariable("day")) {\r
-                       int selectedMonth = uidl.getIntVariable("day");\r
-                       int y = getWidgetIndex(day);\r
-                       if(y > -1) {\r
-                               day = (ListBox) getWidget(y);\r
-                               // Deselect old value\r
-                               day.setItemSelected(day.getSelectedIndex(), false);\r
-                               // and select new\r
-                               for(int i=0; i <day.getItemCount(); i++)\r
-                                       if(day.getValue(i).equals(""+selectedMonth)) {\r
-                                               day.setSelectedIndex(i);\r
-                                               break;\r
-                                       }\r
-                       } else {\r
-                               day = new ListBox();\r
-                               day.setStyleName(ISelect.CLASSNAME);\r
-                               int today = (new Date()).getDay();\r
-                               for(int i=0; i<31; i++) {\r
-                                       day.addItem(""+(i+1), ""+i);\r
-                                       if(i == selectedMonth)\r
-                                               day.setSelectedIndex(day.getItemCount()-1);\r
-                               }\r
-                               day.addChangeListener(this);\r
-                               add(day);\r
-                       }\r
+               if(currentResolution == IDateField.RESOLUTION_MSEC) {\r
+                       int ms = getMilliseconds();\r
+                       String text = ""+ms;\r
+                       if(ms<10) text = "00"+text;\r
+                       else if(ms<100) text = "0"+text;\r
+                       dateText += "." + text;\r
                }\r
+               if(dts.isTwelveHourClock())\r
+                       dateText += " " + (date.getHours()<12? dts.getAmPmStrings()[0] : dts.getAmPmStrings()[1]);\r
+               \r
+               text.setText(dateText);\r
        }\r
 \r
        public void onChange(Widget sender) {\r
-               if(sender == year && client != null)\r
-                       client.updateVariable(id, "year", year.getValue(year.getSelectedIndex()), immediate);\r
-               \r
+               if(sender == text) {\r
+                       DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_ALL;\r
+                       if(currentResolution == IDateField.RESOLUTION_YEAR)\r
+                               DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_YEAR;\r
+                       else if(currentResolution == IDateField.RESOLUTION_MONTH)\r
+                               DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_MONTH;\r
+                       else if(currentResolution == IDateField.RESOLUTION_DAY)\r
+                               DateLocale.SUPPORTED_DF_TOKENS = DateLocale.TOKENS_RESOLUTION_DAY;\r
+                       \r
+                       String f = dts.getDateFormat();\r
+                       \r
+                       if(currentResolution >= IDateField.RESOLUTION_HOUR)\r
+                               f += " " + (dts.isTwelveHourClock()?\r
+                                               DateLocale.TOKEN_HOUR_12 + DateLocale.TOKEN_HOUR_12\r
+                                         : DateLocale.TOKEN_HOUR_24 + DateLocale.TOKEN_HOUR_24)\r
+                                               + dts.getClockDelimeter() + DateLocale.TOKEN_MINUTE + DateLocale.TOKEN_MINUTE;\r
+                       if(currentResolution >= IDateField.RESOLUTION_SEC)\r
+                               f += dts.getClockDelimeter() + DateLocale.TOKEN_SECOND + DateLocale.TOKEN_SECOND;\r
+                       if(currentResolution == IDateField.RESOLUTION_MSEC)\r
+                               f += "." + DateLocale.TOKEN_MILLISECOND + DateLocale.TOKEN_MILLISECOND + DateLocale.TOKEN_MILLISECOND;\r
+                       if(currentResolution >= IDateField.RESOLUTION_HOUR && dts.isTwelveHourClock())\r
+                               f += " " + DateLocale.TOKEN_AM_PM;\r
+                       \r
+                       format = new SimpleDateFormat(f);\r
+                       DateLocale.setLocale(currentLocale);\r
+                       format.setLocale(dl);\r
+                       \r
+                       try {\r
+                               date = format.parse(text.getText());\r
+                       } catch (Exception e) {\r
+                               // TODO redirect to console\r
+                               System.out.println(e);\r
+                               text.addStyleName(ITextField.CLASSNAME+"-error");\r
+                               Timer t = new Timer() {\r
+                                       public void run() {\r
+                                               text.removeStyleName(ITextField.CLASSNAME+"-error");\r
+                                       }\r
+                               };\r
+                               t.schedule(2000);\r
+                               return;\r
+                       }\r
+                       \r
+                       // Update variables\r
+                       // (only the smallest defining resolution needs to be immediate)\r
+                       client.updateVariable(id, "year", date.getYear()+1900, currentResolution==IDateField.RESOLUTION_YEAR);\r
+                       if(currentResolution >= IDateField.RESOLUTION_MONTH)\r
+                               client.updateVariable(id, "month", date.getMonth()+1, currentResolution==IDateField.RESOLUTION_MONTH&&immediate);\r
+                       if(currentResolution >= IDateField.RESOLUTION_DAY)\r
+                               client.updateVariable(id, "day", date.getDate(), currentResolution==IDateField.RESOLUTION_DAY&&immediate);\r
+                       if(currentResolution >= IDateField.RESOLUTION_HOUR)\r
+                               client.updateVariable(id, "hour", date.getHours(), currentResolution==IDateField.RESOLUTION_HOUR&&immediate);\r
+                       if(currentResolution >= IDateField.RESOLUTION_MIN)\r
+                               client.updateVariable(id, "min", date.getMinutes(), currentResolution==IDateField.RESOLUTION_MIN&&immediate);\r
+                       if(currentResolution >= IDateField.RESOLUTION_SEC)\r
+                               client.updateVariable(id, "sec", date.getSeconds(), currentResolution==IDateField.RESOLUTION_SEC&&immediate);\r
+                       if(currentResolution == IDateField.RESOLUTION_MSEC)\r
+                               client.updateVariable(id, "msec", getMilliseconds(), immediate);\r
+                       \r
+                       buildTime();\r
+               }\r
        }\r
 \r
 }\r
diff --git a/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/DateLocale.java b/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/DateLocale.java
new file mode 100644 (file)
index 0000000..bb4cb01
--- /dev/null
@@ -0,0 +1,85 @@
+package com.itmill.toolkit.terminal.gwt.gwtwidgets.util;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+/**\r
+ * Date locale support for the {@link SimpleDateParser}. You are encouraged to\r
+ * extend this class and provide implementations for other locales. \r
+ * @author <a href="mailto:g.georgovassilis@gmail.com">George Georgovassilis</a>\r
+ *\r
+ */\r
+public class DateLocale {\r
+       public final static String TOKEN_DAY_OF_WEEK = "E";\r
+\r
+       public final static String TOKEN_DAY_OF_MONTH = "d";\r
+\r
+       public final static String TOKEN_MONTH = "M";\r
+\r
+       public final static String TOKEN_YEAR = "y";\r
+\r
+       public final static String TOKEN_HOUR_12 = "h";\r
+\r
+       public final static String TOKEN_HOUR_24 = "H";\r
+\r
+       public final static String TOKEN_MINUTE = "m";\r
+\r
+       public final static String TOKEN_SECOND = "s";\r
+       \r
+       public final static String TOKEN_MILLISECOND = "S";\r
+       \r
+       public final static String TOKEN_AM_PM = "a";\r
+\r
+       public final static String AM = "AM";\r
+\r
+       public final static String PM = "PM";\r
+\r
+       public static List SUPPORTED_DF_TOKENS = Arrays.asList(new String[] {\r
+               TOKEN_DAY_OF_WEEK, TOKEN_DAY_OF_MONTH, TOKEN_MONTH, TOKEN_YEAR,\r
+               TOKEN_HOUR_12, TOKEN_HOUR_24, TOKEN_MINUTE, TOKEN_SECOND,\r
+               TOKEN_AM_PM });\r
+       \r
+       public static List TOKENS_RESOLUTION_ALL = Arrays.asList(new String[] {\r
+               TOKEN_DAY_OF_WEEK, TOKEN_DAY_OF_MONTH, TOKEN_MONTH, TOKEN_YEAR,\r
+               TOKEN_HOUR_12, TOKEN_HOUR_24, TOKEN_MINUTE, TOKEN_SECOND,\r
+               TOKEN_AM_PM });\r
+       \r
+       public static List TOKENS_RESOLUTION_YEAR = Arrays.asList(new String[] {\r
+               TOKEN_YEAR});\r
+       \r
+       public static List TOKENS_RESOLUTION_MONTH = Arrays.asList(new String[] {\r
+               TOKEN_YEAR, TOKEN_MONTH});\r
+       \r
+       public static List TOKENS_RESOLUTION_DAY = Arrays.asList(new String[] {\r
+               TOKEN_YEAR, TOKEN_MONTH, TOKEN_DAY_OF_MONTH});\r
+\r
+       public String[] MONTH_LONG = { "January", "February", "March", "April",\r
+               "May", "June", "July", "August", "September", "October",\r
+               "November", "December" };\r
+\r
+       public String[] MONTH_SHORT = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",\r
+               "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" };\r
+\r
+       public String[] WEEKDAY_LONG = { "Sunday", "Monday", "Tuesday",\r
+               "Wednesday", "Thursday", "Friday", "Saturday" };\r
+\r
+       public String[] WEEKDAY_SHORT = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",\r
+               "Sat" };\r
+\r
+       public static String getAM() {\r
+       return AM;\r
+    }\r
+\r
+       public static String getPM() {\r
+       return PM;\r
+    }\r
+\r
+       public String[] getWEEKDAY_LONG() {\r
+               return WEEKDAY_LONG;\r
+       }\r
+\r
+       public String[] getWEEKDAY_SHORT() {\r
+               return WEEKDAY_SHORT;\r
+       }\r
+\r
+}\r
diff --git a/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateFormat.java b/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateFormat.java
new file mode 100644 (file)
index 0000000..79ce651
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2006 Robert Hanson <iamroberthanson AT gmail.com>
+ * 
+ * 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.itmill.toolkit.terminal.gwt.gwtwidgets.util;
+
+import java.util.Date;
+
+/**
+ * <dl>
+ * <dt><b>Title: </b>
+ * <dd>SimpleDateFormat</dd>
+ * <p>
+ * <dt><b>Description: </b>
+ * <dd>GWT does not implement any of the java.text package, so this class tries
+ * to fill the void of the missing java.text.SimpleDateFormat class. This
+ * version however only supports a subset of the date and time patterns
+ * supported by its java.text counterpart. The pattern symbols supported by this
+ * class are:
+ * <dl>
+ * <dt><b>E</b></dt>
+ * <dd>Day in a week</dd>
+ * <dt><b>d</b></dt>
+ * <dd>Day of the month</dd>
+ * <dt><b>y</b></dt>
+ * <dd>Year</dd>
+ * <dt><b>M</b></dt>
+ * <dd>Month January, Jan, 01, 1</dd>
+ * <dt><b>H</b></dt>
+ * <dd>Hour in 24 hour format (0-23)</dd>
+ * <dt><b>h</b></dt>
+ * <dd>Hour in 12 hour format (1-12)</dd>
+ * <dt><b>m</b></dt>
+ * <dd>Minute of the hour </dd>
+ * <dt><b>s</b></dt>
+ * <dd>Seconds of the minute</dd>
+ * <dt><b>a</b></dt>
+ * <dd>am/pm</dd>
+ * </dl>
+ * All characters that are not recognised as a date format character are
+ * translated literally into the output string. <br/> </dd>
+ * <p>
+ * </dl>
+ * <p>
+ * A simple date parsing facility has also been implemented resembling the java
+ * prototype. You can currently parse most numeric patterns but no temporal
+ * literals (such as day or month names).
+ * </p>
+ * 
+ * @author <a href="mailto:jasone@greenrivercomputing.com">Jason Essington</a>
+ * @author <a href="mailto:g.georgovassilis@gmail.com">George Georgovassilis</a>
+ * @version $Revision: 0.0 $
+ */
+public class SimpleDateFormat {
+       private String format;
+       private DateLocale locale = new DateLocale();
+
+       /**
+        * Gets the support locale for formatting and parsing dates
+        * @return
+        */
+       public DateLocale getLocale() {
+       return locale;
+    }
+
+       public void setLocale(DateLocale locale) {
+       this.locale = locale;
+    }
+
+       public SimpleDateFormat(String pattern) {
+               format = pattern;
+       }
+
+       public String format(Date date) {
+               String f = "";
+               if (format != null && format.length() > 0) {
+                       String lastTokenType = null;
+                       String currentToken = "";
+                       for (int i = 0; i < format.length(); i++) {
+                               String thisChar = format.substring(i, i + 1);
+                               String currentTokenType = DateLocale.SUPPORTED_DF_TOKENS
+                                       .contains(thisChar) ? thisChar : "";
+                               if (currentTokenType.equals(lastTokenType) || i == 0) {
+                                       currentToken += thisChar;
+                                       lastTokenType = currentTokenType;
+                               } else {
+                                       if ("".equals(lastTokenType))
+                                               f += currentToken;
+                                       else
+                                               f += handleToken(currentToken, date);
+                                       currentToken = thisChar;
+                                       lastTokenType = currentTokenType;
+                               }
+                       }
+                       if ("".equals(lastTokenType))
+                               f += currentToken;
+                       else
+                               f += handleToken(currentToken, date);
+               }
+               return f;
+       }
+
+       /**
+        * takes a date format string and returns the formatted portion of the date.
+        * For instance if the token is MMMM then the full month name is returned.
+        * 
+        * @param token
+        *            date format token
+        * @param date
+        *            date to format
+        * @return formatted portion of the date
+        */
+       private String handleToken(String token, Date date) {
+               String response = token;
+               String tc = token.substring(0, 1);
+               if (DateLocale.TOKEN_DAY_OF_WEEK.equals(tc)) {
+                       if (token.length() > 3)
+                               response = locale.getWEEKDAY_LONG()[date.getDay()];
+                       else
+                               response = locale.getWEEKDAY_SHORT()[date.getDay()];
+               } else if (DateLocale.TOKEN_DAY_OF_MONTH.equals(tc)) {
+                       if (token.length() == 1)
+                               response = Integer.toString(date.getDate());
+                       else
+                               response = twoCharDateField(date.getDate());
+               } else if (DateLocale.TOKEN_MONTH.equals(tc)) {
+                       switch (token.length()) {
+                       case 1:
+                               response = Integer.toString(date.getMonth() + 1);
+                               break;
+                       case 2:
+                               response = twoCharDateField(date.getMonth() + 1);
+                               break;
+                       case 3:
+                               response = locale.MONTH_SHORT[date.getMonth()];
+                               break;
+                       default:
+                               response = locale.MONTH_LONG[date.getMonth()];
+                               break;
+                       }
+               } else if (DateLocale.TOKEN_YEAR.equals(tc)) {
+                       if (token.length() >= 2)
+                               response = Integer.toString(date.getYear() + 1900);
+                       else
+                               response = twoCharDateField(date.getYear());
+               } else if (DateLocale.TOKEN_HOUR_12.equals(tc)) {
+                       int h = date.getHours();
+                       if (h == 0)
+                               h = 12;
+                       else if (h > 12)
+                               h -= 12;
+                       //if (token.length() > 1)
+                               response = twoCharDateField(h);
+                       //else
+                               //response = Integer.toString(h);
+               } else if (DateLocale.TOKEN_HOUR_24.equals(tc)) {
+                       //if (token.length() > 1)
+                               response = twoCharDateField(date.getHours());
+                       //else
+                               //response = Integer.toString(date.getHours());
+               } else if (DateLocale.TOKEN_MINUTE.equals(tc)) {
+                       //if (token.length() > 1)
+                               response = twoCharDateField(date.getMinutes());
+                       //else
+                               //response = Integer.toString(date.getMinutes());
+               } else if (DateLocale.TOKEN_SECOND.equals(tc)) {
+                       //if (token.length() > 1)
+                               response = twoCharDateField(date.getSeconds());
+                       //else
+                               //response = Integer.toString(date.getSeconds());
+               } else if (DateLocale.TOKEN_AM_PM.equals(tc)) {
+                       int hour = date.getHours();
+                       if (hour > 11)
+                               response = DateLocale.getPM();
+                       else
+                               response = DateLocale.getAM();
+               }
+               return response;
+       }
+
+       /**
+        * This is basically just a sneaky way to guarantee that our 1 or 2 digit
+        * numbers come out as a 2 character string. we add an arbitrary number
+        * larger than 100, convert this new number to a string, then take the right
+        * most 2 characters.
+        * 
+        * @param num
+        * @return
+        */
+       private String twoCharDateField(int num) {
+               String res = Integer.toString(num + 1900);
+               res = res.substring(res.length() - 2);
+               return res;
+       }
+
+       private static Date newDate(long time) {
+               return new Date(time);
+       }
+
+       /**
+        * Parses text and returns the corresponding date object. 
+        * 
+        * @param source
+        * @return java.util.Date
+        */
+       public Date parse(String source){
+               return SimpleDateParser.parse(source, format);
+       };
+
+}
diff --git a/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateParser.java b/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/SimpleDateParser.java
new file mode 100644 (file)
index 0000000..90fdb22
--- /dev/null
@@ -0,0 +1,157 @@
+package com.itmill.toolkit.terminal.gwt.gwtwidgets.util;\r
+\r
+import java.util.Date;\r
+\r
+import com.itmill.toolkit.terminal.gwt.client.DateTimeService;\r
+import com.itmill.toolkit.terminal.gwt.gwtwidgets.util.regex.Pattern;\r
+\r
+/**\r
+ * This is a simple regular expression based parser for date notations.\r
+ * While our aim is to fully support in the future the JDK date parser, currently\r
+ * only numeric notations and literals are supported such as <code>dd/MM/yyyy HH:mm:ss.SSSS</code>.\r
+ * Each entity is parsed with the same number of digits, i.e. for <code>dd</code> two digits will be\r
+ * parsed while for <code>d</code> only one will be parsed.\r
+ * @author <a href="mailto:g.georgovassilis@gmail.com">George Georgovassilis</a>\r
+ *\r
+ */\r
+\r
+public class SimpleDateParser {\r
+\r
+\r
+       private final static String DAY_IN_MONTH = "d";\r
+\r
+       private final static String MONTH = "M";\r
+\r
+       private final static String YEAR = "y";\r
+\r
+       private final static String LITERAL = "\\";\r
+\r
+       private final static int DATE_PATTERN = 0;\r
+\r
+       private final static int REGEX_PATTERN = 1;\r
+\r
+       private final static int COMPONENT = 2;\r
+\r
+       private final static int REGEX = 0;\r
+\r
+       private final static int INSTRUCTION = 1;\r
+\r
+       private final static String[] TOKENS[] = {\r
+       { "SSSS", "(\\d\\d\\d\\d)",DateLocale.TOKEN_MILLISECOND }, \r
+       { "SSS", "(\\d\\d\\d)", DateLocale.TOKEN_MILLISECOND },\r
+       { "SS", "(\\d\\d)", DateLocale.TOKEN_MILLISECOND }, \r
+       { "S", "(\\d)", DateLocale.TOKEN_MILLISECOND },\r
+       { "ss", "(\\d\\d)", DateLocale.TOKEN_SECOND }, \r
+       { "s", "(\\d\\d)", DateLocale.TOKEN_SECOND },\r
+       { "mm", "(\\d\\d)", DateLocale.TOKEN_MINUTE }, \r
+       { "m", "(\\d\\d)", DateLocale.TOKEN_MINUTE},\r
+       { "HH", "(\\d\\d)", DateLocale.TOKEN_HOUR_24},\r
+       { "H", "(\\d{1,2})", DateLocale.TOKEN_HOUR_24 },\r
+       { "hh", "(\\d\\d)", DateLocale.TOKEN_HOUR_12},\r
+       { "h", "(\\d{1,2})", DateLocale.TOKEN_HOUR_12 },\r
+       { "dd", "(\\d\\d)", DateLocale.TOKEN_DAY_OF_MONTH }, \r
+       { "d", "(\\d{1,2})", DateLocale.TOKEN_DAY_OF_MONTH },\r
+       { "MM", "(\\d\\d)", DateLocale.TOKEN_MONTH }, \r
+       { "M", "(\\d{1,2})", DateLocale.TOKEN_MONTH },\r
+       { "yyyy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, \r
+       { "yyy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR },\r
+       { "yy", "(\\d\\d\\d\\d)", DateLocale.TOKEN_YEAR }, \r
+       { "y", "(\\d{1,2})", DateLocale.TOKEN_YEAR },\r
+       { "a", "(\\S{1,4})", DateLocale.TOKEN_AM_PM }\r
+       };\r
+\r
+       private Pattern regularExpression;\r
+\r
+       private String instructions = "";\r
+\r
+       private static void _parse(String format, String[] args) {\r
+               if (format.length() == 0)\r
+                       return;\r
+               if (format.startsWith("'")){\r
+                       format = format.substring(1);\r
+                       int end = format.indexOf("'");\r
+                       if (end == -1)\r
+                               throw new IllegalArgumentException("Unmatched single quotes.");\r
+                       args[REGEX]+=Pattern.quote(format.substring(0,end));\r
+                       format = format.substring(end+1);\r
+               }\r
+               for (int i = 0; i < TOKENS.length; i++) {\r
+                       String[] row = TOKENS[i];\r
+                       String datePattern = row[DATE_PATTERN];\r
+                       if (!format.startsWith(datePattern))\r
+                               continue;\r
+                       format = format.substring(datePattern.length());\r
+                       args[REGEX] += row[REGEX_PATTERN];\r
+                       args[INSTRUCTION] += row[COMPONENT];\r
+                       _parse(format, args);\r
+                       return;\r
+               }\r
+               args[REGEX] += Pattern.quote(""+format.charAt(0));\r
+               format = format.substring(1);\r
+               _parse(format, args);\r
+       }\r
+\r
+       private static void load(Date date, String text, String component, String input, Pattern regex) {\r
+               if (component.equals(DateLocale.TOKEN_MILLISECOND)) {\r
+                       // TODO implement setMilliseconds to date object\r
+               }\r
+\r
+               if (component.equals(DateLocale.TOKEN_SECOND)) {\r
+                       date.setSeconds(Integer.parseInt(text));\r
+               }\r
+\r
+               if (component.equals(DateLocale.TOKEN_MINUTE)) {\r
+                       date.setMinutes(Integer.parseInt(text));\r
+               }\r
+\r
+               if (component.equals(DateLocale.TOKEN_HOUR_24)) {\r
+                       date.setHours(Integer.parseInt(text));\r
+               }\r
+               \r
+               if (component.equals(DateLocale.TOKEN_HOUR_12)) {\r
+                       int h = Integer.parseInt(text);\r
+                       String token = com.itmill.toolkit.terminal.gwt.client.DateLocale.getPM();\r
+                       String which = input.substring(input.length() - token.length()); // Assumes both AM and PM tokens have same length\r
+                       if(which.equals(token))\r
+                               h += 12;\r
+                       date.setHours(h);\r
+               }\r
+\r
+               if (component.equals(DateLocale.TOKEN_DAY_OF_MONTH)) {\r
+                       date.setDate(Integer.parseInt(text));\r
+               }\r
+               if (component.equals(DateLocale.TOKEN_MONTH)) {\r
+                       date.setMonth(Integer.parseInt(text)-1);\r
+               }\r
+               if (component.equals(DateLocale.TOKEN_YEAR)) {\r
+                       //TODO: fix for short patterns\r
+                       date.setYear(Integer.parseInt(text)-1900);\r
+               }\r
+\r
+       }\r
+\r
+       public SimpleDateParser(String format) {\r
+               String[] args = new String[] { "", "" };\r
+               _parse(format, args);\r
+               regularExpression = new Pattern(args[REGEX]);\r
+               instructions = args[INSTRUCTION];\r
+       }\r
+\r
+       public Date parse(String input) {\r
+               Date date = new Date(0, 0, 0, 0, 0, 0);\r
+               String matches[] = regularExpression.match(input);\r
+               if (matches == null)\r
+                       throw new IllegalArgumentException(input+" does not match "+regularExpression.pattern());\r
+               if (matches.length-1!=instructions.length())\r
+                       throw new IllegalArgumentException("Different group count - "+input+" does not match "+regularExpression.pattern());\r
+               for (int group = 0; group < instructions.length(); group++) {\r
+                       String match = matches[group + 1];\r
+                       load(date, match, ""+instructions.charAt(group), input, regularExpression);\r
+               }\r
+               return date;\r
+       }\r
+       \r
+       public static Date parse(String input, String pattern){\r
+               return new SimpleDateParser(pattern).parse(input);\r
+       }\r
+}\r
diff --git a/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/regex/Pattern.java b/src/com/itmill/toolkit/terminal/gwt/gwtwidgets/util/regex/Pattern.java
new file mode 100644 (file)
index 0000000..3a6d0b4
--- /dev/null
@@ -0,0 +1,176 @@
+/*\r
+ * Copyright 2006 Robert Hanson <iamroberthanson AT gmail.com>\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *    http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.itmill.toolkit.terminal.gwt.gwtwidgets.util.regex;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import com.google.gwt.core.client.JavaScriptObject;\r
+\r
+/**\r
+ * <p>\r
+ * Implementation of the {@link java.util.regex.Pattern} class with a\r
+ * wrapper aroung the Javascript <a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Regular_Expressions">RegExp</a> object.\r
+ * As most of the methods delegate to the JavaScript RegExp object, certain differences in the \r
+ * declaration and behaviour of regular expressions must be expected.\r
+ * </p>\r
+ * <p>\r
+ * Please note that neither the {@link java.util.regex.Pattern#compile(String)} method nor\r
+ * {@link Matcher} instances are supported. For the later, consider using {@link Pattern#match(String)}.\r
+ * </p>\r
+ * \r
+ * @author George Georgovassilis\r
+ *\r
+ */\r
+public class Pattern {\r
+\r
+       /**\r
+        * Declares that regular expressions should be matched across line borders.\r
+        */\r
+       public final static int MULTILINE = 1;\r
+\r
+       /**\r
+        * Declares that characters are matched reglardless of case.\r
+        */\r
+       public final static int CASE_INSENSITIVE = 2;\r
+\r
+       private JavaScriptObject regExp;\r
+\r
+       private static JavaScriptObject createExpression(String pattern, int flags) {\r
+               String sFlags = "";\r
+               if ((flags & MULTILINE) != 0)\r
+                       sFlags += "m";\r
+               if ((flags & CASE_INSENSITIVE) != 0)\r
+                       sFlags += "i";\r
+               return _createExpression(pattern, sFlags);\r
+       }\r
+\r
+       private static native JavaScriptObject _createExpression(String pattern,\r
+                       String flags)/*-{\r
+        return new RegExp(pattern, flags);\r
+        }-*/;\r
+\r
+       private native void _match(String text, List matches)/*-{\r
+        var regExp = this.@com.itmill.toolkit.terminal.gwt.gwtwidgets.util.regex.Pattern::regExp;\r
+        var result = text.match(regExp);\r
+        if (result == null) return;\r
+        for (var i=0;i<result.length;i++)\r
+        matches.@java.util.ArrayList::add(Ljava/lang/Object;)(result[i]);\r
+        }-*/;\r
+\r
+       /**\r
+        * Determines wether the specified regular expression is validated by the \r
+        * provided input.\r
+        * @param regex Regular expression\r
+        * @param input String to validate\r
+        * @return <code>true</code> if matched.\r
+        */\r
+       public static boolean matches(String regex, String input) {\r
+               return new Pattern(regex).matches(input);\r
+       }\r
+\r
+       /**\r
+        * Escape a provided string so that it will be interpreted as a literal\r
+        * in regular expressions.\r
+        * The current implementation does escape each character even if not neccessary,\r
+        * generating verbose literals.\r
+        * @param input\r
+        * @return\r
+        */\r
+       public static String quote(String input) {\r
+               String output = "";\r
+               for (int i = 0; i < input.length(); i++) {\r
+                       output += "\\" + input.charAt(i);\r
+               }\r
+               return output;\r
+       }\r
+\r
+       /**\r
+        * Class constructor\r
+        * @param pattern Regular expression\r
+        */\r
+       public Pattern(String pattern) {\r
+               this(pattern, 0);\r
+       }\r
+\r
+       /**\r
+        * Class constructor\r
+        * @param pattern Regular expression\r
+        * @param flags \r
+        */\r
+       public Pattern(String pattern, int flags) {\r
+               regExp = createExpression(pattern, flags);\r
+       }\r
+\r
+       /**\r
+        * This method is borrowed from the JavaScript RegExp object.\r
+        * It parses a string and returns as an array any assignments to parenthesis groups\r
+        * in the pattern's regular expression\r
+        * @param text\r
+        * @return Array of strings following java's Pattern convention for groups:\r
+        * Group 0 is the entire input string and the remaining groups are the matched parenthesis.\r
+        * In case nothing was matched an empty array is returned.\r
+        */\r
+       public String[] match(String text) {\r
+               List matches = new ArrayList();\r
+               _match(text, matches);\r
+               String arr[] = new String[matches.size()];\r
+               for (int i = 0; i < matches.size(); i++)\r
+                       arr[i] = matches.get(i).toString();\r
+               return arr;\r
+       }\r
+\r
+       /**\r
+        * Determines wether a provided text matches the regular expression\r
+        * @param text\r
+        * @return\r
+        */\r
+       public native boolean matches(String text)/*-{\r
+        var regExp = this.@com.itmill.toolkit.terminal.gwt.gwtwidgets.util.regex.Pattern::regExp;\r
+        return regExp.test(text);\r
+        }-*/;\r
+\r
+       /**\r
+        * Returns the regular expression for this pattern\r
+        * @return\r
+        */\r
+       public native String pattern()/*-{\r
+        var regExp = this.@com.itmill.toolkit.terminal.gwt.gwtwidgets.util.regex.Pattern::regExp;\r
+        return regExp.source;\r
+        }-*/;\r
+\r
+       private native void _split(String input, List results)/*-{\r
+        var regExp = this.@com.itmill.toolkit.terminal.gwt.gwtwidgets.util.regex.Pattern::regExp;\r
+        var parts = input.split(regExp);\r
+        for (var i=0;i<parts.length;i++)\r
+        results.@java.util.ArrayList::add(Ljava/lang/Object;)(parts[i] );\r
+        }-*/;\r
+       \r
+       /**\r
+        * Split an input string by the pattern's regular expression\r
+        * @param input\r
+        * @return Array of strings\r
+        */\r
+       public String[] split(String input){\r
+               List results = new ArrayList(); \r
+               _split(input, results);\r
+               String[] parts = new String[results.size()];\r
+               for (int i=0;i<results.size();i++)\r
+                       parts[i] = (String)results.get(i);\r
+               return parts;\r
+       }\r
+\r
+}\r
index 84ef27e2f37782bd761adf3d5e7f4a2cb71edcd2..5ea043f5f160b2c7c4a7ba364d115092ba44bd13 100644 (file)
@@ -15,4 +15,8 @@
        border-color: #4376c3;\r
        border-bottom-color: #6696dd;\r
        border-right-color: #6696dd;\r
+}\r
+\r
+.i-textfield-error {\r
+       background: #ff9999;\r
 }
\ No newline at end of file