瀏覽代碼

Localization services from serverside (AjaxApplicationManager), cached on clientside (LocaleService).

DateTimeService for all components, provides localised month and daynames etc.
New IDateField implementation: one superclass, which different proper implementations extend.
Partially working version of "calendar"-style for DateField.

svn changeset:1816/svn branch:trunk
tags/6.7.0.beta1
Jouni Koivuviita 17 年之前
父節點
當前提交
28ca6dc78a

+ 9
- 27
src/com/itmill/toolkit/terminal/gwt/client/Client.java 查看文件

@@ -42,6 +42,8 @@ public class Client implements EntryPoint {
private HashMap paintables = new HashMap();

private WidgetFactory widgetFactory = new DefaultWidgetFactory();
private LocaleService locale;

/**
* This is the entry point method.
@@ -121,6 +123,13 @@ public class Client implements EntryPoint {
String key = (String) i.next();
resourcesMap.put(key, ((JSONString)resources.get(key)).stringValue());
}
// Store locale data
if(((JSONObject)json).containsKey("locales")) {
JSONArray l = (JSONArray) ((JSONObject) json).get("locales");
for(int i=0; i < l.size(); i++)
LocaleService.addLocale((JSONObject) l.get(i));
}

// Process changes
JSONArray changes = (JSONArray) ((JSONObject) json).get("changes");
@@ -353,31 +362,4 @@ public class Client implements EntryPoint {
public String getResource(String name) {
return (String) resourcesMap.get(name);
}

public JSONObject getLocale(String locale) {
// TODO should perform synchronous call to server to fetch
// locale specific strings
// (GWT only supports synchrounous requests from v. 1.4)
console.log("Loading a new locale: " + locale);
rb = new RequestBuilder(RequestBuilder.POST, appUri
+ "/locale/?requestId=" + (Math.random()) + "&" + locale);
/*try {
rb.sendRequest(locale, new RequestCallback() {
public void onError(Request request, Throwable exception) {
console.error("Got error");
}

public void onResponseReceived(Request request,
Response response) {
handleReceivedJSONMessage(response);
}

});

} catch (RequestException e) {
console.error(e.getMessage());
}*/
// TODO
return null;
}
}

+ 106
- 18
src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java 查看文件

