From: Jouni Koivuviita Date: Mon, 9 Jul 2007 12:44:57 +0000 (+0000) Subject: DateField calendar style client-side implemetation fully functional. DateField now... X-Git-Tag: 6.7.0.beta1~6194 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=911cb83de60dea77958949ac41b943a0afa602bd;p=vaadin-framework.git DateField calendar style client-side implemetation fully functional. DateField now doesn't require a repaint after every value change, it supposes that the client is smart enough to update the view on its own. Fixed locale loading and parsing (now supports all possible locales found from JVM). svn changeset:1821/svn branch:trunk --- diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Client.java b/src/com/itmill/toolkit/terminal/gwt/client/Client.java index 556d4cf66f..b1151e0ac8 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/Client.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Client.java @@ -329,6 +329,14 @@ public class Client implements EntryPoint { else if (uidl.hasAttribute("readonly")) enabled = !uidl.getBooleanAttribute("readonly"); ((FocusWidget) component).setEnabled(enabled); + } else { + boolean enabled = true; + if (uidl.hasAttribute("disabled")) + enabled = !uidl.getBooleanAttribute("disabled"); + if(!enabled) + component.addStyleName("i-disabled"); + else + component.removeStyleName("i-disabled"); } boolean visible = !uidl.getBooleanAttribute("invisible"); component.setVisible(visible); diff --git a/src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java b/src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java index a5781c2fe5..7e92ff80a3 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/DateTimeService.java @@ -92,6 +92,39 @@ public class DateTimeService { return 0; } + public boolean isTwelveHourClock() { + try { + return LocaleService.isTwelveHourClock(currentLocale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return false; + } + + public String getClockDelimeter() { + try { + return LocaleService.getClockDelimiter(currentLocale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + return ":"; + } + + public String[] getAmPmStrings() { + try { + return LocaleService.getAmPmStrings(currentLocale); + } catch (LocaleNotLoadedException e) { + // TODO redirect to console + System.out.println(e + ":" + e.getMessage()); + } + String[] temp = new String[2]; + temp[0] = "AM"; + temp[1] = "PM"; + return temp; + } + public int getStartWeekDay(Date date){ Date dateForFirstOfThisMonth = new Date(date.getYear(), date.getMonth(), 1); int firstDay; diff --git a/src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java b/src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java index fdd6b99b8d..f5d9b1f344 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/LocaleService.java @@ -12,7 +12,7 @@ import com.google.gwt.json.client.JSONString; /** * Date / time etc. localisation service for all widgets. - * Should cache all loaded locales as JSON strings. + * Caches all loaded locales as JSONObjects. * * @author IT Mill Ltd. * @@ -148,5 +148,16 @@ public class LocaleService { return hmd.stringValue(); } else throw new LocaleNotLoadedException(locale); } + + public static String[] getAmPmStrings(String locale) throws LocaleNotLoadedException { + if(cache.containsKey(locale)) { + JSONObject l = (JSONObject) cache.get(locale); + JSONArray ampm = (JSONArray) l.get("ampm"); + String[] temp = new String[2]; + temp[0] = ((JSONString)ampm.get(0)).stringValue(); + temp[1] = ((JSONString)ampm.get(1)).stringValue(); + return temp; + } else throw new LocaleNotLoadedException(locale); + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendar.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendar.java index 1213c18099..b5ce2c7b4b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendar.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendar.java @@ -5,21 +5,18 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class ICalendar extends IDateField { - private ICalendarPanel body; - - private String locale; + private ICalendarPanel date; public ICalendar() { super(); - body = new ICalendarPanel(this); - container.add(body); + setStyleName(CLASSNAME+"-calendar"); + date = new ICalendarPanel(this); + add(date); } public void updateFromUIDL(UIDL uidl, Client client) { super.updateFromUIDL(uidl, client); - boolean needsRedraw = (locale == null || !locale.equals(currentLocale)); - body.updateCalendar(needsRedraw); - locale = currentLocale; + date.updateCalendar(); } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendarPanel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendarPanel.java index 32f60a7edd..fa540057a9 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendarPanel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICalendarPanel.java @@ -2,66 +2,119 @@ package com.itmill.toolkit.terminal.gwt.client.ui; import java.util.Date; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.FlexTable; +import com.google.gwt.user.client.ui.MouseListener; +import com.google.gwt.user.client.ui.MouseListenerCollection; +import com.google.gwt.user.client.ui.SourcesMouseEvents; +import com.google.gwt.user.client.ui.SourcesTableEvents; +import com.google.gwt.user.client.ui.TableListener; import com.google.gwt.user.client.ui.Widget; import com.itmill.toolkit.terminal.gwt.client.DateTimeService; +import com.itmill.toolkit.terminal.gwt.client.LocaleService; -public class ICalendarPanel extends FlexTable implements ClickListener { +public class ICalendarPanel extends FlexTable implements MouseListener, ClickListener { private IDateField datefield; - private IButton prevYear; - private IButton nextYear; - private IButton prevMonth; - private IButton nextMonth; + private IEventButton prevYear; + private IEventButton nextYear; + private IEventButton prevMonth; + private IEventButton nextMonth; + + private ITime time; + + /* Needed to identify resolution changes */ + private int resolution = IDateField.RESOLUTION_YEAR; + + /* Needed to identify locale changes */ + private String locale = LocaleService.getDefaultLocale(); public ICalendarPanel(IDateField parent) { datefield = parent; - // Force table size - setText(0, 0, ""); - setText(7, 6, ""); - buildCalendar(true); + setStyleName(datefield.CLASSNAME+"-calendarpanel"); + //buildCalendar(true); + addTableListener(new DateClickListener(this)); } - public void buildCalendar(boolean forceRedraw) { - buildCalendarHeader(forceRedraw); - buildCalendarBody(); + private void buildCalendar(boolean forceRedraw) { + boolean needsMonth = datefield.currentResolution > IDateField.RESOLUTION_YEAR; + boolean needsBody = datefield.currentResolution >= IDateField.RESOLUTION_DAY; + boolean needsTime = datefield.currentResolution >= IDateField.RESOLUTION_HOUR; + buildCalendarHeader(forceRedraw, needsMonth); + clearCalendarBody(!needsBody); + if(needsBody) + buildCalendarBody(); + if(needsTime) + buildTime(forceRedraw); + else if(time != null) { + remove(time); + time = null; + } } - - private void clearCalendarBody() { - for (int row=2; row < 8; row++){ - for (int col=0; col < 7; col++){ - setText(row, col, ""); + + private void clearCalendarBody(boolean remove) { + if(!remove) { + for (int row = 2; row < 8; row++) { + for (int col = 0; col < 7; col++) { + setHTML(row, col, " "); + } } + } else if(getRowCount() > 2) { + while(getRowCount() > 2) + removeRow(2); } } - private void buildCalendarHeader(boolean forceRedraw) { + private void buildCalendarHeader(boolean forceRedraw, boolean needsMonth) { if(forceRedraw) { - prevYear = new IButton(); prevYear.setText("«"); - nextYear = new IButton(); nextYear.setText("»"); - prevMonth = new IButton(); prevMonth.setText("‹"); - nextMonth = new IButton(); nextMonth.setText("›"); - 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); + if(prevMonth == null) { // Only do once + prevYear = new IEventButton(); prevYear.setHTML("«"); + nextYear = new IEventButton(); nextYear.setHTML("»"); + prevYear.addMouseListener(this); nextYear.addMouseListener(this); + prevYear.addClickListener(this); nextYear.addClickListener(this); + setWidget(0, 0, prevYear); + setWidget(0, 4, nextYear); + + if(needsMonth) { + prevMonth = new IEventButton(); prevMonth.setHTML("‹"); + nextMonth = new IEventButton(); nextMonth.setHTML("›"); + prevMonth.addMouseListener(this); nextMonth.addMouseListener(this); + prevMonth.addClickListener(this); nextMonth.addClickListener(this); + setWidget(0, 3, nextMonth); + setWidget(0, 1, prevMonth); + } + + getFlexCellFormatter().setColSpan(0, 2, 3); + } else if(!needsMonth){ + // Remove month traverse buttons + prevMonth.removeClickListener(this); + prevMonth.removeMouseListener(this); + nextMonth.removeClickListener(this); + nextMonth.removeMouseListener(this); + remove(prevMonth); + remove(nextMonth); + prevMonth = null; nextMonth = null; + } + // Print weekday names 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)); + if(datefield.currentResolution > IDateField.RESOLUTION_MONTH) + setHTML(1,i, "" + datefield.dts.getShortDay(day) + ""); + else + setHTML(1,i, ""); } } - String monthName = datefield.dts.getMonth(datefield.date.getMonth()); + String monthName = needsMonth? datefield.dts.getMonth(datefield.date.getMonth()) : ""; int year = datefield.date.getYear()+1900; - setText(0, 2, monthName + " " + year); + setHTML(0, 2, "" + monthName + " " + year + ""); } private void buildCalendarBody() { @@ -69,55 +122,159 @@ public class ICalendarPanel extends FlexTable implements ClickListener { int startWeekDay = datefield.dts.getStartWeekDay(date); int numDays = DateTimeService.getNumberOfDaysInMonth(date); int dayCount = 0; + Date today = new Date(); 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){ + if(!(row == 2 && col < startWeekDay)) { + if(dayCount < numDays){ int selectedDate = ++dayCount; - //cellValues[row][col] = selectedDate +""; - //if(true == isSelectedDate(date, selectedDate)){ - //setHTML(row, col, "" + selectedDate+""); - //}else{ - setText(row, col, ""+selectedDate); - //} + if(date.getDate() == dayCount){ + setHTML(row, col, "" + selectedDate + ""); + } else if(today.getDate() == dayCount && today.getMonth() == date.getMonth() && today.getYear() == date.getYear()){ + setHTML(row, col, "" + selectedDate + ""); + } else { + setHTML(row, col, "" + selectedDate + ""); + } } else { - setText(row, col, ""); - //cellValues[row][col] = ""; + break; } } } } } + private void buildTime(boolean forceRedraw) { + if(time == null) { + time = new ITime(datefield); + setText(8,0,""); // Add new row + getFlexCellFormatter().setColSpan(8, 0, 7); + setWidget(8, 0, time); + } + time.updateTime(forceRedraw); + } + /** * * @param forceRedraw Build all from scratch, in case of e.g. locale changes */ - public void updateCalendar(boolean forceRedraw) { - clearCalendarBody(); - buildCalendar(forceRedraw); + public void updateCalendar() { + // Locale and resolution changes force a complete redraw + buildCalendar(locale != datefield.currentLocale || resolution != datefield.currentResolution); + locale = datefield.currentLocale; + resolution = datefield.currentResolution; } public void onClick(Widget sender) { + processClickEvent(sender); + } + + private void processClickEvent(Widget sender) { + if(!datefield.enabled || datefield.readonly) + return; if(sender == prevYear) { datefield.date.setYear(datefield.date.getYear()-1); datefield.client.updateVariable(datefield.id, "year", datefield.date.getYear()+1900, datefield.immediate); - updateCalendar(false); + updateCalendar(); } 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); + updateCalendar(); } 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); + updateCalendar(); } 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); + updateCalendar(); + } + } + + private Timer timer; + + public void onMouseDown(final Widget sender, int x, int y) { + if(sender instanceof IEventButton) { + timer = new Timer() { + public void run() { + processClickEvent(sender); + } + }; + timer.scheduleRepeating(100); + } + } + + public void onMouseEnter(Widget sender) {} + + public void onMouseLeave(Widget sender) { + if(timer != null) + timer.cancel(); + } + + public void onMouseMove(Widget sender, int x, int y) {} + + public void onMouseUp(Widget sender, int x, int y) { + if(timer != null) + timer.cancel(); + } + + private class IEventButton extends IButton implements SourcesMouseEvents { + + private MouseListenerCollection mouseListeners; + + public IEventButton() { + super(); + sinkEvents(Event.FOCUSEVENTS | Event.KEYEVENTS | Event.ONCLICK + | Event.MOUSEEVENTS); + } + + public void addMouseListener(MouseListener listener) { + if (mouseListeners == null) { + mouseListeners = new MouseListenerCollection(); + } + mouseListeners.add(listener); + } + + public void removeMouseListener(MouseListener listener) { + if (mouseListeners != null) + mouseListeners.remove(listener); + } + + public void onBrowserEvent(Event event) { + super.onBrowserEvent(event); + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEDOWN: + case Event.ONMOUSEUP: + case Event.ONMOUSEMOVE: + case Event.ONMOUSEOVER: + case Event.ONMOUSEOUT: + if (mouseListeners != null) { + mouseListeners.fireMouseEvent(this, event); + } + break; + } + } + } + + private class DateClickListener implements TableListener { + + private ICalendarPanel cal; + + public DateClickListener(ICalendarPanel panel) { + cal = panel; + } + + public void onCellClicked(SourcesTableEvents sender, int row, int col) { + if(sender != cal || row < 2 || row > 7 || !cal.datefield.enabled || cal.datefield.readonly) + return; + + Integer day = new Integer(cal.getText(row, col)); + cal.datefield.date.setDate(day.intValue()); + cal.datefield.client.updateVariable(cal.datefield.id, "day", cal.datefield.date.getDate(), cal.datefield.immediate); + + // No need to update calendar header + cal.clearCalendarBody(false); + cal.buildCalendarBody(); } + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java index f4d980df17..358ef30c2d 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IDateField.java @@ -2,7 +2,6 @@ package com.itmill.toolkit.terminal.gwt.client.ui; import java.util.Date; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.itmill.toolkit.terminal.gwt.client.Client; import com.itmill.toolkit.terminal.gwt.client.DateTimeService; @@ -10,15 +9,13 @@ 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 { +public class IDateField extends FlowPanel implements Paintable { public static final String CLASSNAME = "i-datefield"; String id; Client client; - - protected FlowPanel container; protected boolean immediate; @@ -33,13 +30,19 @@ public class IDateField extends Composite implements Paintable { protected String currentLocale; + protected boolean readonly; + + protected boolean enabled; + protected Date date; + /* For easy access, because java.util.Date doesn't have getMilliseconds method */ + private int milliseconds = 0; + protected DateTimeService dts; public IDateField() { - container = new FlowPanel(); - initWidget(container); + setStyleName(CLASSNAME); date = new Date(); dts = new DateTimeService(); } @@ -51,8 +54,11 @@ public class IDateField extends Composite implements Paintable { // Save details this.client = client; - id = uidl.getId(); - immediate = uidl.getBooleanAttribute("immediate"); + this.id = uidl.getId(); + this.immediate = uidl.getBooleanAttribute("immediate"); + + readonly = uidl.getBooleanAttribute("readonly"); + enabled = !uidl.getBooleanAttribute("disabled"); if(uidl.hasAttribute("locale")) { String locale = uidl.getStringAttribute("locale"); @@ -60,61 +66,74 @@ public class IDateField extends Composite implements Paintable { dts.setLocale(locale); currentLocale = locale; } catch (LocaleNotLoadedException e) { - dts = new DateTimeService(); currentLocale = dts.getLocale(); + // TODO redirect this to console 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; - if(uidl.hasAttribute("day")) - newResolution = RESOLUTION_DAY; - if(uidl.hasAttribute("hour")) - newResolution = RESOLUTION_HOUR; - if(uidl.hasAttribute("min")) - newResolution = RESOLUTION_MIN; - if(uidl.hasAttribute("sec")) - newResolution = RESOLUTION_SEC; - if(uidl.hasAttribute("msec")) + + int newResolution; + if(uidl.hasVariable("msec")) newResolution = RESOLUTION_MSEC; - - if(currentResolution > newResolution) - container.clear(); + else if(uidl.hasVariable("sec")) + newResolution = RESOLUTION_SEC; + else if(uidl.hasVariable("min")) + newResolution = RESOLUTION_MIN; + else if(uidl.hasVariable("hour")) + newResolution = RESOLUTION_HOUR; + else if(uidl.hasVariable("day")) + newResolution = RESOLUTION_DAY; + else if(uidl.hasVariable("month")) + newResolution = RESOLUTION_MONTH; + else + newResolution = RESOLUTION_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"); + int year = uidl.getIntVariable("year"); + int month = (currentResolution >= RESOLUTION_MONTH)? uidl.getIntVariable("month") : -1; + int day = (currentResolution >= RESOLUTION_DAY)? uidl.getIntVariable("day") : -1; + int hour = (currentResolution >= RESOLUTION_HOUR)? uidl.getIntVariable("hour") : -1; + int min = (currentResolution >= RESOLUTION_MIN)? uidl.getIntVariable("min") : -1; + int sec = (currentResolution >= RESOLUTION_SEC)? uidl.getIntVariable("sec") : -1; + int msec = (currentResolution >= RESOLUTION_MSEC)? uidl.getIntVariable("msec") : -1; - date = new Date((long) buildDate(year, month, day, hour, min, sec, msec)); + // Construct new date for this datefield + date = new Date((long) buildTime(year, month, day, hour, min, sec, msec)); + milliseconds = msec<0? 0 : msec; } /* * We need this redundant native function because - * GWT hasn't implemented setMilliseconds to the Date class. + * Java's Date object doesn't have a setMilliseconds method. */ - private native double buildDate(int y, int m, int d, int h, int mi, int s, int ms) /*-{ + private static native double buildTime(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); + if(y && y >= 0) date.setFullYear(y); + if(m && m >= 1) date.setMonth(m-1); + if(d && d >= 0) date.setDate(d); + if(h && h >= 0) date.setHours(h); + if(mi && mi >= 0) date.setMinutes(mi); + if(s && s >= 0) date.setSeconds(s); + if(ms && ms >= 0) date.setMilliseconds(ms); return date.getTime(); } catch (e) { - console.error(e); + // TODO print some error message on the console + //console.log(e); + return (new Date()).getTime(); } }-*/; + + public int getMilliseconds() { + return milliseconds; + } + + public void setMilliseconds(int ms) { + long time = (long) buildTime(date.getYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), ms); + date = new Date(time); + milliseconds = ms; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java index 187d8e01d6..dbfff25850 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java @@ -8,10 +8,17 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL; public class ILabel extends HTML implements Paintable { public static final String CLASSNAME = "i-label"; + + public ILabel() { + super(); + } + + public ILabel(String text) { + super(text); + setStyleName(CLASSNAME); + } public void updateFromUIDL(UIDL uidl, Client client) { - - setStyleName(CLASSNAME); if (client.updateComponent(this, uidl, true)) return; 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 a93870f071..73993bbd70 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextualDate.java @@ -26,9 +26,9 @@ public class ITextualDate extends IDateField implements Paintable, ChangeListene if(uidl.hasVariable("year")) { int selectedYear = uidl.getIntVariable("year"); - int y = container.getWidgetIndex(year); + int y = getWidgetIndex(year); if(y > -1 || !currentLocale.equals(uidl.getStringAttribute("locale"))) { - year = (ListBox) container.getWidget(y); + year = (ListBox) getWidget(y); // Deselect old value year.setItemSelected(year.getSelectedIndex(), false); // and select new @@ -47,14 +47,14 @@ public class ITextualDate extends IDateField implements Paintable, ChangeListene year.setSelectedIndex(year.getItemCount()-1); } year.addChangeListener(this); - container.add(year); + add(year); } } if(uidl.hasVariable("month")) { int selectedMonth = uidl.getIntVariable("month"); - int y = container.getWidgetIndex(month); + int y = getWidgetIndex(month); if(y > -1) { - month = (ListBox) container.getWidget(y); + month = (ListBox) getWidget(y); // Deselect old value month.setItemSelected(month.getSelectedIndex(), false); // and select new @@ -73,14 +73,14 @@ public class ITextualDate extends IDateField implements Paintable, ChangeListene month.setSelectedIndex(month.getItemCount()-1); } month.addChangeListener(this); - container.add(month); + add(month); } } if(uidl.hasVariable("day")) { int selectedMonth = uidl.getIntVariable("day"); - int y = container.getWidgetIndex(day); + int y = getWidgetIndex(day); if(y > -1) { - day = (ListBox) container.getWidget(y); + day = (ListBox) getWidget(y); // Deselect old value day.setItemSelected(day.getSelectedIndex(), false); // and select new @@ -99,7 +99,7 @@ public class ITextualDate extends IDateField implements Paintable, ChangeListene day.setSelectedIndex(day.getItemCount()-1); } day.addChangeListener(this); - container.add(day); + add(day); } } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITime.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITime.java new file mode 100644 index 0000000000..f9207b0cf9 --- /dev/null +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITime.java @@ -0,0 +1,193 @@ +package com.itmill.toolkit.terminal.gwt.client.ui; + +import com.google.gwt.user.client.ui.ChangeListener; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.ListBox; +import com.google.gwt.user.client.ui.Widget; + +public class ITime extends FlowPanel implements ChangeListener { + + private IDateField datefield; + + private ListBox hours; + + private ListBox mins; + + private ListBox sec; + + private ListBox msec; + + private ListBox ampm; + + private int resolution = IDateField.RESOLUTION_HOUR; + + private boolean readonly; + + public ITime(IDateField parent) { + super(); + datefield = parent; + setStyleName(IDateField.CLASSNAME+"-time"); + } + + private void buildTime(boolean redraw) { + boolean thc = datefield.dts.isTwelveHourClock(); + if(redraw) { + clear(); + int numHours = thc?12:24; + hours = new ListBox(); + hours.setStyleName(ISelect.CLASSNAME); + for(int i=0; i= IDateField.RESOLUTION_MIN) { + mins = new ListBox(); + mins.setStyleName(ISelect.CLASSNAME); + for(int i=0; i<60; i++) + mins.addItem((i<10)?"0"+i:""+i); + mins.addChangeListener(this); + } + if(datefield.currentResolution >= IDateField.RESOLUTION_SEC) { + sec = new ListBox(); + sec.setStyleName(ISelect.CLASSNAME); + for(int i=0; i<60; i++) + sec.addItem((i<10)?"0"+i:""+i); + sec.addChangeListener(this); + } + if(datefield.currentResolution == IDateField.RESOLUTION_MSEC) { + msec = new ListBox(); + msec.setStyleName(ISelect.CLASSNAME); + for(int i=0; i<1000; i++) { + if(i<10) + msec.addItem("00"+i); + else if(i<100) + msec.addItem("0"+i); + else msec.addItem(""+i); + } + 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; + + if(ro) { + int h = datefield.date.getHours(); + if(thc) h -= h<12? 0 : 12; + add(new ILabel(h<10? "0"+h : ""+h)); + } else add(hours); + + if(datefield.currentResolution >= IDateField.RESOLUTION_MIN) { + add(new ILabel(delimiter)); + if(ro) { + int m = mins.getSelectedIndex(); + add(new ILabel(m<10? "0"+m : ""+m)); + } + else add(mins); + } + if(datefield.currentResolution >= IDateField.RESOLUTION_SEC) { + add(new ILabel(delimiter)); + if(ro) { + int s = sec.getSelectedIndex(); + add(new ILabel(s<10? "0"+s : ""+s)); + } + else add(sec); + } + if(datefield.currentResolution == IDateField.RESOLUTION_MSEC) { + add(new ILabel(".")); + if(ro) { + int m = datefield.getMilliseconds(); + String ms = m<100? "0"+m : ""+m; + add(new ILabel(m<10? "0"+ms : ms)); + } + else add(msec); + } + if(datefield.currentResolution == IDateField.RESOLUTION_HOUR) { + add(new ILabel(delimiter+"00")); // o'clock + } + if(thc) { + add(new ILabel(" ")); + if(ro) add(new ILabel(ampm.getItemText(datefield.date.getHours()<12? 0 : 1))); + else add(ampm); + } + + if(ro) return; + } + + boolean enabled = datefield.enabled; + hours.setEnabled(enabled); + if(mins != null) mins.setEnabled(enabled); + if(sec != null) sec.setEnabled(enabled); + if(msec != null) msec.setEnabled(enabled); + if(ampm != null) ampm.setEnabled(enabled); + + } + + public void updateTime(boolean redraw) { + buildTime(redraw || resolution != datefield.currentResolution + || readonly != datefield.readonly); + resolution = datefield.currentResolution; + readonly = datefield.readonly; + } + + public void onChange(Widget sender) { + if(sender == hours) { + int h = hours.getSelectedIndex(); + if(datefield.dts.isTwelveHourClock()) + h = h + ampm.getSelectedIndex()*12; + datefield.date.setHours(h); + datefield.client.updateVariable(datefield.id, "hour", h, datefield.immediate); + //updateTime(false); + } + else if(sender == mins) { + int m = mins.getSelectedIndex(); + datefield.date.setMinutes(m); + datefield.client.updateVariable(datefield.id, "min", m, datefield.immediate); + //updateTime(false); + } + else if(sender == sec) { + int s = sec.getSelectedIndex(); + datefield.date.setSeconds(s); + datefield.client.updateVariable(datefield.id, "sec", s, datefield.immediate); + //updateTime(false); + } + else if(sender == msec) { + int ms = msec.getSelectedIndex(); + datefield.setMilliseconds(ms); + datefield.client.updateVariable(datefield.id, "msec", ms, datefield.immediate); + //updateTime(false); + } + else if(sender == ampm) { + int h = hours.getSelectedIndex() + ampm.getSelectedIndex()*12; + datefield.date.setHours(h); + datefield.client.updateVariable(datefield.id, "hour", h, datefield.immediate); + //updateTime(false); + } + } + +} diff --git a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css index 7268334ddc..98f8c2507d 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css @@ -2,4 +2,5 @@ @import "textfield/css/textfield.css"; @import "select/css/select.css"; @import "panel/css/panel.css"; -@import "tabsheet/css/tabsheet.css"; \ No newline at end of file +@import "tabsheet/css/tabsheet.css"; +@import "datefield/css/datefield.css"; \ No newline at end of file diff --git a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/common/css/common.css b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/common/css/common.css index da33039187..46ac419287 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/common/css/common.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/common/css/common.css @@ -14,6 +14,11 @@ input, select, textarea, button { select { padding: 0; margin: 0; +} + +.i-disabled { + opacity: 0.3; + filter: alpha(opacity:30); } /* TODO move table styles to separate file */ diff --git a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/datefield/css/datefield.css b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/datefield/css/datefield.css new file mode 100644 index 0000000000..b990a94631 --- /dev/null +++ b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/datefield/css/datefield.css @@ -0,0 +1,71 @@ +.i-datefield-calendarpanel { + width: 22em; +} +.i-datefield-calendarpanel table { + width: 100%; +} +.i-datefield-calendarpanel td { + width: 14.2%; + text-align: center; + padding: 0; +} +.i-datefield-calendarpanel .i-button { + width: 22px; + height: 22px; + font-size: 1.1em; + padding: 0; + line-height: 1em; +} +.i-datefield-calendarpanel-month { + font-size: 1.1em; +} +.i-datefield-calendarpanel-day { + cursor: pointer; + padding: 0 3px; +} +.i-datefield-calendarpanel-day-today { + font-weight: bold; + border: 1px solid #aaa; + padding: 0 3px; + cursor: pointer; +} +.i-disabled .i-datefield-calendarpanel-day, +.i-disabled .i-datefield-calendarpanel-day-today { + cursor: default; +} +.i-datefield-calendarpanel-day-selected { + font-weight: bold; + color: #fff; + padding: 0 3px; + background-color: #1C3E6E; + cursor: default; +} +.i-datefield-time { + white-space: nowrap; +} +.i-datefield-time .i-label { + display: inline; +} + + +.i-datefield-calendar { + border: 1px solid #29528a; + padding: 5px; + background: #fff; +} +.i-datefield-calendar:before { + display: block; + height: 2px; + overflow: hidden; + background: transparent url(../../panel/img/top-right-small.png) no-repeat right top; + content: url(../../panel/img/top-left-small.png); + margin: -6px -6px 3px -6px; +} +.i-datefield-calendar:after { + display: block; + height: 2px; + overflow: hidden; + background: transparent url(../../panel/img/bottom-right.png) no-repeat right top; + content: url(../../panel/img/bottom-left.png); + margin: 5px -6px -6px -6px; +} \ 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 50215a1c35..bf59c5ca76 100644 --- a/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java @@ -108,7 +108,7 @@ public class AjaxApplicationManager implements public AjaxApplicationManager(Application application) { this.application = application; - requireLocale(application.getLocale().getLanguage()); + requireLocale(application.getLocale().toString()); } /** @@ -233,7 +233,7 @@ public class AjaxApplicationManager implements // Reset sent locales locales = null; - requireLocale(application.getLocale().getLanguage()); + requireLocale(application.getLocale().toString()); // Adds all non-native windows for (Iterator i = window.getApplication().getWindows() @@ -397,6 +397,12 @@ public class AjaxApplicationManager implements } outWriter.print("}"); + + /* ----------------------------- + * Sending Locale sensitive date + * ----------------------------- + */ + // Store JVM default locale for later restoration // (we'll have to change the default locale for a while) Locale jvmDefault = Locale.getDefault(); @@ -405,7 +411,7 @@ public class AjaxApplicationManager implements outWriter.print(", \"locales\":["); for(;pendingLocalesIndex < locales.size(); pendingLocalesIndex++) { - Locale l = new Locale((String) locales.get(pendingLocalesIndex)); + Locale l = generateLocale((String) locales.get(pendingLocalesIndex)); // Locale name outWriter.print("{\"name\":\"" + l.toString() + "\","); @@ -495,7 +501,10 @@ public class AjaxApplicationManager implements //outWriter.print("\"tf\":\"" + timeformat + "\","); outWriter.print("\"thc\":" + twelve_hour_clock + ","); outWriter.print("\"hmd\":\"" + hour_min_delimiter + "\""); - + if(twelve_hour_clock) { + String[] ampm = dfs.getAmPmStrings(); + outWriter.print(",\"ampm\":[\""+ampm[0]+"\",\""+ampm[1]+"\"]"); + } outWriter.print("}"); if(pendingLocalesIndex < locales.size()-1) outWriter.print(","); @@ -904,10 +913,20 @@ public class AjaxApplicationManager implements public void requireLocale(String value) { if(locales == null) { locales = new ArrayList(); - locales.add(application.getLocale().getLanguage()); + locales.add(application.getLocale().toString()); pendingLocalesIndex = 0; } if(!locales.contains(value)) locales.add(value); } + + private Locale generateLocale(String value) { + String[] temp = value.split("_"); + if(temp.length == 1) + return new Locale(temp[0]); + else if(temp.length == 2) + return new Locale(temp[0], temp[1]); + else + return new Locale(temp[0], temp[1], temp[2]); + } } diff --git a/src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java b/src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java index 0d13cb9e45..882dd8f140 100644 --- a/src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxJsonPaintTarget.java @@ -433,9 +433,9 @@ public class AjaxJsonPaintTarget implements PaintTarget, AjaxPaintTarget { * content is written. * * @param name - * the Boolean attribute name. + * the String attribute name. * @param value - * the Boolean attribute value. + * the String attribute value. * * @throws PaintException * if the paint operation failed. diff --git a/src/com/itmill/toolkit/ui/DateField.java b/src/com/itmill/toolkit/ui/DateField.java index 17a10e2423..350716a595 100644 --- a/src/com/itmill/toolkit/ui/DateField.java +++ b/src/com/itmill/toolkit/ui/DateField.java @@ -316,7 +316,7 @@ public class DateField extends AbstractField { if (newDate != oldDate && (newDate == null || !newDate.equals(oldDate))) - setValue(newDate); + setValue(newDate, true); // Don't require a repaint, client updates itself } } @@ -348,17 +348,22 @@ public class DateField extends AbstractField { */ public void setValue(Object newValue) throws Property.ReadOnlyException, Property.ConversionException { + setValue(newValue, false); + } + + public void setValue(Object newValue, boolean repaintIsNotNeeded) throws Property.ReadOnlyException, + Property.ConversionException { // Allows setting dates directly if (newValue == null || newValue instanceof Date) - super.setValue(newValue); + super.setValue(newValue, repaintIsNotNeeded); else { - + // Try to parse as string try { SimpleDateFormat parser = new SimpleDateFormat(); Date val = parser.parse(newValue.toString()); - super.setValue(val); + super.setValue(val, repaintIsNotNeeded); } catch (ParseException e) { throw new Property.ConversionException(e.getMessage()); }