@@ -1,44 +1,132 @@
package com.itmill.toolkit.terminal.gwt.client;
import java.util.Date;
/**
* This class provides date/time parsing services to all components.
* This class provides date/time parsing services to
* all components on the client side.
*
* @author Jouni Koivuviita
* @author IT Mill Ltd.
*
*/
public class DateTimeService {
private LocaleService localeService;
private String currentLocale;
public DateTimeService(Client client) {
localeService = new LocaleService(client);
private static int [] maxDaysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/**
* Creates a new date time service with the application default locale.
*/
public DateTimeService() {
currentLocale = LocaleService.getDefaultLocale();
}
public DateTimeService(Client client, String locale) {
this(client);
/**
* Creates a new date time service with a given locale.
*
* @param locale e.g. fi, en etc.
* @throws LocaleNotLoadedException
*/
public DateTimeService(String locale) throws LocaleNotLoadedException {
setLocale(locale);
}
public void setLocale(String locale) {
currentLocale = locale;
public void setLocale(String locale) throws LocaleNotLoadedException {
if(LocaleService.getAvailableLocales().contains(locale))
currentLocale = locale;
else throw new LocaleNotLoadedException(locale);
}
public String getLocale() {
return currentLocale;
}
public String getMonth(int month) throws Exception {
if(currentLocale != null)
return localeService.getMonthNames(currentLocale)[month];
else throw new Exception("No locale specified.");
public String getMonth(int month) {
try {
return LocaleService.getMonthNames(currentLocale)[month];
} catch (LocaleNotLoadedException e) {
// TODO redirect to console
System.out.println(e + ":" + e.getMessage());
}
return null;
}
public String getShortMonth(int month) {
try {
return LocaleService.getShortMonthNames(currentLocale)[month];
} catch (LocaleNotLoadedException e) {
// TODO redirect to console
System.out.println(e + ":" + e.getMessage());
}
return null;
}
public String getDay(int day) {
try {
return LocaleService.getDayNames(currentLocale)[day];
} catch (LocaleNotLoadedException e) {
// TODO redirect to console
System.out.println(e + ":" + e.getMessage());
}
return null;
}
public String getShortDay(int day) {
try {
return LocaleService.getShortDayNames(currentLocale)[day];
} catch (LocaleNotLoadedException e) {
// TODO redirect to console
System.out.println(e + ":" + e.getMessage());
}
return null;
}
public int getFirstDayOfWeek() {
try {
return LocaleService.getFirstDayOfWeek(currentLocale);
} catch (LocaleNotLoadedException e) {
// TODO redirect to console
System.out.println(e + ":" + e.getMessage());
}
return 0;
}
public int getStartWeekDay(Date date){
Date dateForFirstOfThisMonth = new Date(date.getYear(), date.getMonth(), 1);
int firstDay;
try {
firstDay = LocaleService.getFirstDayOfWeek(currentLocale);
} catch (LocaleNotLoadedException e) {
firstDay = 0;
// TODO redirect to console
System.out.println(e + ":" + e.getMessage());
}
int start = dateForFirstOfThisMonth.getDay() - firstDay;
if(start < 0) start = 6;
return start;
}
public static int getNumberOfDaysInMonth(Date date){
int month = date.getMonth();
if(month == 1 && true == isLeapYear(date))
return 29;
return maxDaysInMonth[month];
}
public String getShortMonth(int month) throws Exception {
if(currentLocale != null)
return localeService.getShortMonthNames(currentLocale)[month];
else throw new Exception("No locale specified.");
public static boolean isLeapYear(Date date){
// Instantiate the date for 1st March of that year
Date firstMarch = new Date(date.getYear(), 2, 1);
// Go back 1 day
long firstMarchTime = firstMarch.getTime();
long lastDayTimeFeb = firstMarchTime - (24*60*60*1000); // NUM_MILLISECS_A_DAY
//Instantiate new Date with this time
Date febLastDay = new Date(lastDayTimeFeb);
// Check for date in this new instance
return (29 == febLastDay.getDate()) ? true : false;
}
}

+ 11
- 3
src/com/itmill/toolkit/terminal/gwt/client/DefaultWidgetFactory.java 查看文件

@@ -3,10 +3,10 @@ package com.itmill.toolkit.terminal.gwt.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.ui.IButton;
import com.itmill.toolkit.terminal.gwt.client.ui.ICalendar;
import com.itmill.toolkit.terminal.gwt.client.ui.ICheckBox;
import com.itmill.toolkit.terminal.gwt.client.ui.IComponent;
import com.itmill.toolkit.terminal.gwt.client.ui.ICustomLayout;
import com.itmill.toolkit.terminal.gwt.client.ui.IDateField;
import com.itmill.toolkit.terminal.gwt.client.ui.IEmbedded;
import com.itmill.toolkit.terminal.gwt.client.ui.IGridLayout;
import com.itmill.toolkit.terminal.gwt.client.ui.IHorizontalLayout;
@@ -14,11 +14,13 @@ import com.itmill.toolkit.terminal.gwt.client.ui.ILabel;
import com.itmill.toolkit.terminal.gwt.client.ui.IOptionGroup;
import com.itmill.toolkit.terminal.gwt.client.ui.IPanel;
import com.itmill.toolkit.terminal.gwt.client.ui.IPasswordField;
import com.itmill.toolkit.terminal.gwt.client.ui.IPopupCalendar;
import com.itmill.toolkit.terminal.gwt.client.ui.ISelect;
import com.itmill.toolkit.terminal.gwt.client.ui.ITablePaging;
import com.itmill.toolkit.terminal.gwt.client.ui.ITabsheet;
import com.itmill.toolkit.terminal.gwt.client.ui.ITextArea;
import com.itmill.toolkit.terminal.gwt.client.ui.ITextField;
import com.itmill.toolkit.terminal.gwt.client.ui.ITextualDate;
import com.itmill.toolkit.terminal.gwt.client.ui.ITree;
import com.itmill.toolkit.terminal.gwt.client.ui.ITwinColSelect;
import com.itmill.toolkit.terminal.gwt.client.ui.IUnknownComponent;
@@ -82,8 +84,14 @@ public class DefaultWidgetFactory implements WidgetFactory {
}
return new ITablePaging();
}
if("datefield".equals(tag))
return new IDateField();
if("datefield".equals(tag)) {
if(uidl.hasAttribute("style"))
if("calendar".equals(uidl.getStringAttribute("style")))
return new ICalendar();
else if("text".equals(uidl.getStringAttribute("style")))
return new ITextualDate();
return new IPopupCalendar();
}

return new IUnknownComponent();
}

+ 13
- 0
src/com/itmill/toolkit/terminal/gwt/client/LocaleNotLoadedException.java 查看文件

@@ -0,0 +1,13 @@
package com.itmill.toolkit.terminal.gwt.client;
public class LocaleNotLoadedException extends Exception {
/**
* Serial generated by Eclipse.
*/
private static final long serialVersionUID = 2005227056545210838L;
public LocaleNotLoadedException(String locale) {
super(locale);
}
}

+ 120
- 49
src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java 查看文件

@@ -2,80 +2,151 @@ package com.itmill.toolkit.terminal.gwt.client;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONBoolean;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
/**
* Date / time etc. localisation service for all widgets.
* Should cache all loaded locales as JSON strings.
*
* @author Jouni Koivuviita
* @author IT Mill Ltd.
*
*/
public class LocaleService {
private Client client;
private static Map cache = new HashMap();
private static String defaultLocale;
public static void addLocale(JSONObject json) {
String key = ((JSONString)json.get("name")).stringValue();
if(cache.containsKey(key))
cache.remove(key);
cache.put(key, json);
if(cache.size()==1)
setDefaultLocale(key);
}
public static void setDefaultLocale(String locale) {
defaultLocale = locale;
}
private Map cache = new HashMap();
public static String getDefaultLocale() {
return defaultLocale;
}
public static Set getAvailableLocales() {
return cache.keySet();
}
public static String[] getMonthNames(String locale) throws LocaleNotLoadedException {
if(cache.containsKey(locale)) {
JSONObject l = (JSONObject) cache.get(locale);
JSONArray mn = (JSONArray) l.get("mn");
String[] temp = new String[12];
temp[0] = ((JSONString)mn.get(0)).stringValue();
temp[1] = ((JSONString)mn.get(1)).stringValue();
temp[2] = ((JSONString)mn.get(2)).stringValue();
temp[3] = ((JSONString)mn.get(3)).stringValue();
temp[4] = ((JSONString)mn.get(4)).stringValue();
temp[5] = ((JSONString)mn.get(5)).stringValue();
temp[6] = ((JSONString)mn.get(6)).stringValue();
temp[7] = ((JSONString)mn.get(7)).stringValue();
temp[8] = ((JSONString)mn.get(8)).stringValue();
temp[9] = ((JSONString)mn.get(9)).stringValue();
temp[10] = ((JSONString)mn.get(10)).stringValue();
temp[11] = ((JSONString)mn.get(11)).stringValue();
return temp;
} else throw new LocaleNotLoadedException(locale);
}
public LocaleService(Client client){
this.client = client;
public static String[] getShortMonthNames(String locale) throws LocaleNotLoadedException {
if(cache.containsKey(locale)) {
JSONObject l = (JSONObject) cache.get(locale);
JSONArray smn = (JSONArray) l.get("smn");
String[] temp = new String[12];
temp[0] = ((JSONString)smn.get(0)).stringValue();
temp[1] = ((JSONString)smn.get(1)).stringValue();
temp[2] = ((JSONString)smn.get(2)).stringValue();
temp[3] = ((JSONString)smn.get(3)).stringValue();
temp[4] = ((JSONString)smn.get(4)).stringValue();
temp[5] = ((JSONString)smn.get(5)).stringValue();
temp[6] = ((JSONString)smn.get(6)).stringValue();
temp[7] = ((JSONString)smn.get(7)).stringValue();
temp[8] = ((JSONString)smn.get(8)).stringValue();
temp[9] = ((JSONString)smn.get(9)).stringValue();
temp[10] = ((JSONString)smn.get(10)).stringValue();
temp[11] = ((JSONString)smn.get(11)).stringValue();
return temp;
} else throw new LocaleNotLoadedException(locale);
}
private void loadLocale(String locale) {
JSONObject resp = client.getLocale(locale);
cache.put(locale, resp);
public static String[] getDayNames(String locale) throws LocaleNotLoadedException{
if(cache.containsKey(locale)) {
JSONObject l = (JSONObject) cache.get(locale);
JSONArray dn = (JSONArray) l.get("dn");
String[] temp = new String[7];
temp[0] = ((JSONString)dn.get(0)).stringValue();
temp[1] = ((JSONString)dn.get(1)).stringValue();
temp[2] = ((JSONString)dn.get(2)).stringValue();
temp[3] = ((JSONString)dn.get(3)).stringValue();
temp[4] = ((JSONString)dn.get(4)).stringValue();
temp[5] = ((JSONString)dn.get(5)).stringValue();
temp[6] = ((JSONString)dn.get(6)).stringValue();
return temp;
} else throw new LocaleNotLoadedException(locale);
}
public String[] getMonthNames(String locale) {
// TODO
//if(cache.containsKey(locale))
//else loadLocale(locale);
String[] temp = new String[12];
temp[0] = "tammi"; temp[1] = "helmi"; temp[2] = "maalis"; temp[3] = "huhti";
temp[4] = "touko"; temp[5] = "kesä"; temp[6] = "heinä"; temp[7] = "elo";
temp[8] = "syys"; temp[9] = "loka"; temp[10] = "marras"; temp[11] = "joulu";
return temp;
public static String[] getShortDayNames(String locale) throws LocaleNotLoadedException {
if(cache.containsKey(locale)) {
JSONObject l = (JSONObject) cache.get(locale);
JSONArray sdn = (JSONArray) l.get("sdn");
String[] temp = new String[7];
temp[0] = ((JSONString)sdn.get(0)).stringValue();
temp[1] = ((JSONString)sdn.get(1)).stringValue();
temp[2] = ((JSONString)sdn.get(2)).stringValue();
temp[3] = ((JSONString)sdn.get(3)).stringValue();
temp[4] = ((JSONString)sdn.get(4)).stringValue();
temp[5] = ((JSONString)sdn.get(5)).stringValue();
temp[6] = ((JSONString)sdn.get(6)).stringValue();
return temp;
} else throw new LocaleNotLoadedException(locale);
}
public String[] getShortMonthNames(String locale) {
// TODO
//if(cache.containsKey(locale))
//else loadLocale(locale);
String[] temp = new String[12];
temp[0] = "tam"; temp[1] = "hel"; temp[2] = "maa"; temp[3] = "huh";
temp[4] = "tou"; temp[5] = "kes"; temp[6] = "hei"; temp[7] = "elo";
temp[8] = "syy"; temp[9] = "lok"; temp[10] = "mar"; temp[11] = "jou";
return temp;
public static int getFirstDayOfWeek(String locale) throws LocaleNotLoadedException {
if(cache.containsKey(locale)) {
JSONObject l = (JSONObject) cache.get(locale);
JSONNumber fdow = (JSONNumber) l.get("fdow");
return (int) fdow.getValue();
} else throw new LocaleNotLoadedException(locale);
}
public String[] getDayNames(String locale) {
// TODO
//if(cache.containsKey(locale))
//else loadLocale(locale);
String[] temp = new String[7];
temp[1] = "maanatai"; temp[2] = "tiistai"; temp[3] = "keskiviikko";
temp[4] = "torstai"; temp[5] = "perjantai"; temp[6] = "lauantai";
temp[0] = "sunnuntai";
return temp;
public static String getDateFormat(String locale) throws LocaleNotLoadedException {
if(cache.containsKey(locale)) {
JSONObject l = (JSONObject) cache.get(locale);
JSONString df = (JSONString) l.get("df");
return df.stringValue();
} else throw new LocaleNotLoadedException(locale);
}
public String[] getShortDayNames(String locale) {
// TODO
//if(cache.containsKey(locale))
//else loadLocale(locale);
String[] temp = new String[7];
temp[1] = "ma"; temp[2] = "ti"; temp[3] = "ke";
temp[4] = "to"; temp[5] = "pe"; temp[6] = "la";
temp[0] = "su";
return temp;
public static boolean isTwelveHourClock(String locale) throws LocaleNotLoadedException {
if(cache.containsKey(locale)) {
JSONObject l = (JSONObject) cache.get(locale);
JSONBoolean thc = (JSONBoolean) l.get("thc");
return thc.booleanValue();
} else throw new LocaleNotLoadedException(locale);
}
public int getFirstDayOfWeek(String locale) {
// TODO
//if(cache.containsKey(locale))
//else loadLocale(locale);
return 1;
public static String getClockDelimiter(String locale) throws LocaleNotLoadedException {
if(cache.containsKey(locale)) {
JSONObject l = (JSONObject) cache.get(locale);
JSONString hmd = (JSONString) l.get("hmd");
return hmd.stringValue();
} else throw new LocaleNotLoadedException(locale);
}
}

+ 25
- 0
src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendar.java 查看文件

@@ -0,0 +1,25 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
import com.itmill.toolkit.terminal.gwt.client.Client;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
public class ICalendar extends IDateField {
private ICalendarPanel body;
private String locale;
public ICalendar() {
super();
body = new ICalendarPanel(this);
container.add(body);
}
public void updateFromUIDL(UIDL uidl, Client client) {
super.updateFromUIDL(uidl, client);
boolean needsRedraw = (locale == null || !locale.equals(currentLocale));
body.updateCalendar(needsRedraw);
locale = currentLocale;
}
}

+ 123
- 0
src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendarPanel.java 查看文件

@@ -0,0 +1,123 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
import java.util.Date;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.DateTimeService;
public class ICalendarPanel extends FlexTable implements ClickListener {
private IDateField datefield;
private IButton prevYear;
private IButton nextYear;
private IButton prevMonth;
private IButton nextMonth;
public ICalendarPanel(IDateField parent) {
datefield = parent;
// Force table size
setText(0, 0, "");
setText(7, 6, "");
buildCalendar(true);
}
public void buildCalendar(boolean forceRedraw) {
buildCalendarHeader(forceRedraw);
buildCalendarBody();
}
private void clearCalendarBody() {
for (int row=2; row < 8; row++){
for (int col=0; col < 7; col++){
setText(row, col, "");
}
}
}
private void buildCalendarHeader(boolean forceRedraw) {
if(forceRedraw) {
prevYear = new IButton(); prevYear.setText("&laquo;");
nextYear = new IButton(); nextYear.setText("&raquo;");
prevMonth = new IButton(); prevMonth.setText("&lsaquo;");
nextMonth = new IButton(); nextMonth.setText("&rsaquo;");
prevYear.addClickListener(this); nextYear.addClickListener(this);
prevMonth.addClickListener(this); nextMonth.addClickListener(this);setWidget(0, 0, prevYear);
setWidget(0, 1, prevMonth);
setWidget(0, 3, nextMonth);
setWidget(0, 4, nextYear);
getFlexCellFormatter().setColSpan(0, 2, 3);
int firstDay = datefield.dts.getFirstDayOfWeek();
for(int i = 0; i < 7; i++) {
int day = i + firstDay;
if(day > 6) day = 0;
setText(1,i, datefield.dts.getShortDay(day));
}
}
String monthName = datefield.dts.getMonth(datefield.date.getMonth());
int year = datefield.date.getYear()+1900;
setText(0, 2, monthName + " " + year);
}
private void buildCalendarBody() {
Date date = datefield.date;
int startWeekDay = datefield.dts.getStartWeekDay(date);
int numDays = DateTimeService.getNumberOfDaysInMonth(date);
int dayCount = 0;
for (int row = 2; row < 8; row++){
for (int col = 0; col < 7; col++){
if(row == 2 && col < startWeekDay){
setText(row, col, "");
//cellValues[row][col] = "";
} else {
if(numDays > dayCount){
int selectedDate = ++dayCount;
//cellValues[row][col] = selectedDate +"";
//if(true == isSelectedDate(date, selectedDate)){
//setHTML(row, col, "<font class='currentDate'>" + selectedDate+"<font>");
//}else{
setText(row, col, ""+selectedDate);
//}
} else {
setText(row, col, "");
//cellValues[row][col] = "";
}
}
}
}
}
/**
*
* @param forceRedraw Build all from scratch, in case of e.g. locale changes
*/
public void updateCalendar(boolean forceRedraw) {
clearCalendarBody();
buildCalendar(forceRedraw);
}
public void onClick(Widget sender) {
if(sender == prevYear) {
datefield.date.setYear(datefield.date.getYear()-1);
datefield.client.updateVariable(datefield.id, "year", datefield.date.getYear()+1900, datefield.immediate);
updateCalendar(false);
} else if(sender == nextYear) {
datefield.date.setYear(datefield.date.getYear()+1);
datefield.client.updateVariable(datefield.id, "year", datefield.date.getYear()+1900, datefield.immediate);
updateCalendar(false);
} else if(sender == prevMonth) {
datefield.date.setMonth(datefield.date.getMonth()-1);
datefield.client.updateVariable(datefield.id, "month", datefield.date.getMonth()+1, datefield.immediate);
updateCalendar(false);
} else if(sender == nextMonth) {
datefield.date.setMonth(datefield.date.getMonth()+1);
datefield.client.updateVariable(datefield.id, "month", datefield.date.getMonth()+1, datefield.immediate);
updateCalendar(false);
}
}
}

+ 62
- 68
src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java 查看文件

@@ -2,61 +2,46 @@ package com.itmill.toolkit.terminal.gwt.client.ui;
import java.util.Date;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.Client;
import com.itmill.toolkit.terminal.gwt.client.DateTimeService;
import com.itmill.toolkit.terminal.gwt.client.LocaleNotLoadedException;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
public class IDateField extends Composite implements Paintable, ChangeListener {
/*
* This implementation is old already.
* We should use the DateTimeService class (which is a draft) to get
* locale specific strings and use them to build the datefield
* and its different styles (with inheritance of course).
*
* Drafting usage patterns:
*
* DateTimeService dts = new DateTimeService(client, "fi_FI");
* String month = dts.getMonth(0); // Returns "January"
* String day = dts.getDay(19); // Returns e.g. "sunday"
* String dateformat = dts.getDateFormat(); // Returns something like MM_/_DD_/_YYYY
* String timeformat = dts.getTimeFormat(); // Returns something like HH_:_MM
* String date = dts.parseDate(new Date()); // Returns e.g. 6/19/2007 14:32
* String date = dts.parseFullDate(new Date()); // Returns e.g. Tuesday 6th June 2007 14:32
*/
public class IDateField extends Composite implements Paintable {
public static final String CLASSNAME = "i-datefield";
String id;
Client client;
protected FlowPanel container;
private boolean immediate;
protected boolean immediate;
private FlowPanel container;
protected static int RESOLUTION_YEAR = 0;
protected static int RESOLUTION_MONTH = 1;
protected static int RESOLUTION_DAY = 2;
protected static int RESOLUTION_HOUR = 3;
protected static int RESOLUTION_MIN = 4;
protected static int RESOLUTION_SEC = 5;
protected static int RESOLUTION_MSEC = 6;
protected int currentResolution = RESOLUTION_YEAR;
private ListBox year;
protected String currentLocale;
private static int RESOLUTION_YEAR = 0;
private static int RESOLUTION_MONTH = 1;
private static int RESOLUTION_DAY = 2;
private static int RESOLUTION_HOUR = 3;
private static int RESOLUTION_MIN = 4;
private static int RESOLUTION_SEC = 5;
private static int RESOLUTION_MSEC = 6;
private int currentResolution = RESOLUTION_YEAR;
protected Date date;
protected DateTimeService dts;
public IDateField() {
container = new FlowPanel();
initWidget(container);
date = new Date();
dts = new DateTimeService();
}
public void updateFromUIDL(UIDL uidl, Client client) {
@@ -69,6 +54,18 @@ public class IDateField extends Composite implements Paintable, ChangeListener {
id = uidl.getId();
immediate = uidl.getBooleanAttribute("immediate");
if(uidl.hasAttribute("locale")) {
String locale = uidl.getStringAttribute("locale");
try {
dts.setLocale(locale);
currentLocale = locale;
} catch (LocaleNotLoadedException e) {
dts = new DateTimeService();
currentLocale = dts.getLocale();
System.out.println("Tried to use an unloaded locale \"" + locale + "\". Using default locale (" + currentLocale + ").");
}
}
int newResolution = RESOLUTION_YEAR;
if(uidl.hasAttribute("month"))
newResolution = RESOLUTION_MONTH;
@@ -86,41 +83,38 @@ public class IDateField extends Composite implements Paintable, ChangeListener {
if(currentResolution > newResolution)
container.clear();
if(uidl.hasVariable("year")) {
int selectedYear = uidl.getIntVariable("year");
int y = container.getWidgetIndex(year);
if(y > -1) {
year = (ListBox) container.getWidget(y);
// Deselect old value
year.setItemSelected(year.getSelectedIndex(), false);
// and select new
for(int i=0; i < year.getItemCount(); i++)
if(year.getValue(i).equals(""+selectedYear)) {
year.setSelectedIndex(i);
break;
}
} else {
year = new ListBox();
year.setStyleName(ISelect.CLASSNAME);
int today = 1900 + (new Date()).getYear();
for(int i=1970; i<today+400; i++) {
year.addItem(""+i, ""+i);
if(i == selectedYear)
year.setSelectedIndex(year.getItemCount()-1);
}
year.addChangeListener(this);
container.add(year);
}
}
currentResolution = newResolution;
int year = uidl.getIntAttribute("year");
int month = uidl.getIntAttribute("month");
int day = uidl.getIntAttribute("day");
int hour = uidl.getIntAttribute("hour");
int min = uidl.getIntAttribute("min");
int sec = uidl.getIntAttribute("sec");
int msec = uidl.getIntAttribute("msec");
currentResolution = newResolution;
}
public void onChange(Widget sender) {
if(sender == year && client != null)
client.updateVariable(id, "year", year.getValue(year.getSelectedIndex()), immediate);
date = new Date((long) buildDate(year, month, day, hour, min, sec, msec));
}
/*
* We need this redundant native function because
* GWT hasn't implemented setMilliseconds to the Date class.
*/
private native double buildDate(int y, int m, int d, int h, int mi, int s, int ms) /*-{
try {
var date = new Date();
if(y) date.setFullYear(y-1900);
if(m) date.setMonth(m-1);
if(d) date.setDate(d);
if(h) date.setHour(h);
if(mi) date.setMinutes(mi);
if(s) date.setSeconds(s);
if(ms) date.setMilliseconds(ms);
return date.getTime();
} catch (e) {
console.error(e);
}
}-*/;
}

+ 5
- 0
src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupCalendar.java 查看文件

@@ -0,0 +1,5 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
public class IPopupCalendar extends IDateField {
}

+ 113
- 0
src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java 查看文件

@@ -0,0 +1,113 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
import java.util.Date;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.Client;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
public class ITextualDate extends IDateField implements Paintable, ChangeListener {
private ListBox year;
private ListBox month;
private ListBox day;
public ITextualDate() {
}
public void updateFromUIDL(UIDL uidl, Client client) {
super.updateFromUIDL(uidl, client);
if(uidl.hasVariable("year")) {
int selectedYear = uidl.getIntVariable("year");
int y = container.getWidgetIndex(year);
if(y > -1 || !currentLocale.equals(uidl.getStringAttribute("locale"))) {
year = (ListBox) container.getWidget(y);
// Deselect old value
year.setItemSelected(year.getSelectedIndex(), false);
// and select new
for(int i=0; i < year.getItemCount(); i++)
if(year.getValue(i).equals(""+selectedYear)) {
year.setSelectedIndex(i);
break;
}
} else {
year = new ListBox();
year.setStyleName(ISelect.CLASSNAME);
int today = 1900 + (new Date()).getYear();
for(int i=1970; i<today+400; i++) {
year.addItem(""+i, ""+i);
if(i == selectedYear)
year.setSelectedIndex(year.getItemCount()-1);
}
year.addChangeListener(this);
container.add(year);
}
}
if(uidl.hasVariable("month")) {
int selectedMonth = uidl.getIntVariable("month");
int y = container.getWidgetIndex(month);
if(y > -1) {
month = (ListBox) container.getWidget(y);
// Deselect old value
month.setItemSelected(month.getSelectedIndex(), false);
// and select new
for(int i=0; i < month.getItemCount(); i++)
if(month.getValue(i).equals(""+selectedMonth)) {
month.setSelectedIndex(i);
break;
}
} else {
month = new ListBox();
month.setStyleName(ISelect.CLASSNAME);
int today = (new Date()).getMonth();
for(int i=0; i<12; i++) {
month.addItem(""+(i+1), ""+i);
if(i == selectedMonth)
month.setSelectedIndex(month.getItemCount()-1);
}
month.addChangeListener(this);
container.add(month);
}
}
if(uidl.hasVariable("day")) {
int selectedMonth = uidl.getIntVariable("day");
int y = container.getWidgetIndex(day);
if(y > -1) {
day = (ListBox) container.getWidget(y);
// Deselect old value
day.setItemSelected(day.getSelectedIndex(), false);
// and select new
for(int i=0; i <day.getItemCount(); i++)
if(day.getValue(i).equals(""+selectedMonth)) {
day.setSelectedIndex(i);
break;
}
} else {
day = new ListBox();
day.setStyleName(ISelect.CLASSNAME);
int today = (new Date()).getDay();
for(int i=0; i<31; i++) {
day.addItem(""+(i+1), ""+i);
if(i == selectedMonth)
day.setSelectedIndex(day.getItemCount()-1);
}
day.addChangeListener(this);
container.add(day);
}
}
}
public void onChange(Widget sender) {
if(sender == year && client != null)
client.updateVariable(id, "year", year.getValue(year.getSelectedIndex()), immediate);
}
}

+ 133
- 1
src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java 查看文件

@@ -35,13 +35,18 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
@@ -96,9 +101,14 @@ public class AjaxApplicationManager implements
private Set removedWindows = new HashSet();

private PaintTarget paintTarget;
private List locales;
private int pendingLocalesIndex;

public AjaxApplicationManager(Application application) {
this.application = application;
requireLocale(application.getLocale().getLanguage());
}

/**
@@ -220,6 +230,10 @@ public class AjaxApplicationManager implements
if (repaintAll) {
paintables = new LinkedHashSet();
paintables.add(window);
// Reset sent locales
locales = null;
requireLocale(application.getLocale().getLanguage());

// Adds all non-native windows
for (Iterator i = window.getApplication().getWindows()
@@ -382,7 +396,115 @@ public class AjaxApplicationManager implements
}
}
outWriter.print("}");

// Store JVM default locale for later restoration
// (we'll have to change the default locale for a while)
Locale jvmDefault = Locale.getDefault();
// Send locale informations to client
outWriter.print(", \"locales\":[");
for(;pendingLocalesIndex < locales.size(); pendingLocalesIndex++) {
Locale l = new Locale((String) locales.get(pendingLocalesIndex));
// Locale name
outWriter.print("{\"name\":\"" + l.toString() + "\",");
/*
* Month names (both short and full)
*/
DateFormatSymbols dfs = new DateFormatSymbols(l);
String[] short_months = dfs.getShortMonths();
String[] months = dfs.getMonths();
outWriter.print("\"smn\":[\"" + // ShortMonthNames
short_months[0] + "\",\"" +
short_months[1] + "\",\"" +
short_months[2] + "\",\"" +
short_months[3] + "\",\"" +
short_months[4] + "\",\"" +
short_months[5] + "\",\"" +
short_months[6] + "\",\"" +
short_months[7] + "\",\"" +
short_months[8] + "\",\"" +
short_months[9] + "\",\"" +
short_months[10] + "\",\"" +
short_months[11] + "\"" +
"],");
outWriter.print("\"mn\":[\"" + // MonthNames
months[0] + "\",\"" +
months[1] + "\",\"" +
months[2] + "\",\"" +
months[3] + "\",\"" +
months[4] + "\",\"" +
months[5] + "\",\"" +
months[6] + "\",\"" +
months[7] + "\",\"" +
months[8] + "\",\"" +
months[9] + "\",\"" +
months[10] + "\",\"" +
months[11] + "\"" +
"],");
/*
* Weekday names (both short and full)
*/
String[] short_days = dfs.getShortWeekdays();
String[] days = dfs.getWeekdays();
outWriter.print("\"sdn\":[\"" + // ShortDayNames
short_days[1] + "\",\"" +
short_days[2] + "\",\"" +
short_days[3] + "\",\"" +
short_days[4] + "\",\"" +
short_days[5] + "\",\"" +
short_days[6] + "\",\"" +
short_days[7] + "\"" +
"],");
outWriter.print("\"dn\":[\"" + // DayNames
days[1] + "\",\"" +
days[2] + "\",\"" +
days[3] + "\",\"" +
days[4] + "\",\"" +
days[5] + "\",\"" +
days[6] + "\",\"" +
days[7] + "\"" +
"],");
/*
* First day of week (0 = sunday, 1 = monday)
*/
Calendar cal = new GregorianCalendar(l);
outWriter.print("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ",");
/*
* Date formatting (MM/DD/YYYY etc.)
*/
// 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 + "\",");
/*
* 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
// 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)
String hour_min_delimiter = timeformat.contains(".")? "." : ":";
//outWriter.print("\"tf\":\"" + timeformat + "\",");
outWriter.print("\"thc\":" + twelve_hour_clock + ",");
outWriter.print("\"hmd\":\"" + hour_min_delimiter + "\"");
outWriter.print("}");
if(pendingLocalesIndex < locales.size()-1)
outWriter.print(",");
}
outWriter.print("]"); // Close locales
// Restore JVM default locale
Locale.setDefault(jvmDefault);
outWriter.flush();
outWriter.close();
out.flush();
@@ -778,4 +900,14 @@ public class AjaxApplicationManager implements
return this.owner;
}
}

public void requireLocale(String value) {
if(locales == null) {
locales = new ArrayList();
locales.add(application.getLocale().getLanguage());
pendingLocalesIndex = 0;
}
if(!locales.contains(value))
locales.add(value);
}
}

+ 3
- 0
src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java 查看文件

@@ -450,6 +450,9 @@ public class AjaxJsonPaintTarget implements PaintTarget, AjaxPaintTarget {

if (customLayoutArgumentsOpen && "style".equals(name))
getPreCachedResources().add("layout/" + value + ".html");
if(name.equals("locale"))
manager.requireLocale(value);

}


Loading…
取消
儲存