Merging in date picker branch into 1.6.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4264 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/eclipse/reference/code-museum/.checkstyle b/eclipse/reference/code-museum/.checkstyle
new file mode 100644
index 0000000..223d35d
--- /dev/null
+++ b/eclipse/reference/code-museum/.checkstyle
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fileset-config file-format-version="1.2.0" simple-config="true">
+ <fileset name="all" enabled="true" check-config-name="GWT Checks" local="false">
+ <file-match-pattern match-pattern="." include-pattern="true"/>
+ </fileset>
+</fileset-config>
diff --git a/reference/code-museum/src/com/google/gwt/museum/SingleIssue.gwt.xml b/reference/code-museum/src/com/google/gwt/museum/SingleIssue.gwt.xml
index dc1f1f3..0920476 100644
--- a/reference/code-museum/src/com/google/gwt/museum/SingleIssue.gwt.xml
+++ b/reference/code-museum/src/com/google/gwt/museum/SingleIssue.gwt.xml
@@ -2,11 +2,12 @@
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
+ <inherits name='com.google.gwt.museum.Museum'/>
<inherits name="com.google.gwt.user.theme.standard.StandardResources"/>
<!-- Specify the app entry point class. -->
- <entry-point class='com.google.gwt.museum.client.defaultmuseum.Issue2703'/>
+ <entry-point class='com.google.gwt.museum.client.defaultmuseum.VisualsForDateBox'/>
<source path="client/common"/>
- <source path="client/defaultmuseum" includes="Issue2703.java"/>
+ <source path="client/defaultmuseum"/>
<source path="client/viewer"/>
</module>
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
index 2f894bb..60e3bd1 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
@@ -50,6 +50,8 @@
}
public void addVisuals() {
+ addIssue(new VisualsForDateBox());
+ addIssue(new VisualsForDatePicker());
addIssue(new VisualsForDisclosurePanelEvents());
addIssue(new VisualsForEventsFiring());
addIssue(new VisualsForPopupEvents());
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDateBox.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDateBox.java
new file mode 100644
index 0000000..a4423a6
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDateBox.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.datepicker.client.DateBox;
+import com.google.gwt.user.datepicker.client.DatePicker;
+import com.google.gwt.user.datepicker.client.DateBox.InvalidDateReporter;
+
+import java.util.Date;
+
+/**
+ * Visuals for date box.
+ */
+public class VisualsForDateBox extends AbstractIssue {
+
+ @Override
+ public Widget createIssue() {
+ VerticalPanel v = new VerticalPanel();
+ v.add(new HTML("<div style='height:25px'></div>"));
+ v.add(dateRange());
+ v.add(new HTML("<div style='height:25px'></div>"));
+ final Label startErrors = makeErrorLabel();
+
+ Widget errorReportingDateBox = dateRange(new DateBox.InvalidDateReporter() {
+ public void clearError() {
+ startErrors.setText("");
+ }
+ public void reportError(String input) {
+ startErrors.setText("\"" + input + "\" is not a date");
+ }
+ });
+
+ v.add(errorReportingDateBox);
+ v.add(startErrors);
+
+ return v;
+ }
+
+ @Override
+ public String getInstructions() {
+ return "Click on first date box, see that date picker is displayed, "
+ + "use arrow keys to navigate to second date box, select a date. "
+ + "The second set includes an error display (one, shared by both "
+ + "fields). See that it notices when you type garbage, and that "
+ + "its error message is cleared when you empty the field or provide "
+ + "a valid date.";
+ }
+
+ @Override
+ public String getSummary() {
+ return "date box visual test";
+ }
+
+ @Override
+ public boolean hasCSS() {
+ return false;
+ }
+
+ private Widget dateRange() {
+ return dateRange(null);
+ }
+
+ private Widget dateRange(InvalidDateReporter invalidDateReporter) {
+ VerticalPanel v = new VerticalPanel();
+ HorizontalPanel p = new HorizontalPanel();
+ v.add(p);
+ final DateBox start = newDateBox(invalidDateReporter);
+ start.setWidth("13em");
+ final DateBox end = newDateBox(invalidDateReporter);
+ end.setWidth("13em");
+
+ end.getDatePicker().addValueChangeHandler(new ValueChangeHandler<Date>() {
+ public void onValueChange(ValueChangeEvent<Date> event) {
+ start.removeStyleName("user-modified");
+ }
+ });
+
+ start.setValue(new Date());
+
+ p.add(start);
+ Label l = new Label(" - ");
+ l.setStyleName("filler");
+ p.add(l);
+ p.add(end);
+ final Label value = new Label();
+ p.add(value);
+ HorizontalPanel h2 = new HorizontalPanel();
+ v.add(h2);
+ h2.add(new Button("Short format", new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ start.setDateFormat(DateTimeFormat.getShortDateFormat());
+ end.setDateFormat(DateTimeFormat.getShortDateFormat());
+ }
+ }));
+ h2.add(new Button("Long format", new ClickHandler() {
+
+ public void onClick(ClickEvent event) {
+ start.setDateFormat(DateTimeFormat.getLongDateFormat());
+ end.setDateFormat(DateTimeFormat.getLongDateFormat());
+ }
+ }));
+
+ h2.add(new Button("Clear", new ClickHandler() {
+ public void onClick(ClickEvent sender) {
+ start.setValue(null);
+ end.setValue(null);
+ }
+ }));
+
+ h2.add(new Button("Get Value", new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ DateTimeFormat f = DateTimeFormat.getShortDateFormat();
+ Date d1 = start.getValue();
+ Date d2 = end.getValue();
+ value.setText("Start: \""
+ + (d1 == null ? "null" : f.format(d1))
+ + "\" End: \""
+ + (d2 == null ? "null" : f.format(d2))
+ + "\"");
+ }
+ }));
+ return v;
+ }
+
+ private Label makeErrorLabel() {
+ final Label startErrors = new Label();
+ startErrors.getElement().getStyle().setProperty("color", "red");
+ return startErrors;
+ }
+
+ private DateBox newDateBox(InvalidDateReporter invalidDateReporter) {
+ DateBox dateBox =
+ invalidDateReporter == null ? new DateBox() : new DateBox(
+ new DatePicker(), invalidDateReporter);
+ return dateBox;
+ }
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDatePicker.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDatePicker.java
new file mode 100644
index 0000000..14386b3
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDatePicker.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.logical.shared.HighlightEvent;
+import com.google.gwt.event.logical.shared.HighlightHandler;
+import com.google.gwt.event.logical.shared.ShowRangeEvent;
+import com.google.gwt.event.logical.shared.ShowRangeHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.datepicker.client.DatePicker;
+
+import java.util.Date;
+
+/**
+ * Date picker demo.
+ */
+public class VisualsForDatePicker extends AbstractIssue {
+
+ @Override
+ public Widget createIssue() {
+ VerticalPanel p = new VerticalPanel();
+ final DatePicker picker = new DatePicker();
+ p.add(picker);
+ final Label value = new Label("value: ");
+ p.add(value);
+ final Label highlight = new Label("highlight: ");
+ p.add(highlight);
+ final Label range = new Label("range: ");
+ p.add(range);
+ picker.addValueChangeHandler(new ValueChangeHandler<Date>() {
+ public void onValueChange(ValueChangeEvent<Date> event) {
+ value.setText("value: "
+ + DateTimeFormat.getShortDateFormat().format(event.getValue()));
+ }
+ });
+ picker.addHighlightHandler(new HighlightHandler<Date>() {
+
+ @SuppressWarnings("deprecation")
+ // Should never be seen, as highlight should be cloned.
+ public void onHighlight(HighlightEvent<Date> event) {
+ event.getHighlighted().setYear(1);
+ picker.getHighlightedDate().setYear(1);
+ }
+
+ });
+ picker.addHighlightHandler(new HighlightHandler<Date>() {
+ public void onHighlight(HighlightEvent<Date> event) {
+ highlight.setText("highlight: "
+ + DateTimeFormat.getShortDateFormat().format(event.getHighlighted()));
+ }
+ });
+ picker.addShowRangeHandler(new ShowRangeHandler<Date>() {
+ public void onShowRange(ShowRangeEvent<Date> event) {
+ Date start = event.getStart();
+ Date end = event.getEnd();
+ DateTimeFormat format = DateTimeFormat.getShortDateFormat();
+ range.setText("range: " + format.format(start) + " - "
+ + format.format(end));
+ }
+ });
+ return p;
+ };
+
+ @Override
+ public String getInstructions() {
+ return "Go back one month, go forward one month, check that highlighting is working, and try selecting a date.";
+ }
+
+ @Override
+ public String getSummary() {
+ return "Visual test for date picker";
+ }
+
+ @Override
+ public boolean hasCSS() {
+ return false;
+ }
+
+}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
index f00e966..768e1f3 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
@@ -62,6 +62,7 @@
import com.google.gwt.sample.showcase.client.content.widgets.CwBasicButton;
import com.google.gwt.sample.showcase.client.content.widgets.CwCheckBox;
import com.google.gwt.sample.showcase.client.content.widgets.CwCustomButton;
+import com.google.gwt.sample.showcase.client.content.widgets.CwDatePicker;
import com.google.gwt.sample.showcase.client.content.widgets.CwFileUpload;
import com.google.gwt.sample.showcase.client.content.widgets.CwHyperlink;
import com.google.gwt.sample.showcase.client.content.widgets.CwRadioButton;
@@ -320,6 +321,8 @@
images.catWidgets());
setupMainMenuOption(catWidgets, new CwFileUpload(constants),
images.catWidgets());
+ setupMainMenuOption(catWidgets, new CwDatePicker(constants),
+ images.catWidgets());
setupMainMenuOption(catWidgets, new CwHyperlink(constants),
images.catWidgets());
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.java
index 99b7595..68f59ec 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.java
@@ -49,6 +49,7 @@
import com.google.gwt.sample.showcase.client.content.widgets.CwBasicButton;
import com.google.gwt.sample.showcase.client.content.widgets.CwCheckBox;
import com.google.gwt.sample.showcase.client.content.widgets.CwCustomButton;
+import com.google.gwt.sample.showcase.client.content.widgets.CwDatePicker;
import com.google.gwt.sample.showcase.client.content.widgets.CwFileUpload;
import com.google.gwt.sample.showcase.client.content.widgets.CwHyperlink;
import com.google.gwt.sample.showcase.client.content.widgets.CwRadioButton;
@@ -73,7 +74,7 @@
CwDateTimeFormat.CwConstants, CwMessagesExample.CwConstants,
CwConstantsExample.CwConstants, CwConstantsWithLookupExample.CwConstants,
CwDictionaryExample.CwConstants, CwDecoratorPanel.CwConstants,
- CwAnimation.CwConstants {
+ CwAnimation.CwConstants, CwDatePicker.CwConstants {
/**
* The path to source code for examples, raw files, and style definitions.
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.properties b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.properties
index a049c0b..00b8a7b 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.properties
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.properties
@@ -73,6 +73,10 @@
cwCustomButtonDescription = PushButtons and ToggleButtons allow you to customize the look of your buttons
cwCustomButtonPush = <b>Push Buttons:</b>
cwCustomButtonToggle = <b>Toggle Buttons:</b>
+cwDatePickerName = Date Picker
+cwDatePickerDescription = Let users select a date using the DatePicker.
+cwDatePickerBoxLabel = <br><br><br><b>DateBox with popup DatePicker:</b>
+cwDatePickerLabel = <b>Permanent DatePicker:</b>
cwDateTimeFormatName = Date Time Format
cwDateTimeFormatDescription = Class DateTimeFormat supports locale-sensitive formatting and parsing of date and time values, like NumberFormat, using a flexible pattern-based syntax. Both custom patterns and standard patterns are supported.
cwDateTimeFormatFailedToParseInput = Unable to parse input
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_ar.properties b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_ar.properties
index 6fcfa36..09b106a 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_ar.properties
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_ar.properties
@@ -234,3 +234,7 @@
cwTreeBrahmsWorkSonatas = اثنين السوناتات لكلارينيت -- و قاصر ,لاثنين من السوناتات كلارينيت -- ة - شقة الرئيسية
cwTreeBrahmsWorkSymphonies = رقم 1 -- ج طفيفة ,رقم 2 -- د طفيفة ,رقم 3 -- و الرئيسية ,رقم 4 -- ة طفيفة
cwTreeMozartWorkConcertos = كونشرتو البيانو رقم 12 , كونشرتو البيانو رقم 17 , كونشرتو الكلارينت , كونشرتو الكمان رقم 5 , رقم 4 كونشرتو الكمان
+cwDatePickerName = تاريخ القاطف
+cwDatePickerDescription = اسمحوا المستخدمين اختيار تاريخ باستخدام DatePicker.
+cwDatePickerBoxLabel = <br><br><br><b>DateBox مع قافزة DatePicker : </b>
+cwDatePickerLabel = <b>الدائم DatePicker : </b>
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_fr.properties b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_fr.properties
index 183d0c9..ca4a4a5 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_fr.properties
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_fr.properties
@@ -232,3 +232,7 @@
cwTreeBrahmsWorkSonatas = Deux Sonates pour clarinette - F Minor, deux sonates pour clarinette - mi bémol majeur
cwTreeBrahmsWorkSymphonies = n ° 1 - C Minor, n ° 2 - ré mineur, n ° 3 - F Major, n ° 4 - E Minor
cwTreeMozartWorkConcertos = Concerto pour piano n ° 12, Concerto pour piano n ° 17, Concerto pour clarinette, Concerto pour violon n ° 5, Concerto pour violon n ° 4
+cwDatePickerName = Date Picker
+cwDatePickerDescription = Permettre aux utilisateurs de sélectionner une date à l'aide de la DatePicker.
+cwDatePickerBoxLabel = <br><br><b>DateBox avec popup DatePicker:</b>
+cwDatePickerLabel = <b>DatePicker permanent:</b>
\ No newline at end of file
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_zh.properties b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_zh.properties
index 47586d7..f917536 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_zh.properties
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_zh.properties
@@ -232,3 +232,7 @@
cwTreeBrahmsWorkSonatas = 2奏鸣曲单簧管-F小调, 2单簧管奏鸣曲- E大调大
cwTreeBrahmsWorkSymphonies =第1号-C小调, 第2号- D小调, 第3号- F大, 第4号- E小调
cwTreeMozartWorkConcertos =钢琴协奏曲第12号, 钢琴协奏曲第17号, 单簧管协奏曲, 小提琴协奏曲第5号, 小提琴协奏曲第4号
+cwDatePickerName =日期选择器
+cwDatePickerDescription =让用户选择日期使用DatePicker 。
+cwDatePickerBoxLabel = <br><br><br><b>DateBox与弹出DatePicker:</b>
+cwDatePickerLabel =<b>常驻DatePicker:</b>
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwDatePicker.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwDatePicker.java
new file mode 100644
index 0000000..f25df4e
--- /dev/null
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwDatePicker.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.sample.showcase.client.content.widgets;
+
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.i18n.client.Constants;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.sample.showcase.client.ContentWidget;
+import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
+import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
+import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.datepicker.client.DateBox;
+import com.google.gwt.user.datepicker.client.DatePicker;
+
+import java.util.Date;
+
+/**
+ * Example file.
+ */
+@ShowcaseStyle({
+ ".gwt-DatePicker", ".datePicker", "td.datePickerMonth", ".gwt-DateBox",
+ ".dateBox"})
+public class CwDatePicker extends ContentWidget {
+ /**
+ * The constants used in this Content Widget.
+ */
+ @ShowcaseSource
+ public static interface CwConstants extends Constants,
+ ContentWidget.CwConstants {
+ String cwDatePickerBoxLabel();
+
+ String cwDatePickerDescription();
+
+ String cwDatePickerLabel();
+
+ String cwDatePickerName();
+ }
+
+ /**
+ * An instance of the constants.
+ */
+ @ShowcaseData
+ private CwConstants constants;
+
+ /**
+ * Constructor.
+ *
+ * @param constants the constants
+ */
+ public CwDatePicker(CwConstants constants) {
+ super(constants);
+ this.constants = constants;
+ }
+
+ @Override
+ public String getDescription() {
+ return constants.cwDatePickerDescription();
+ }
+
+ @Override
+ public String getName() {
+ return constants.cwDatePickerName();
+ }
+
+ /**
+ * Initialize this example.
+ */
+ @ShowcaseSource
+ @Override
+ public Widget onInitialize() {
+ // Create a basic date picker
+ DatePicker datePicker = new DatePicker();
+ final Label text = new Label();
+
+ // Set the value in the text box when the user selects a date
+ datePicker.addValueChangeHandler(new ValueChangeHandler<Date>() {
+ public void onValueChange(ValueChangeEvent<Date> event) {
+ Date date = event.getValue();
+ String dateString = DateTimeFormat.getMediumDateFormat().format(date);
+ text.setText(dateString);
+ }
+ });
+
+ // Set the default value
+ datePicker.setValue(new Date(), true);
+
+ // Create a DateBox
+ DateBox dateBox = new DateBox();
+
+ // Combine the widgets into a panel and return them
+ VerticalPanel vPanel = new VerticalPanel();
+ vPanel.add(new HTML(constants.cwDatePickerLabel()));
+ vPanel.add(text);
+ vPanel.add(datePicker);
+ vPanel.add(new HTML(constants.cwDatePickerBoxLabel()));
+ vPanel.add(dateBox);
+ return vPanel;
+ }
+}
diff --git a/user/javadoc/com/google/gwt/examples/DateBoxExample.java b/user/javadoc/com/google/gwt/examples/DateBoxExample.java
new file mode 100644
index 0000000..8e65035
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/DateBoxExample.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.examples;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.datepicker.client.DateBox;
+
+import java.util.Date;
+
+public class DateBoxExample implements EntryPoint {
+
+ public void onModuleLoad() {
+ DateBox dateBox = new DateBox();
+ dateBox.setValue(new Date());
+ RootPanel.get().add(dateBox);
+ }
+}
diff --git a/user/javadoc/com/google/gwt/examples/DatePickerExample.java b/user/javadoc/com/google/gwt/examples/DatePickerExample.java
new file mode 100644
index 0000000..88adac9
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/DatePickerExample.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.examples;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.datepicker.client.DatePicker;
+
+import java.util.Date;
+
+public class DatePickerExample implements EntryPoint {
+
+ public void onModuleLoad() {
+ // Create a date picker
+ DatePicker datePicker = new DatePicker();
+ final Label text = new Label();
+
+ // Set the value in the text box when the user selects a date
+ datePicker.addValueChangeHandler(new ValueChangeHandler<Date>() {
+ public void onValueChange(ValueChangeEvent<Date> event) {
+ Date date = event.getValue();
+ String dateString = DateTimeFormat.getMediumDateFormat().format(date);
+ text.setText(dateString);
+ }
+ });
+
+ // Set the default value
+ datePicker.setValue(new Date(), true);
+
+ // Add the widgets to the page
+ RootPanel.get().add(text);
+ RootPanel.get().add(datePicker);
+ }
+}
diff --git a/user/src/com/google/gwt/event/dom/client/HasBlurHandlers.java b/user/src/com/google/gwt/event/dom/client/HasBlurHandlers.java
index 2892059..14c43df 100644
--- a/user/src/com/google/gwt/event/dom/client/HasBlurHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasBlurHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link BlurHandler} instances.
*/
-public interface HasBlurHandlers {
+public interface HasBlurHandlers extends HasHandlers {
/**
* Adds a {@link BlurEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasChangeHandlers.java b/user/src/com/google/gwt/event/dom/client/HasChangeHandlers.java
index 8b9b8da..0a9ccc2 100644
--- a/user/src/com/google/gwt/event/dom/client/HasChangeHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasChangeHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link ChangeHandler} instances.
*/
-public interface HasChangeHandlers {
+public interface HasChangeHandlers extends HasHandlers {
/**
* Adds a {@link ChangeEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasClickHandlers.java b/user/src/com/google/gwt/event/dom/client/HasClickHandlers.java
index 26c1a9a..0371319 100644
--- a/user/src/com/google/gwt/event/dom/client/HasClickHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasClickHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link ClickHandler} instances.
*/
-public interface HasClickHandlers {
+public interface HasClickHandlers extends HasHandlers {
/**
* Adds a {@link ClickEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasContextMenuHandlers.java b/user/src/com/google/gwt/event/dom/client/HasContextMenuHandlers.java
index 669ed5d..8a7e54b 100644
--- a/user/src/com/google/gwt/event/dom/client/HasContextMenuHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasContextMenuHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link ContextMenuHandler} instances.
*/
-public interface HasContextMenuHandlers {
+public interface HasContextMenuHandlers extends HasHandlers {
/**
* Adds a {@link ContextMenuEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasDoubleClickHandlers.java b/user/src/com/google/gwt/event/dom/client/HasDoubleClickHandlers.java
index 35f6d7b..9fedae7 100644
--- a/user/src/com/google/gwt/event/dom/client/HasDoubleClickHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasDoubleClickHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link DoubleClickHandler} instances.
*/
-public interface HasDoubleClickHandlers {
+public interface HasDoubleClickHandlers extends HasHandlers {
/**
* Adds a {@link DoubleClickEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasErrorHandlers.java b/user/src/com/google/gwt/event/dom/client/HasErrorHandlers.java
index 00b741c..3fa51ed 100644
--- a/user/src/com/google/gwt/event/dom/client/HasErrorHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasErrorHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link ErrorHandler} instances.
*/
-public interface HasErrorHandlers {
+public interface HasErrorHandlers extends HasHandlers {
/**
* Adds a {@link ErrorEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasFocusHandlers.java b/user/src/com/google/gwt/event/dom/client/HasFocusHandlers.java
index a7d3dfd..8b1f69b 100644
--- a/user/src/com/google/gwt/event/dom/client/HasFocusHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasFocusHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link FocusHandler} instances.
*/
-public interface HasFocusHandlers {
+public interface HasFocusHandlers extends HasHandlers {
/**
* Adds a {@link FocusEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasKeyDownHandlers.java b/user/src/com/google/gwt/event/dom/client/HasKeyDownHandlers.java
index 5d584d7..e3ae78a 100644
--- a/user/src/com/google/gwt/event/dom/client/HasKeyDownHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasKeyDownHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link KeyDownHandler} instances.
*/
-public interface HasKeyDownHandlers {
+public interface HasKeyDownHandlers extends HasHandlers {
/**
* Adds a {@link KeyDownEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasKeyPressHandlers.java b/user/src/com/google/gwt/event/dom/client/HasKeyPressHandlers.java
index 7d55449..06e4e73 100644
--- a/user/src/com/google/gwt/event/dom/client/HasKeyPressHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasKeyPressHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link KeyPressHandler} instances.
*/
-public interface HasKeyPressHandlers {
+public interface HasKeyPressHandlers extends HasHandlers {
/**
* Adds a {@link KeyPressEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasKeyUpHandlers.java b/user/src/com/google/gwt/event/dom/client/HasKeyUpHandlers.java
index 0b6bc92..060494e 100644
--- a/user/src/com/google/gwt/event/dom/client/HasKeyUpHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasKeyUpHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link KeyUpHandler} instances.
*/
-public interface HasKeyUpHandlers {
+public interface HasKeyUpHandlers extends HasHandlers {
/**
* Adds a {@link KeyUpEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasLoadHandlers.java b/user/src/com/google/gwt/event/dom/client/HasLoadHandlers.java
index efe2892..732c3e9 100644
--- a/user/src/com/google/gwt/event/dom/client/HasLoadHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasLoadHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link LoadHandler} instances.
*/
-public interface HasLoadHandlers {
+public interface HasLoadHandlers extends HasHandlers {
/**
* Adds a {@link LoadEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasLoseCaptureHandlers.java b/user/src/com/google/gwt/event/dom/client/HasLoseCaptureHandlers.java
index dac1c4b..397cd4e 100644
--- a/user/src/com/google/gwt/event/dom/client/HasLoseCaptureHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasLoseCaptureHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link LoseCaptureHandler} instances.
*/
-public interface HasLoseCaptureHandlers {
+public interface HasLoseCaptureHandlers extends HasHandlers {
/**
* Adds a {@link LoseCaptureEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseDownHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseDownHandlers.java
index 71853a1..749b93e 100644
--- a/user/src/com/google/gwt/event/dom/client/HasMouseDownHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseDownHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link MouseDownHandler} instances.
*/
-public interface HasMouseDownHandlers {
+public interface HasMouseDownHandlers extends HasHandlers {
/**
* Adds a {@link MouseDownEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseMoveHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseMoveHandlers.java
index 90f6e55..c68ebc3 100644
--- a/user/src/com/google/gwt/event/dom/client/HasMouseMoveHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseMoveHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link MouseMoveHandler} instances.
*/
-public interface HasMouseMoveHandlers {
+public interface HasMouseMoveHandlers extends HasHandlers {
/**
* Adds a {@link MouseMoveEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseOutHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseOutHandlers.java
index e993c67..4d3e734 100644
--- a/user/src/com/google/gwt/event/dom/client/HasMouseOutHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseOutHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link MouseOutHandler} instances.
*/
-public interface HasMouseOutHandlers {
+public interface HasMouseOutHandlers extends HasHandlers {
/**
* Adds a {@link MouseOutEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseOverHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseOverHandlers.java
index dab97b6..28cb7d4 100644
--- a/user/src/com/google/gwt/event/dom/client/HasMouseOverHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseOverHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link MouseOverHandler} instances.
*/
-public interface HasMouseOverHandlers {
+public interface HasMouseOverHandlers extends HasHandlers {
/**
* Adds a {@link MouseOverEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseUpHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseUpHandlers.java
index e04a391..72eec9e 100644
--- a/user/src/com/google/gwt/event/dom/client/HasMouseUpHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseUpHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link MouseUpHandler} instances.
*/
-public interface HasMouseUpHandlers {
+public interface HasMouseUpHandlers extends HasHandlers {
/**
* Adds a {@link MouseUpEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseWheelHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseWheelHandlers.java
index 7aaaa41..01c0236 100644
--- a/user/src/com/google/gwt/event/dom/client/HasMouseWheelHandlers.java
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseWheelHandlers.java
@@ -15,13 +15,14 @@
*/
package com.google.gwt.event.dom.client;
+import com.google.gwt.event.logical.shared.HasHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* A widget that implements this interface provides registration for
* {@link MouseWheelHandler} instances.
*/
-public interface HasMouseWheelHandlers {
+public interface HasMouseWheelHandlers extends HasHandlers {
/**
* Adds a {@link MouseWheelEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/dom/client/KeyEvent.java b/user/src/com/google/gwt/event/dom/client/KeyEvent.java
index 6d73bdc..18e7d2c 100644
--- a/user/src/com/google/gwt/event/dom/client/KeyEvent.java
+++ b/user/src/com/google/gwt/event/dom/client/KeyEvent.java
@@ -36,6 +36,17 @@
}
/**
+ * Does this event have any modifier keys down? Specifically. is the control,
+ * meta, shift, or alt key currently pressed?
+ *
+ * @return whether this event have any modifier key down
+ */
+ public boolean isAnyModifierKeyDown() {
+ return isControlKeyDown() || isShiftKeyDown() || isMetaKeyDown()
+ || isAltKeyDown();
+ }
+
+ /**
* Gets the key-repeat state of this event.
*
* @return <code>true</code> if this key event was an auto-repeat
diff --git a/user/src/com/google/gwt/event/logical/shared/BeforeSelectionEvent.java b/user/src/com/google/gwt/event/logical/shared/BeforeSelectionEvent.java
index d81a715..556335a 100644
--- a/user/src/com/google/gwt/event/logical/shared/BeforeSelectionEvent.java
+++ b/user/src/com/google/gwt/event/logical/shared/BeforeSelectionEvent.java
@@ -36,14 +36,13 @@
* manager. If no such handlers exist, this method will do nothing.
*
* @param <I> the item type
- * @param <S> The event source type
* @param source the source of the handlers
* @param item the item
* @return the event so that the caller can check if it was canceled, or null
- * if no handlers of this event type have been registered
+ * if no handlers of this event type have been registered
*/
- public static <I, S extends HasBeforeSelectionHandlers<I> & HasHandlers> BeforeSelectionEvent<I> fire(
- S source, I item) {
+ public static <I> BeforeSelectionEvent<I> fire(
+ HasBeforeSelectionHandlers<I> source, I item) {
// If no handlers exist, then type can be null.
if (TYPE != null) {
HandlerManager handlers = source.getHandlers();
@@ -80,7 +79,7 @@
}
/**
- * Cancel the before selection event.
+ * Cancel the before selection event.
*
* Classes overriding this method should still call super.cancel().
*/
diff --git a/user/src/com/google/gwt/event/logical/shared/CloseEvent.java b/user/src/com/google/gwt/event/logical/shared/CloseEvent.java
index 25ceaba..c68536b 100644
--- a/user/src/com/google/gwt/event/logical/shared/CloseEvent.java
+++ b/user/src/com/google/gwt/event/logical/shared/CloseEvent.java
@@ -35,12 +35,10 @@
* no such handlers exist, this method will do nothing.
*
* @param <T> the target type
- * @param <S> The event source
* @param source the source of the handlers
* @param target the target
*/
- public static <T, S extends HasCloseHandlers<T> & HasHandlers> void fire(
- S source, T target) {
+ public static <T> void fire(HasCloseHandlers<T> source, T target) {
fire(source, target, false);
}
@@ -48,13 +46,12 @@
* Fires a close event on all registered handlers in the handler manager.
*
* @param <T> the target type
- * @param <S> The event source
* @param source the source of the handlers
* @param target the target
* @param autoClosed was the target closed automatically
*/
- public static <T, S extends HasCloseHandlers<T> & HasHandlers> void fire(
- S source, T target, boolean autoClosed) {
+ public static <T> void fire(
+ HasCloseHandlers<T> source, T target, boolean autoClosed) {
if (TYPE != null) {
HandlerManager handlers = source.getHandlers();
if (handlers != null) {
diff --git a/user/src/com/google/gwt/event/logical/shared/HasBeforeSelectionHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasBeforeSelectionHandlers.java
index 96a6d71..1c95fcc 100644
--- a/user/src/com/google/gwt/event/logical/shared/HasBeforeSelectionHandlers.java
+++ b/user/src/com/google/gwt/event/logical/shared/HasBeforeSelectionHandlers.java
@@ -23,7 +23,7 @@
*
* @param <I> the type about to be selected
*/
-public interface HasBeforeSelectionHandlers<I> {
+public interface HasBeforeSelectionHandlers<I> extends HasHandlers {
/**
* Adds a {@link BeforeSelectionEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/logical/shared/HasCloseHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasCloseHandlers.java
index fecdb4d..76dcede 100644
--- a/user/src/com/google/gwt/event/logical/shared/HasCloseHandlers.java
+++ b/user/src/com/google/gwt/event/logical/shared/HasCloseHandlers.java
@@ -23,7 +23,7 @@
*
* @param <T> the type being closed
*/
-public interface HasCloseHandlers<T> {
+public interface HasCloseHandlers<T> extends HasHandlers {
/**
* Adds a {@link CloseEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/logical/shared/HasHighlightHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasHighlightHandlers.java
new file mode 100644
index 0000000..5c84ce6
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasHighlightHandlers.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.HandlerRegistration;
+
+/**
+ * A widget that implements this interface is a public source of
+ * {@link HighlightEvent} events.
+ *
+ * @param <V> the highlighted value type
+ */
+public interface HasHighlightHandlers<V> extends HasHandlers {
+ /**
+ * Adds a {@link HighlightEvent} handler.
+ *
+ * @param handler the handler
+ * @return the registration for the event
+ */
+ HandlerRegistration addHighlightHandler(HighlightHandler<V> handler);
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/HasOpenHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasOpenHandlers.java
index 647f270..70bd58f 100644
--- a/user/src/com/google/gwt/event/logical/shared/HasOpenHandlers.java
+++ b/user/src/com/google/gwt/event/logical/shared/HasOpenHandlers.java
@@ -23,7 +23,7 @@
*
* @param <T> the type being opened
*/
-public interface HasOpenHandlers<T> {
+public interface HasOpenHandlers<T> extends HasHandlers {
/**
* Adds a {@link OpenEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/logical/shared/HasResizeHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasResizeHandlers.java
index a5cff3f..df0b620 100644
--- a/user/src/com/google/gwt/event/logical/shared/HasResizeHandlers.java
+++ b/user/src/com/google/gwt/event/logical/shared/HasResizeHandlers.java
@@ -21,7 +21,7 @@
* A widget that implements this interface is a public source of
* {@link ResizeEvent} events.
*/
-public interface HasResizeHandlers {
+public interface HasResizeHandlers extends HasHandlers {
/**
* Adds a {@link ResizeEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/logical/shared/HasSelectionHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasSelectionHandlers.java
index 3d310c6..392c47f 100644
--- a/user/src/com/google/gwt/event/logical/shared/HasSelectionHandlers.java
+++ b/user/src/com/google/gwt/event/logical/shared/HasSelectionHandlers.java
@@ -23,7 +23,7 @@
*
* @param <I> the type being selected
*/
-public interface HasSelectionHandlers<I> {
+public interface HasSelectionHandlers<I> extends HasHandlers {
/**
* Adds a {@link SelectionEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/logical/shared/HasShowRangeHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasShowRangeHandlers.java
new file mode 100644
index 0000000..20850ce
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasShowRangeHandlers.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.HandlerRegistration;
+
+/**
+ * A widget that implements this interface is a public source of
+ * {@link ShowRangeEvent} events.
+ *
+ * @param <V> the type of range
+ */
+public interface HasShowRangeHandlers<V> extends HasHandlers {
+ /**
+ * Adds a {@link ShowRangeEvent} handler.
+ *
+ * @param handler the handler
+ * @return the registration for the event
+ */
+ HandlerRegistration addShowRangeHandler(ShowRangeHandler<V> handler);
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/HasValueChangeHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasValueChangeHandlers.java
index 2ea1f12..f4278ab 100644
--- a/user/src/com/google/gwt/event/logical/shared/HasValueChangeHandlers.java
+++ b/user/src/com/google/gwt/event/logical/shared/HasValueChangeHandlers.java
@@ -23,7 +23,7 @@
*
* @param <I> the value about to be changed
*/
-public interface HasValueChangeHandlers<I> {
+public interface HasValueChangeHandlers<I> extends HasHandlers {
/**
* Adds a {@link ValueChangeEvent} handler.
*
diff --git a/user/src/com/google/gwt/event/logical/shared/HighlightEvent.java b/user/src/com/google/gwt/event/logical/shared/HighlightEvent.java
new file mode 100644
index 0000000..fa9a535
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HighlightEvent.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+
+/**
+ * Represents a highlight event.
+ *
+ * @param <V> the highlighted value type
+ */
+public class HighlightEvent<V> extends GwtEvent<HighlightHandler<V>> {
+
+ /**
+ * Handler type.
+ */
+ private static Type<HighlightHandler<?>> TYPE;
+
+ /**
+ * Fires a highlight event on all registered handlers in the handler manager.
+ *
+ * @param <V> the highlighted value type
+ * @param <S> The event source
+ * @param source the source of the handlers
+ * @param highlighted the value highlighted
+ */
+ public static <V, S extends HasHighlightHandlers<V> & HasHandlers> void fire(
+ S source, V highlighted) {
+ if (TYPE != null) {
+ HandlerManager handlers = source.getHandlers();
+ if (handlers != null) {
+ HighlightEvent<V> event = new HighlightEvent<V>(highlighted);
+ handlers.fireEvent(event);
+ }
+ }
+ }
+
+ /**
+ * Gets the type associated with this event.
+ *
+ * @return returns the handler type
+ */
+ public static Type<HighlightHandler<?>> getType() {
+ if (TYPE == null) {
+ TYPE = new Type<HighlightHandler<?>>();
+ }
+ return TYPE;
+ }
+
+ private final V highlighted;
+
+ /**
+ * Creates a new highlight event.
+ *
+ * @param highlighted value highlighted
+ */
+ protected HighlightEvent(V highlighted) {
+ this.highlighted = highlighted;
+ }
+
+ /**
+ * Gets the value highlighted.
+ *
+ * @return value highlighted
+ */
+ public V getHighlighted() {
+ return highlighted;
+ }
+
+ @Override
+ protected void dispatch(HighlightHandler<V> handler) {
+ handler.onHighlight(this);
+ }
+
+ // Because of type erasure, our static type is
+ // wild carded, yet the "real" type should use our I param.
+ @SuppressWarnings("unchecked")
+ @Override
+ protected final Type<HighlightHandler<V>> getAssociatedType() {
+ return (Type) TYPE;
+ }
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/HighlightHandler.java b/user/src/com/google/gwt/event/logical/shared/HighlightHandler.java
new file mode 100644
index 0000000..effc2ce
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HighlightHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link HighlightEvent} events.
+ *
+ * @param <V> the highlighted value type
+ */
+public interface HighlightHandler<V> extends EventHandler {
+
+ /**
+ * Called when {@link HighlightEvent} is fired.
+ *
+ * @param event the {@link HighlightEvent} that was fired
+ */
+ void onHighlight(HighlightEvent<V> event);
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/OpenEvent.java b/user/src/com/google/gwt/event/logical/shared/OpenEvent.java
index 34026f2..ca8c1a6 100644
--- a/user/src/com/google/gwt/event/logical/shared/OpenEvent.java
+++ b/user/src/com/google/gwt/event/logical/shared/OpenEvent.java
@@ -35,12 +35,10 @@
* such handlers exist, this method will do nothing.
*
* @param <T> the target type
- * @param <S> The event source
* @param source the source of the handlers
* @param target the target
*/
- public static <T, S extends HasOpenHandlers<T> & HasHandlers> void fire(
- S source, T target) {
+ public static <T> void fire(HasOpenHandlers<T> source, T target) {
if (TYPE != null) {
HandlerManager handlers = source.getHandlers();
if (handlers != null) {
diff --git a/user/src/com/google/gwt/event/logical/shared/SelectionEvent.java b/user/src/com/google/gwt/event/logical/shared/SelectionEvent.java
index 40a8423..c43ab56 100644
--- a/user/src/com/google/gwt/event/logical/shared/SelectionEvent.java
+++ b/user/src/com/google/gwt/event/logical/shared/SelectionEvent.java
@@ -39,8 +39,7 @@
* @param source the source of the handlers
* @param selectedItem the selected item
*/
- public static <I, S extends HasSelectionHandlers<I> & HasHandlers> void fire(
- S source, I selectedItem) {
+ public static <I> void fire(HasSelectionHandlers<I> source, I selectedItem) {
if (TYPE != null) {
HandlerManager handlers = source.getHandlers();
if (handlers != null) {
diff --git a/user/src/com/google/gwt/event/logical/shared/ShowRangeEvent.java b/user/src/com/google/gwt/event/logical/shared/ShowRangeEvent.java
new file mode 100644
index 0000000..cbbccb9
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/ShowRangeEvent.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+
+/**
+ * Represents a show range event.
+ *
+ * @param <V> the type of range
+ */
+public class ShowRangeEvent<V> extends GwtEvent<ShowRangeHandler<V>> {
+
+ /**
+ * Handler type.
+ */
+ private static Type<ShowRangeHandler<?>> TYPE;
+
+ /**
+ * Fires a show range event on all registered handlers in the handler manager.
+ *
+ * @param <V> the type of range
+ * @param <S> the event source
+ * @param source the source of the handlers
+ * @param start the start of the range
+ * @param end the end of the range
+ */
+ public static <V, S extends HasShowRangeHandlers<V> & HasHandlers> void fire(
+ S source, V start, V end) {
+ if (TYPE != null) {
+ HandlerManager handlers = source.getHandlers();
+ if (handlers != null) {
+ ShowRangeEvent<V> event = new ShowRangeEvent<V>(start, end);
+ handlers.fireEvent(event);
+ }
+ }
+ }
+
+ /**
+ * Gets the type associated with this event.
+ *
+ * @return returns the handler type
+ */
+ public static Type<ShowRangeHandler<?>> getType() {
+ if (TYPE == null) {
+ TYPE = new Type<ShowRangeHandler<?>>();
+ }
+ return TYPE;
+ }
+
+ private final V start;
+
+ private final V end;
+
+ /**
+ * Creates a new show range event.
+ *
+ * @param start start of the range
+ * @param end end of the range
+ */
+ protected ShowRangeEvent(V start, V end) {
+ this.start = start;
+ this.end = end;
+ }
+
+ /**
+ * Gets the end of the range.
+ *
+ * @return end of the range
+ */
+ public V getEnd() {
+ return end;
+ }
+
+ /**
+ * Gets the start of the range.
+ *
+ * @return start of the range
+ */
+ public V getStart() {
+ return start;
+ }
+
+ @Override
+ protected void dispatch(ShowRangeHandler<V> handler) {
+ handler.onShowRange(this);
+ }
+
+ // Because of type erasure, our static type is
+ // wild carded, yet the "real" type should use our I param.
+ @SuppressWarnings("unchecked")
+ @Override
+ protected final Type<ShowRangeHandler<V>> getAssociatedType() {
+ return (Type) TYPE;
+ }
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/logical/shared/ShowRangeHandler.java b/user/src/com/google/gwt/event/logical/shared/ShowRangeHandler.java
new file mode 100644
index 0000000..bde468f
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/ShowRangeHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link ShowRangeEvent} events.
+ *
+ * @param <V> the type of range
+ */
+public interface ShowRangeHandler<V> extends EventHandler {
+
+ /**
+ * Called when {@link ShowRangeEvent} is fired.
+ *
+ * @param event the {@link ShowRangeEvent} that was fired
+ */
+ void onShowRange(ShowRangeEvent<V> event);
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/ValueChangeEvent.java b/user/src/com/google/gwt/event/logical/shared/ValueChangeEvent.java
index 52376e8..5a769dc 100644
--- a/user/src/com/google/gwt/event/logical/shared/ValueChangeEvent.java
+++ b/user/src/com/google/gwt/event/logical/shared/ValueChangeEvent.java
@@ -35,12 +35,10 @@
* manager.If no such handlers exist, this method will do nothing.
*
* @param <I> the old value type
- * @param <S> The event source
* @param source the source of the handlers
* @param value the value
*/
- public static <I, S extends HasValueChangeHandlers<I> & HasHandlers> void fire(
- S source, I value) {
+ public static <I> void fire(HasValueChangeHandlers<I> source, I value) {
if (TYPE != null) {
HandlerManager handlers = source.getHandlers();
if (handlers != null && handlers.isEventHandled(TYPE)) {
@@ -61,13 +59,11 @@
* @param oldValue the oldValue, may be null
* @param newValue the newValue, may be null
*/
- public static <I, S extends HasValueChangeHandlers<I> & HasHandlers> void fireIfNotEqual(
- S source, I oldValue, I newValue) {
- if (TYPE != null) {
- if (oldValue != newValue
- && (oldValue == null || !oldValue.equals(newValue))) {
- fire(source, newValue);
- }
+ public static <I> void fireIfNotEqual(HasValueChangeHandlers<I> source,
+ I oldValue, I newValue) {
+ if (shouldFire(source, oldValue, newValue)) {
+ ValueChangeEvent<I> event = new ValueChangeEvent<I>(newValue);
+ source.getHandlers().fireEvent(event);
}
}
@@ -83,10 +79,27 @@
return TYPE;
}
+ /**
+ * Convenience method to allow subtypes to know when they should fire a value
+ * change event in a null-safe manner.
+ *
+ * @param <I> value type
+ * @param source the source
+ * @param oldValue the old value
+ * @param newValue the new value
+ * @return whether the event should be fired
+ */
+ protected static <I> boolean shouldFire(HasValueChangeHandlers<I> source,
+ I oldValue, I newValue) {
+ return TYPE != null && source.getHandlers() != null && oldValue != newValue
+ && (oldValue == null || !oldValue.equals(newValue));
+ }
+
private final I value;
/**
* Creates a value change event.
+ *
* @param value the value
*/
protected ValueChangeEvent(I value) {
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index 17de395..70216b7 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -40,7 +40,7 @@
<inherits name="com.google.gwt.user.Window" />
<inherits name="com.google.gwt.user.Tree"/>
<inherits name="com.google.gwt.user.Hyperlink"/>
-
+ <inherits name="com.google.gwt.user.datepicker.DatePicker"/>
<super-source path="translatable"/>
<source path="client"/>
diff --git a/user/src/com/google/gwt/user/client/ui/PopupPanel.java b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
index 417134d..2792e80 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
@@ -272,6 +272,8 @@
private String desiredWidth;
private boolean isAnimationEnabled = false;
+
+ private Element autoHidePartner;
/**
* The {@link ResizeAnimation} used to open and close the {@link PopupPanel}s.
@@ -454,6 +456,7 @@
return modal;
}
+ @SuppressWarnings("deprecation")
public boolean onEventPreview(Event event) {
Element target = DOM.eventGetTarget(event);
@@ -485,7 +488,7 @@
return true;
}
- if (!eventTargetsPopup && autoHide) {
+ if (!eventTargetsPopup && shouldAutoHide(event)) {
hide(true);
return true;
}
@@ -503,7 +506,8 @@
// If it's an outside click and auto-hide is enabled:
// hide the popup and _don't_ eat the event. ONMOUSEDOWN is used to
// prevent problems with showing a popup in response to a mousedown.
- if (!eventTargetsPopup && autoHide && (type == Event.ONMOUSEDOWN)) {
+ if (!eventTargetsPopup && shouldAutoHide(event)
+ && (type == Event.ONMOUSEDOWN)) {
hide(true);
return true;
}
@@ -581,6 +585,15 @@
}
/**
+ * If the auto hide partner is non null, its mouse events will
+ * not hide a panel set to autohide.
+ * @param element new auto hide partner
+ */
+ public void setAutoHidePartner(Element element) {
+ this.autoHidePartner = element;
+ }
+
+ /**
* Sets the height of the panel's child widget. If the panel's child widget
* has not been set, the height passed in will be cached and used to set the
* height immediately after the child widget is set.
@@ -613,7 +626,7 @@
public void setModal(boolean modal) {
this.modal = modal;
}
-
+
/**
* Sets the popup's position relative to the browser's client area. The
* popup's position may be set before calling {@link #show()}.
@@ -728,6 +741,25 @@
resizeAnimation.setState(true);
}
+ /**
+ * Normally, the popup is positioned directly below the relative target, with
+ * its left edge aligned with the left edge of the target. Depending on the
+ * width and height of the popup and the distance from the target to the
+ * bottom and right edges of the window, the popup may be displayed directly
+ * above the target, and/or its right edge may be aligned with the right edge
+ * of the target.
+ *
+ * @param target the target to show the popup below
+ */
+ public final void showRelativeTo(final UIObject target) {
+ // Set the position of the popup right before it is shown.
+ setPopupPositionAndShow(new PositionCallback() {
+ public void setPosition(int offsetWidth, int offsetHeight) {
+ position(target, offsetWidth, offsetHeight);
+ }
+ });
+ }
+
@Override
protected Element getContainerElement() {
return impl.getContainerElement(DOM.getFirstChild(super.getContainerElement()));
@@ -801,4 +833,144 @@
elt.blur();
}
}-*/;
+
+ private boolean eventInPartner(Event event) {
+ return autoHidePartner != null
+ && autoHidePartner.isOrHasChild(event.getTarget());
+ }
+
+ /**
+ * Positions the popup, called after the offset width and height of the popup are known.
+ *
+ * @param relativeObject the ui object to position relative to
+ * @param offsetWidth the drop down's offset width
+ * @param offsetHeight the drop down's offset height
+ */
+ private void position(final UIObject relativeObject, int offsetWidth,
+ int offsetHeight) {
+ // Calculate left position for the popup. The computation for
+ // the left position is bidi-sensitive.
+
+ int textBoxOffsetWidth = relativeObject.getOffsetWidth();
+
+ // Compute the difference between the popup's width and the
+ // textbox's width
+ int offsetWidthDiff = offsetWidth - textBoxOffsetWidth;
+
+ int left;
+
+ if (LocaleInfo.getCurrentLocale().isRTL()) { // RTL case
+
+ int textBoxAbsoluteLeft = relativeObject.getAbsoluteLeft();
+
+ // Right-align the popup. Note that this computation is
+ // valid in the case where offsetWidthDiff is negative.
+ left = textBoxAbsoluteLeft - offsetWidthDiff;
+
+ // If the suggestion popup is not as wide as the text box, always
+ // align to the right edge of the text box. Otherwise, figure out whether
+ // to right-align or left-align the popup.
+ if (offsetWidthDiff > 0) {
+
+ // Make sure scrolling is taken into account, since
+ // box.getAbsoluteLeft() takes scrolling into account.
+ int windowRight = Window.getClientWidth() + Window.getScrollLeft();
+ int windowLeft = Window.getScrollLeft();
+
+ // Compute the left value for the right edge of the textbox
+ int textBoxLeftValForRightEdge = textBoxAbsoluteLeft
+ + textBoxOffsetWidth;
+
+ // Distance from the right edge of the text box to the right edge
+ // of the window
+ int distanceToWindowRight = windowRight - textBoxLeftValForRightEdge;
+
+ // Distance from the right edge of the text box to the left edge of the
+ // window
+ int distanceFromWindowLeft = textBoxLeftValForRightEdge - windowLeft;
+
+ // If there is not enough space for the overflow of the popup's
+ // width to the right of the text box and there IS enough space for the
+ // overflow to the right of the text box, then left-align the popup.
+ // However, if there is not enough space on either side, stick with
+ // right-alignment.
+ if (distanceFromWindowLeft < offsetWidth
+ && distanceToWindowRight >= offsetWidthDiff) {
+ // Align with the left edge of the text box.
+ left = textBoxAbsoluteLeft;
+ }
+ }
+ } else { // LTR case
+
+ // Left-align the popup.
+ left = relativeObject.getAbsoluteLeft();
+
+ // If the suggestion popup is not as wide as the text box, always align to
+ // the left edge of the text box. Otherwise, figure out whether to
+ // left-align or right-align the popup.
+ if (offsetWidthDiff > 0) {
+ // Make sure scrolling is taken into account, since
+ // box.getAbsoluteLeft() takes scrolling into account.
+ int windowRight = Window.getClientWidth() + Window.getScrollLeft();
+ int windowLeft = Window.getScrollLeft();
+
+ // Distance from the left edge of the text box to the right edge
+ // of the window
+ int distanceToWindowRight = windowRight - left;
+
+ // Distance from the left edge of the text box to the left edge of the
+ // window
+ int distanceFromWindowLeft = left - windowLeft;
+
+ // If there is not enough space for the overflow of the popup's
+ // width to the right of hte text box, and there IS enough space for the
+ // overflow to the left of the text box, then right-align the popup.
+ // However, if there is not enough space on either side, then stick with
+ // left-alignment.
+ if (distanceToWindowRight < offsetWidth
+ && distanceFromWindowLeft >= offsetWidthDiff) {
+ // Align with the right edge of the text box.
+ left -= offsetWidthDiff;
+ }
+ }
+ }
+
+ // Calculate top position for the popup
+
+ int top = relativeObject.getAbsoluteTop();
+
+ // Make sure scrolling is taken into account, since
+ // box.getAbsoluteTop() takes scrolling into account.
+ int windowTop = Window.getScrollTop();
+ int windowBottom = Window.getScrollTop() + Window.getClientHeight();
+
+ // Distance from the top edge of the window to the top edge of the
+ // text box
+ int distanceFromWindowTop = top - windowTop;
+
+ // Distance from the bottom edge of the window to the bottom edge of
+ // the text box
+ int distanceToWindowBottom = windowBottom
+ - (top + relativeObject.getOffsetHeight());
+
+ // If there is not enough space for the popup's height below the text
+ // box and there IS enough space for the popup's height above the text
+ // box, then then position the popup above the text box. However, if there
+ // is not enough space on either side, then stick with displaying the
+ // popup below the text box.
+ if (distanceToWindowBottom < offsetHeight
+ && distanceFromWindowTop >= offsetHeight) {
+ top -= offsetHeight;
+ } else {
+ // Position above the text box
+ top += relativeObject.getOffsetHeight();
+ }
+ setPopupPosition(left, top);
+ }
+
+ private boolean shouldAutoHide(Event event) {
+ boolean shouldAutoHide = autoHide && !eventInPartner(event);
+ return shouldAutoHide;
+ }
+
}
diff --git a/user/src/com/google/gwt/user/datepicker/DatePicker.gwt.xml b/user/src/com/google/gwt/user/datepicker/DatePicker.gwt.xml
new file mode 100644
index 0000000..d8acc9d
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/DatePicker.gwt.xml
@@ -0,0 +1,3 @@
+<module>
+</module>
+
diff --git a/user/src/com/google/gwt/user/datepicker/client/CalendarModel.java b/user/src/com/google/gwt/user/datepicker/client/CalendarModel.java
new file mode 100644
index 0000000..d38dd0b
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/CalendarModel.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.i18n.client.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * Model used to get calendar information for {@link DatePicker} and its
+ * subclasses.
+ */
+@SuppressWarnings(/* Required to use Date API in gwt */{"deprecation"})
+public class CalendarModel {
+
+ /**
+ * The number of weeks normally displayed in a month.
+ */
+ public static final int WEEKS_IN_MONTH = 6;
+
+ /**
+ * Number of days normally displayed in a week.
+ */
+ public static final int DAYS_IN_WEEK = 7;
+
+ private static final String[] dayOfWeekNames = new String[7];
+
+ private static final DateTimeFormat dayOfMonthFormatter = DateTimeFormat.getFormat("d");
+
+ private static final DateTimeFormat dayOfWeekFormatter = DateTimeFormat.getFormat("ccccc");
+
+ private static final DateTimeFormat monthAndYearFormatter = DateTimeFormat.getFormat("MMM yyyy");
+
+ private static String[] dayOfMonthNames = new String[32];
+
+ private final Date currentMonth;
+
+ /**
+ * Constructor.
+ */
+ public CalendarModel() {
+ currentMonth = new Date();
+
+ CalendarUtil.setToFirstDayOfMonth(currentMonth);
+
+ // Finding day of week names
+ Date date = new Date();
+ for (int i = 1; i <= 7; i++) {
+ date.setDate(i);
+ int dayOfWeek = date.getDay();
+ dayOfWeekNames[dayOfWeek] = getDayOfWeekFormatter().format(date);
+ }
+
+ // Finding day of month names
+ date.setMonth(0);
+
+ for (int i = 1; i < 32; ++i) {
+ date.setDate(i);
+ dayOfMonthNames[i] = getDayOfMonthFormatter().format(date);
+ }
+ }
+
+ /**
+ * Formats the current specified month. For example "Sep".
+ *
+ * @return the formatted month
+ */
+ public String formatCurrentMonth() {
+ return getMonthAndYearFormatter().format(currentMonth);
+ }
+
+ /**
+ * Formats a date's day of month. For example "1".
+ *
+ * @param date the date
+ * @return the formated day of month
+ */
+ public String formatDayOfMonth(Date date) {
+ return dayOfMonthNames[date.getDate()];
+ }
+
+ /**
+ * Format a day in the week. So, for example "Monday".
+ *
+ * @param dayInWeek the day in week to format
+ * @return the formatted day in week
+ */
+ public String formatDayOfWeek(int dayInWeek) {
+ return dayOfWeekNames[dayInWeek];
+ }
+
+ /**
+ * Gets the first day of the first week in the currently specified month.
+ *
+ * @return the first day
+ */
+ public Date getCurrentFirstDayOfFirstWeek() {
+ int wkDayOfMonth1st = currentMonth.getDay();
+ int start = CalendarUtil.getStartingDayOfWeek();
+ if (wkDayOfMonth1st == start) {
+ // always return a copy to allow SimpleCalendarView to adjust first
+ // display date
+ return new Date(currentMonth.getTime());
+ } else {
+ Date d = new Date(currentMonth.getTime());
+ int offset = wkDayOfMonth1st - start > 0 ? wkDayOfMonth1st - start
+ : DAYS_IN_WEEK - (start - wkDayOfMonth1st);
+ CalendarUtil.addDaysToDate(d, -offset);
+ return d;
+ }
+ }
+
+ /**
+ * Gets the date representation of the currently specified month. Used to
+ * access both the month and year information.
+ *
+ * @return the month and year
+ */
+ public Date getCurrentMonth() {
+ return currentMonth;
+ }
+
+ /**
+ * Is a date in the currently specified month?
+ *
+ * @param date the date
+ * @return date
+ */
+ public boolean isInCurrentMonth(Date date) {
+ return currentMonth.getMonth() == date.getMonth();
+ }
+
+ /**
+ * Sets the currently specified date.
+ *
+ * @param currentDate the currently specified date
+ */
+ public void setCurrentMonth(Date currentDate) {
+ this.currentMonth.setYear(currentDate.getYear());
+ this.currentMonth.setMonth(currentDate.getMonth());
+ }
+
+ /**
+ * Shifts the currently specified date by the given number of months. The day
+ * of the month will be pinned to the original value as far as possible.
+ *
+ * @param deltaMonths - number of months to be added to the current date
+ */
+ public void shiftCurrentMonth(int deltaMonths) {
+ CalendarUtil.addMonthsToDate(currentMonth, deltaMonths);
+ refresh();
+ }
+
+ /**
+ * Gets the date of month formatter.
+ *
+ * @return the day of month formatter
+ */
+ protected DateTimeFormat getDayOfMonthFormatter() {
+ return dayOfMonthFormatter;
+ }
+
+ /**
+ * Gets the day of week formatter.
+ *
+ * @return the day of week formatter
+ */
+ protected DateTimeFormat getDayOfWeekFormatter() {
+ return dayOfWeekFormatter;
+ }
+
+ /**
+ * Gets the month and year formatter.
+ *
+ * @return the month and year formatter
+ */
+ protected DateTimeFormat getMonthAndYearFormatter() {
+ return monthAndYearFormatter;
+ }
+
+ /**
+ * Refresh the current model as needed.
+ */
+ protected void refresh() {
+ }
+
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/CalendarUtil.java b/user/src/com/google/gwt/user/datepicker/client/CalendarUtil.java
new file mode 100644
index 0000000..0df0427
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/CalendarUtil.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.constants.DateTimeConstants;
+
+import java.util.Date;
+
+/**
+ * Useful utilities for creating views of a calendar.
+ */
+public class CalendarUtil {
+
+ static DateTimeConstants intlConstants;
+
+ private static int firstDayOfWeekend;
+
+ private static int lastDayOfWeekend;
+ private static int startingDay;
+
+ static {
+ if (GWT.isClient()) {
+ intlConstants = (DateTimeConstants) GWT.create(DateTimeConstants.class);
+ // Finding the start and end of weekend
+ firstDayOfWeekend = Integer.parseInt(intlConstants.weekendRange()[0]) - 1;
+ lastDayOfWeekend = Integer.parseInt(intlConstants.weekendRange()[1]) - 1;
+ startingDay = Integer.parseInt(CalendarUtil.intlConstants.firstDayOfTheWeek()) - 1;
+ }
+ }
+
+ /**
+ * Adds the given number of days to a date.
+ *
+ * @param date the date
+ * @param days number of days
+ */
+ public static void addDaysToDate(Date date, int days) {
+ date.setDate(date.getDate() + days);
+ }
+
+ /**
+ * Adds the given number of months to a date.
+ *
+ * @param date the date
+ * @param months number of months
+ */
+ public static void addMonthsToDate(Date date, int months) {
+ if (months != 0) {
+ int month = date.getMonth();
+ int year = date.getYear();
+
+ int resultMonthCount = year * 12 + month + months;
+ int resultYear = resultMonthCount / 12;
+ int resultMonth = resultMonthCount - resultYear * 12;
+
+ date.setMonth(resultMonth);
+ date.setYear(resultYear);
+ }
+ }
+
+ /**
+ * Copies a date.
+ *
+ * @param date the date
+ * @return the copy
+ */
+ public static Date copyDate(Date date) {
+ if (date == null) {
+ return null;
+ }
+ Date newDate = new Date();
+ newDate.setTime(date.getTime());
+ return newDate;
+ }
+
+ /**
+ * Returns the number of days between the two dates. Time is ignored.
+ *
+ * @param start starting date
+ * @param finish ending date
+ * @return the different
+ */
+ public static int getDaysBetween(Date start, Date finish) {
+ if (hasTime(start)) {
+ start = copyDate(start);
+ resetTime(start);
+ }
+
+ if (hasTime(finish)) {
+ finish = copyDate(finish);
+ resetTime(finish);
+ }
+
+ long aTime = start.getTime();
+ long bTime = finish.getTime();
+
+ long adjust = 60 * 60 * 1000;
+ adjust = (bTime > aTime) ? adjust : -adjust;
+
+ return (int) ((bTime - aTime + adjust) / (24 * 60 * 60 * 1000));
+ }
+
+ /**
+ * Returns the day of the week on which week starts in the current locale. The
+ * range between 0 for Sunday and 6 for Saturday.
+ *
+ * @return the day of the week
+ */
+ public static int getStartingDayOfWeek() {
+ return startingDay;
+ }
+
+ /**
+ * Sets a date object to be at the beginning of the month and no time
+ * specified.
+ *
+ * @param date the date
+ */
+ public static void setToFirstDayOfMonth(Date date) {
+ resetTime(date);
+ date.setDate(1);
+ }
+
+ static boolean hasTime(Date start) {
+ return start.getHours() != 0 || start.getMinutes() != 0
+ || start.getSeconds() != 0;
+ }
+
+ /**
+ * Is a day in the week a weekend?
+ *
+ * @param dayOfWeek day of week
+ * @return is the day of week a weekend?
+ */
+ static boolean isWeekend(int dayOfWeek) {
+ return dayOfWeek == firstDayOfWeekend || dayOfWeek == lastDayOfWeekend;
+ }
+
+ /**
+ * Resets the date to have no time modifiers.
+ *
+ * @param date the date
+ */
+ private static void resetTime(Date date) {
+ long msec = date.getTime();
+ msec = (msec / 1000) * 1000;
+ date.setTime(msec);
+
+ date.setHours(0);
+ date.setMinutes(0);
+ date.setSeconds(0);
+ }
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/CalendarView.java b/user/src/com/google/gwt/user/datepicker/client/CalendarView.java
new file mode 100644
index 0000000..adaa19a
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/CalendarView.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import java.util.Date;
+
+/**
+ * The CalendarView is a calendar grid that represents the current view of a
+ * {@link DatePicker}. Note, the calendar view only deals with the currently
+ * visible dates and all state is flushed when the calendar view is refreshed.
+ *
+ */
+public abstract class CalendarView extends DatePickerComponent {
+
+ /**
+ * Constructor.
+ */
+ public CalendarView() {
+ }
+
+ /**
+ * Adds a style name to the cell of the supplied date. This style is only set
+ * until the next time the {@link CalendarView} is refreshed.
+ *
+ * @param styleName style name to add
+ * @param date date that will have the supplied style added
+ */
+ public abstract void addStyleToDate(String styleName, Date date);
+
+ /**
+ * Returns the first date that is currently shown by the calendar.
+ *
+ * @return the first date.
+ */
+ public abstract Date getFirstDate();
+
+ /**
+ * Returns the last date that is currently shown by the calendar.
+ *
+ * @return the last date.
+ */
+ public abstract Date getLastDate();
+
+ /**
+ * Is the cell representing the given date enabled?
+ *
+ * @param date the date
+ * @return is the date enabled
+ */
+ public abstract boolean isDateEnabled(Date date);
+
+ /**
+ * Removes a visible style name from the cell of the supplied date.
+ *
+ * @param styleName style name to remove
+ * @param date date that will have the supplied style added
+ */
+ public abstract void removeStyleFromDate(String styleName, Date date);
+
+ /**
+ * Enables or Disables a particular date. by default all valid dates are
+ * enabled after a rendering event. Disabled dates cannot be selected.
+ *
+ * @param enabled true for enabled, false for disabled
+ * @param date date to enable or disable
+ */
+ public abstract void setEnabledOnDate(boolean enabled, Date date);
+
+ /**
+ * Allows the calendar view to update the date picker's highlighted date.
+ *
+ * @param date the highlighted date
+ */
+ protected final void setHighlightedDate(Date date) {
+ getDatePicker().setHighlightedDate(date);
+ }
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/datepicker/client/CellGridImpl.java b/user/src/com/google/gwt/user/datepicker/client/CellGridImpl.java
new file mode 100644
index 0000000..7530165
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/CellGridImpl.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.UIObject;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Highlighting, selectable cell grid. Used to help construct the default
+ * calendar view.
+ *
+ * @param <V> type of value in grid.
+ */
+@SuppressWarnings("unchecked")
+abstract class CellGridImpl<V> extends Grid {
+
+ /**
+ * Cell type.
+ */
+ abstract class Cell extends UIObject {
+ private boolean enabled = true;
+ private V value;
+ private int index;
+
+ /**
+ * Create a cell grid.
+ *
+ * @param elem the wrapped element
+ * @param value the value
+ */
+ public Cell(Element elem, V value) {
+ this.value = value;
+ Cell current = this;
+ index = cellList.size();
+ cellList.add(current);
+
+ setElement(elem);
+ elementToCell.put(current);
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public boolean isHighlighted() {
+ return this == highlightedCell;
+ }
+
+ public boolean isSelected() {
+ return selectedCell == this;
+ }
+
+ public final void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ onEnabled(enabled);
+ }
+
+ public void verticalNavigation(int keyCode) {
+ switch (keyCode) {
+ case KeyCodes.KEY_UP:
+ setHighlighted(previousItem());
+ break;
+ case KeyCodes.KEY_DOWN:
+ setHighlighted(nextItem());
+ break;
+ case KeyCodes.KEY_ESCAPE:
+ // Figure out new event for this.
+ break;
+ case KeyCodes.KEY_ENTER:
+ setSelected(this);
+ break;
+ }
+ }
+
+ protected Cell nextItem() {
+ if (index == getLastIndex()) {
+ return cellList.get(0);
+ } else {
+ return cellList.get(index + 1);
+ }
+ }
+
+ protected void onEnabled(boolean enabled) {
+ updateStyle();
+ }
+
+ protected void onHighlighted(boolean highlighted) {
+ updateStyle();
+ }
+
+ protected void onSelected(boolean selected) {
+ updateStyle();
+ }
+
+ protected Cell previousItem() {
+ if (index != 0) {
+ return cellList.get(index - 1);
+ } else {
+ return cellList.get(getLastIndex());
+ }
+ }
+
+ protected abstract void updateStyle();
+
+ private int getLastIndex() {
+ return cellList.size() - 1;
+ }
+ }
+
+ private Cell highlightedCell;
+
+ private Cell selectedCell;
+ private ElementMapper<Cell> elementToCell = new ElementMapper<Cell>();
+ private ArrayList<Cell> cellList = new ArrayList<Cell>();
+
+ protected CellGridImpl() {
+ setCellPadding(0);
+ setCellSpacing(0);
+ setBorderWidth(0);
+ sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT);
+ }
+
+ public Cell getCell(Element element) {
+ return elementToCell.get((com.google.gwt.user.client.Element) element);
+ }
+
+ public Cell getCell(Event e) {
+ // Find out which cell was actually clicked.
+ Element td = getEventTargetCell(e);
+ return td != null
+ ? elementToCell.get((com.google.gwt.user.client.Element) td) : null;
+ }
+
+ public Cell getCell(int i) {
+ return cellList.get(i);
+ }
+
+ public Iterator getCells() {
+ return cellList.iterator();
+ }
+
+ public Cell getHighlightedCell() {
+ return highlightedCell;
+ }
+
+ public int getNumCells() {
+ return cellList.size();
+ }
+
+ public Cell getSelectedCell() {
+ return selectedCell;
+ }
+
+ public V getSelectedValue() {
+ return getValue(selectedCell);
+ }
+
+ public V getValue(Cell cell) {
+ return (cell == null ? null : cell.getValue());
+ }
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ switch (DOM.eventGetType(event)) {
+ case Event.ONCLICK: {
+ Cell cell = getCell(event);
+ if (isActive(cell)) {
+ setSelected(cell);
+ }
+ break;
+ }
+ case Event.ONMOUSEOUT: {
+ Element e = DOM.eventGetFromElement(event);
+ if (e != null) {
+ Cell cell = elementToCell.get((com.google.gwt.user.client.Element) e);
+ if (cell == highlightedCell) {
+ setHighlighted(null);
+ }
+ }
+ break;
+ }
+ case Event.ONMOUSEOVER: {
+ Element e = DOM.eventGetToElement(event);
+ if (e != null) {
+ Cell cell = elementToCell.get((com.google.gwt.user.client.Element) e);
+ if (isActive(cell)) {
+ setHighlighted(cell);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onUnload() {
+ setHighlighted(null);
+ }
+
+ public final void setHighlighted(Cell nextHighlighted) {
+ if (nextHighlighted == highlightedCell) {
+ return;
+ }
+ Cell oldHighlighted = highlightedCell;
+ highlightedCell = nextHighlighted;
+ if (oldHighlighted != null) {
+ oldHighlighted.onHighlighted(false);
+ }
+ if (highlightedCell != null) {
+ highlightedCell.onHighlighted(true);
+ }
+ }
+
+ public final void setSelected(Cell cell) {
+ Cell last = getSelectedCell();
+ selectedCell = cell;
+
+ if (last != null) {
+ last.onSelected(false);
+ }
+ if (selectedCell != null) {
+ selectedCell.onSelected(true);
+ }
+ onSelected(last, selectedCell);
+ }
+
+ protected void onKeyDown(Cell lastHighlighted, KeyDownEvent event) {
+ if (event.isAnyModifierKeyDown()) {
+ return;
+ }
+ int keyCode = event.getNativeKeyCode();
+ if (lastHighlighted == null) {
+ if (keyCode == KeyCodes.KEY_DOWN && cellList.size() > 0) {
+ setHighlighted(cellList.get(0));
+ }
+ } else {
+ lastHighlighted.verticalNavigation(keyCode);
+ }
+ }
+
+ protected abstract void onSelected(Cell lastSelected, Cell cell);
+
+ private boolean isActive(Cell cell) {
+ return cell != null && cell.isEnabled();
+ }
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/DateBox.java b/user/src/com/google/gwt/user/datepicker/client/DateBox.java
new file mode 100644
index 0000000..6bc18b9
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/DateBox.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.DeferredCommand;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HasValue;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.TextBox;
+
+import java.util.Date;
+
+/**
+ * A text box that shows a {@link DatePicker} when the user focuses on it.
+ *
+ * <h3>CSS Style Rules</h3>
+ *
+ * <ul class="css">
+ *
+ * <li>.gwt-DateBox { }</li>
+ *
+ * <li>.dateBoxPopup { Applied to the popup around the DatePicker }</li>
+ *
+ * </ul>
+ *
+ * <p>
+ * <h3>Example</h3>
+ * {@example com.google.gwt.examples.DateBoxExample}
+ * </p>
+ */
+public class DateBox extends Composite implements HasValue<Date> {
+
+ /**
+ * Implemented by a delegate to report errors parsing date values from the
+ * user's input.
+ */
+ public interface InvalidDateReporter {
+ /**
+ * Called when a valid date has been parsed, or the datebox has been
+ * cleared.
+ */
+ void clearError();
+
+ /**
+ * Given an unparseable string, explain the situation to the user.
+ *
+ * @param input what the user typed
+ */
+ void reportError(String input);
+ }
+
+ private class DateBoxHandler implements ValueChangeHandler<Date>,
+ FocusHandler, BlurHandler, ClickHandler, KeyDownHandler {
+
+ public void onBlur(BlurEvent event) {
+ if (!popup.isVisible()) {
+ updateDateFromTextBox();
+ }
+ }
+
+ public void onClick(ClickEvent event) {
+ showDatePicker();
+ }
+
+ public void onFocus(FocusEvent event) {
+ if (allowDPShow) {
+ showDatePicker();
+ }
+ }
+
+ public void onKeyDown(KeyDownEvent event) {
+ switch (event.getNativeKeyCode()) {
+ case KeyCodes.KEY_ENTER:
+ case KeyCodes.KEY_TAB:
+ case KeyCodes.KEY_ESCAPE:
+ case KeyCodes.KEY_UP:
+ updateDateFromTextBox();
+ hideDatePicker();
+ break;
+ case KeyCodes.KEY_DOWN:
+ showDatePicker();
+ break;
+ }
+ }
+
+ public void onValueChange(ValueChangeEvent<Date> event) {
+ setValue(event.getValue());
+ hideDatePicker();
+ preventDatePickerPopup();
+ box.setFocus(true);
+ }
+ }
+
+ /**
+ * Default style name.
+ */
+ public static final String DEFAULT_STYLENAME = "gwt-DateBox";
+
+ public static final InvalidDateReporter DEFAULT_INVALID_DATE_REPORTER = new InvalidDateReporter() {
+ public void clearError() {
+ }
+
+ public void reportError(String input) {
+ }
+ };
+ private static final DateTimeFormat DEFAULT_FORMATTER = DateTimeFormat.getMediumDateFormat();
+
+ private final PopupPanel popup;
+ private final TextBox box = new TextBox();
+ private final DatePicker picker;
+
+ private final InvalidDateReporter invalidDateReporter;
+ private DateTimeFormat dateFormatter = DEFAULT_FORMATTER;
+
+ private boolean allowDPShow = true;
+
+ /**
+ * Create a new date box with a new {@link DatePicker} and the
+ * {@link #DEFAULT_INVALID_DATE_REPORTER}, which does nothing.
+ */
+ public DateBox() {
+ this(new DatePicker(), DEFAULT_INVALID_DATE_REPORTER);
+ }
+
+ /**
+ * Create a new date box.
+ *
+ * @param picker the picker to drop down from the date box
+ */
+ public DateBox(DatePicker picker, InvalidDateReporter invalidDateReporter) {
+ this.picker = picker;
+ this.invalidDateReporter = invalidDateReporter;
+ this.popup = new PopupPanel();
+ popup.setAutoHideEnabled(true);
+ popup.setAutoHidePartner(box.getElement());
+ popup.setWidget(picker);
+ popup.setStyleName("dateBoxPopup");
+ initWidget(box);
+ setStyleName(DEFAULT_STYLENAME);
+
+ DateBoxHandler handler = new DateBoxHandler();
+ picker.addValueChangeHandler(handler);
+ box.addFocusHandler(handler);
+ box.addBlurHandler(handler);
+ box.addClickHandler(handler);
+ box.addKeyDownHandler(handler);
+ }
+
+ public HandlerRegistration addValueChangeHandler(
+ ValueChangeHandler<Date> handler) {
+ return addHandler(handler, ValueChangeEvent.getType());
+ }
+
+ /**
+ * Gets the current cursor position in the date box.
+ *
+ * @return the cursor position
+ *
+ */
+ public int getCursorPos() {
+ return box.getCursorPos();
+ }
+
+ /**
+ * Gets the date picker.
+ *
+ * @return the date picker
+ */
+ public DatePicker getDatePicker() {
+ return picker;
+ }
+
+ /**
+ * Gets the date box's position in the tab index.
+ *
+ * @return the date box's tab index
+ */
+ public int getTabIndex() {
+ return box.getTabIndex();
+ }
+
+ /**
+ * Get text box.
+ *
+ * @return the text box used to enter the formatted date
+ */
+ public TextBox getTextBox() {
+ return box;
+ }
+
+ /**
+ * Get the date displayed, or null if the text box is empty, or cannot be
+ * interpretted. The {@link InvalidDateReporter} may fire as a side effect of
+ * this call.
+ *
+ * @return the Date
+ */
+ public Date getValue() {
+ return parseDate(true);
+ }
+
+ /**
+ * Hide the date picker.
+ */
+ public void hideDatePicker() {
+ popup.hide();
+ }
+
+ /**
+ * @return true if date picker is currently visible, false if not
+ */
+ public boolean isDatePickerVisible() {
+ return popup.isVisible();
+ }
+
+ /**
+ * Sets the date box's 'access key'. This key is used (in conjunction with a
+ * browser-specific modifier key) to automatically focus the widget.
+ *
+ * @param key the date box's access key
+ */
+ public void setAccessKey(char key) {
+ box.setAccessKey(key);
+ }
+
+ /**
+ * Sets the date format to the given format. If date box is not empty,
+ * contents of date box will be replaced with current date in new format. If
+ * the date cannot be parsed, the current value will be preserved and the
+ * InvalidDateReporter notified as usual.
+ *
+ * @param format format.
+ */
+ public void setDateFormat(DateTimeFormat format) {
+ if (format != dateFormatter) {
+ Date date = getValue();
+ dateFormatter = format;
+ setValue(date);
+ }
+ }
+
+ /**
+ * Sets whether the date box is enabled.
+ *
+ * @param enabled is the box enabled
+ */
+ public void setEnabled(boolean enabled) {
+ box.setEnabled(enabled);
+ }
+
+ /**
+ * Explicitly focus/unfocus this widget. Only one widget can have focus at a
+ * time, and the widget that does will receive all keyboard events.
+ *
+ * @param focused whether this widget should take focus or release it
+ */
+ public void setFocus(boolean focused) {
+ box.setFocus(focused);
+ }
+
+ /**
+ * Sets the date box's position in the tab index. If more than one widget has
+ * the same tab index, each such widget will receive focus in an arbitrary
+ * order. Setting the tab index to <code>-1</code> will cause this widget to
+ * be removed from the tab order.
+ *
+ * @param index the date box's tab index
+ */
+ public void setTabIndex(int index) {
+ box.setTabIndex(index);
+ }
+
+ /**
+ * Set the date.
+ */
+ public void setValue(Date date) {
+ setValue(date, false);
+ }
+
+ public void setValue(Date date, boolean fireEvents) {
+ Date oldDate = getValue();
+
+ if (date == null) {
+ picker.setValue(null);
+ box.setText("");
+ } else {
+ picker.setValue(date, false);
+ picker.setCurrentMonth(date);
+ setDate(date);
+ }
+
+ invalidDateReporter.clearError();
+ if (fireEvents) {
+ DateChangeEvent.fireIfNotEqualDates(this, oldDate, date);
+ }
+ }
+
+ /**
+ * Parses the current date box's value and shows that date.
+ */
+ public void showDatePicker() {
+ Date current = parseDate(false);
+ if (current == null) {
+ current = new Date();
+ }
+ picker.setCurrentMonth(current);
+ popup.showRelativeTo(this);
+ }
+
+ private Date parseDate(boolean reportError) {
+ Date d = null;
+ String text = box.getText().trim();
+ if (!text.equals("")) {
+ try {
+ d = dateFormatter.parse(text);
+ } catch (IllegalArgumentException exception) {
+ if (reportError) {
+ invalidDateReporter.reportError(text);
+ }
+ }
+ }
+ return d;
+ }
+
+ private void preventDatePickerPopup() {
+ allowDPShow = false;
+ DeferredCommand.addCommand(new Command() {
+ public void execute() {
+ allowDPShow = true;
+ }
+ });
+ }
+
+ /**
+ * Does the actual work of setting the date. Performs no validation, fires no
+ * events.
+ */
+ private void setDate(Date value) {
+ box.setText(dateFormatter.format(value));
+ }
+
+ private void updateDateFromTextBox() {
+ Date parsedDate = parseDate(true);
+ if (parsedDate != null) {
+ setValue(parsedDate);
+ }
+ }
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/DateChangeEvent.java b/user/src/com/google/gwt/user/datepicker/client/DateChangeEvent.java
new file mode 100644
index 0000000..6c2affb
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/DateChangeEvent.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.event.logical.shared.HasHandlers;
+import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+
+import java.util.Date;
+
+/**
+ * Creates a new value every time a date is accessed.
+ */
+class DateChangeEvent extends ValueChangeEvent<Date> {
+
+ /**
+ * Fires value change event if the old value is not equal to the new value.
+ * Use this call rather than making the decision to short circuit yourself for
+ * safe handling of null.
+ *
+ * @param <I> the old value type
+ * @param <S> The event source
+ * @param source the source of the handlers
+ * @param oldValue the oldValue, may be null
+ * @param newValue the newValue, may be null
+ */
+ public static <S extends HasValueChangeHandlers<Date> & HasHandlers> void fireIfNotEqualDates(
+ S source, Date oldValue, Date newValue) {
+ if (ValueChangeEvent.shouldFire(source, oldValue, newValue)) {
+ source.getHandlers().fireEvent(new DateChangeEvent(newValue));
+ }
+ }
+
+ /**
+ * Creates a new date value change event.
+ *
+ * @param value the value
+ */
+ protected DateChangeEvent(Date value) {
+ super(value);
+ }
+
+ public Date getValue() {
+ return CalendarUtil.copyDate(super.getValue());
+ }
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/DatePicker.java b/user/src/com/google/gwt/user/datepicker/client/DatePicker.java
new file mode 100644
index 0000000..e6705a5
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/DatePicker.java
@@ -0,0 +1,652 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.event.logical.shared.HasHighlightHandlers;
+import com.google.gwt.event.logical.shared.HasShowRangeHandlers;
+import com.google.gwt.event.logical.shared.HighlightEvent;
+import com.google.gwt.event.logical.shared.HighlightHandler;
+import com.google.gwt.event.logical.shared.ShowRangeEvent;
+import com.google.gwt.event.logical.shared.ShowRangeHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HasValue;
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Standard GWT date picker.
+ *
+ * <h3>CSS Style Rules</h3>
+ *
+ * <ul class="css">
+ *
+ * <li>.gwt-DatePicker { }</li>
+ *
+ * <li>.datePickerMonthSelector { the month selector widget }</li>
+ *
+ * <li>.datePickerMonth { the month in the month selector widget } <li>
+ *
+ * <li>.datePickerPreviousButton { the previous month button } <li>
+ *
+ * <li>.datePickerNextButton { the next month button } <li>
+ *
+ * <li>.datePickerDays { the portion of the picker that shows the days }</li>
+ *
+ * <li>.datePickerWeekdayLabel { the label over weekdays }</li>
+ *
+ * <li>.datePickerWeekendLabel { the label over weekends }</li>
+ *
+ * <li>.datePickerDay { a single day }</li>
+ *
+ * <li>.datePickerDayIsToday { today's date }</li>
+ *
+ * <li>.datePickerDayIsWeekend { a weekend day }</li>
+ *
+ * <li>.datePickerDayIsFiller { a day in another month }</li>
+ *
+ * <li>.datePickerDayIsValue { the selected day }</li>
+ *
+ * <li>.datePickerDayIsDisabled { a disabled day }</li>
+ *
+ * <li>.datePickerDayIsHighlighted { the currently highlighted day }</li>
+ *
+ * <li>.datePickerDayIsValueAndHighlighted { the highlighted day if it is also
+ * selected }</li>
+ *
+ * </ul>
+ *
+ * <p>
+ * <h3>Example</h3>
+ * {@example com.google.gwt.examples.DatePickerExample}
+ * </p>
+ */
+public class DatePicker extends Composite implements
+ HasHighlightHandlers<Date>, HasShowRangeHandlers<Date>, HasValue<Date> {
+
+ /**
+ * Convenience class to group css style names.
+ */
+ static class StandardCss {
+
+ static StandardCss DEFAULT = new StandardCss("gwt-DatePicker", "datePicker");
+
+ private String baseName;
+ private String widgetName;
+
+ public StandardCss(String widgetName, String baseName) {
+ this.widgetName = widgetName;
+ this.baseName = baseName;
+ }
+
+ public String datePicker() {
+ return getWidgetStyleName();
+ }
+
+ public String day() {
+ return wrap("Day");
+ }
+
+ public String day(String dayModifier) {
+ return day() + "Is" + dayModifier;
+ }
+
+ public String dayIsDisabled() {
+ return day("Disabled");
+ }
+
+ public String dayIsFiller() {
+ return day("Filler");
+ }
+
+ public String dayIsHighlighted() {
+ return day("Highlighted");
+ }
+
+ public String dayIsToday() {
+ return day("Today");
+ }
+
+ public String dayIsValue() {
+ return day("Value");
+ }
+
+ public String dayIsValueAndHighlighted() {
+ return dayIsValue() + "AndHighlighted";
+ }
+
+ public String dayIsWeekend() {
+ return day("Weekend");
+ }
+
+ public String days() {
+ return wrap("Days");
+ }
+
+ public String daysLabel() {
+ return wrap("DaysLabel");
+ }
+
+ public String getBaseStyleName() {
+ return baseName;
+ }
+
+ public String getWidgetStyleName() {
+ return widgetName;
+ }
+
+ public String month() {
+ return wrap("Month");
+ }
+
+ public String monthSelector() {
+ return wrap("MonthSelector");
+ }
+
+ public String nextButton() {
+ return wrap("NextButton");
+ }
+
+ public String previousButton() {
+ return wrap("PreviousButton");
+ }
+
+ public String weekdayLabel() {
+ return wrap("WeekdayLabel");
+ }
+
+ public String weekendLabel() {
+ return wrap("WeekendLabel");
+ }
+
+ /**
+ * Prepends the base name to the given style.
+ *
+ * @param style style name
+ * @return style name
+ */
+ protected String wrap(String style) {
+ return baseName + style;
+ }
+ }
+
+ /**
+ * A date highlighted event that copied on read.
+ */
+ private class DateHighlightEvent extends HighlightEvent<Date> {
+ protected DateHighlightEvent(Date highlighted) {
+ super(highlighted);
+ }
+
+ @Override
+ public Date getHighlighted() {
+ return CalendarUtil.copyDate(super.getHighlighted());
+ }
+ }
+
+ private class DateStyler {
+ private Map<String, String> info = new HashMap<String, String>();
+
+ public String getStyleName(Date d) {
+ return info.get(genKey(d));
+ }
+
+ public void setStyleName(Date d, String styleName, boolean add) {
+ // Code is easier to maintain if surrounded by " ", and on all browsers
+ // this is a no-op.
+ styleName = " " + styleName + " ";
+ String key = genKey(d);
+ String current = info.get(key);
+
+ if (add) {
+ if (current == null) {
+ info.put(key, styleName);
+ } else if (current.indexOf(styleName) == -1) {
+ info.put(key, current + styleName);
+ }
+ } else {
+ if (current != null) {
+ String newValue = current.replaceAll(styleName, "");
+ if (newValue.trim().length() == 0) {
+ info.remove(key);
+ } else {
+ info.put(key, newValue);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private String genKey(Date d) {
+ return d.getYear() + "/" + d.getMonth() + "/" + d.getDate();
+ }
+ }
+ private final DateStyler styler = new DateStyler();
+ private final MonthSelector monthSelector;
+ private final CalendarView view;
+ private final CalendarModel model;
+ private Date value;
+ private Date highlighted;
+
+ private StandardCss css = StandardCss.DEFAULT;
+
+ /**
+ * Create a new date picker.
+ */
+ public DatePicker() {
+ this(new DefaultMonthSelector(), new DefaultCalendarView(),
+ new CalendarModel());
+ }
+
+ /**
+ * Creates a new date picker.
+ *
+ * @param monthSelector the month selector
+ * @param view the view
+ * @param model the model
+ */
+
+ protected DatePicker(MonthSelector monthSelector, CalendarView view,
+ CalendarModel model) {
+
+ this.model = model;
+ this.monthSelector = monthSelector;
+ monthSelector.setDatePicker(this);
+ this.view = view;
+ view.setDatePicker(this);
+
+ view.setup();
+ monthSelector.setup();
+ this.setup();
+
+ setCurrentMonth(new Date());
+ addStyleToDates(css().dayIsToday(), new Date());
+ }
+
+ public HandlerRegistration addHighlightHandler(HighlightHandler<Date> handler) {
+ return addHandler(handler, HighlightEvent.getType());
+ }
+
+ public HandlerRegistration addShowRangeHandler(ShowRangeHandler<Date> handler) {
+ return addHandler(handler, ShowRangeEvent.getType());
+ }
+
+ /**
+ * Adds a show range handler and immediately activate the handler on the
+ * current view.
+ *
+ * @param handler the handler
+ * @return the handler registration
+ */
+ public HandlerRegistration addShowRangeHandlerAndFire(
+ ShowRangeHandler<Date> handler) {
+ ShowRangeEvent<Date> event = new ShowRangeEvent<Date>(
+ getView().getFirstDate(), getView().getLastDate()) {
+ };
+ handler.onShowRange(event);
+ return addShowRangeHandler(handler);
+ }
+
+ /**
+ * Add a style name to the given dates.
+ */
+ public void addStyleToDates(String styleName, Date date) {
+ styler.setStyleName(date, styleName, true);
+ if (isDateVisible(date)) {
+ getView().addStyleToDate(styleName, date);
+ }
+ }
+
+ /**
+ * Add a style name to the given dates.
+ */
+ public void addStyleToDates(String styleName, Date date, Date... moreDates) {
+ addStyleToDates(styleName, date);
+ for (Date d : moreDates) {
+ addStyleToDates(styleName, d);
+ }
+ }
+
+ /**
+ * Add a style name to the given dates.
+ */
+ public void addStyleToDates(String styleName, Iterable<Date> dates) {
+ for (Date d : dates) {
+ addStyleToDates(styleName, d);
+ }
+ }
+
+ /**
+ * Adds the given style name to the specified dates, which must be visible.
+ * This is only set until the next time the DatePicker is refreshed.
+ */
+ public void addTransientStyleToDates(String styleName, Date date) {
+ assert isDateVisible(date) : date + " must be visible";
+ getView().addStyleToDate(styleName, date);
+ }
+
+ /**
+ * Adds the given style name to the specified dates, which must be visible.
+ * This is only set until the next time the DatePicker is refreshed.
+ */
+ public final void addTransientStyleToDates(String styleName, Date date,
+ Date... moreDates) {
+ addTransientStyleToDates(styleName, date);
+ for (Date d : moreDates) {
+ addTransientStyleToDates(styleName, d);
+ }
+ }
+
+ /**
+ * Adds the given style name to the specified dates, which must be visible.
+ * This is only set until the next time the DatePicker is refreshed.
+ */
+ public final void addTransientStyleToDates(String styleName,
+ Iterable<Date> dates) {
+ for (Date d : dates) {
+ addTransientStyleToDates(styleName, d);
+ }
+ }
+
+ public HandlerRegistration addValueChangeHandler(
+ ValueChangeHandler<Date> handler) {
+ return addHandler(handler, ValueChangeEvent.getType());
+ }
+
+ /**
+ * Gets the current month the date picker is showing.
+ *
+ * <p>
+ * A datepicker <b> may </b> show days not in the current month. It
+ * <b>must</b> show all days in the current month.
+ * </p>
+ * @return the current month
+ *
+ */
+ public Date getCurrentMonth() {
+ return getModel().getCurrentMonth();
+ }
+
+ /**
+ * Returns the first shown date.
+ *
+ * @return the first date.
+ */
+ // Final because the view should always control the value of the first date.
+ public final Date getFirstDate() {
+ return view.getFirstDate();
+ }
+
+ /**
+ * Gets the highlighted date (the one the mouse is hovering over), if any.
+ *
+ * @return the highlighted date
+ */
+ public final Date getHighlightedDate() {
+ return CalendarUtil.copyDate(highlighted);
+ }
+
+ /**
+ * Returns the last shown date.
+ *
+ * @return the last date.
+ */
+ // Final because the view should always control the value of the last date.
+ public final Date getLastDate() {
+ return view.getLastDate();
+ }
+
+ /**
+ * Gets the style associated with a date (does not include styles
+ * set via {@link #addTransientStyleToDates}).
+ *
+ * @param date the date
+ * @return the styles associated with this date
+ */
+ public String getStyleOfDate(Date date) {
+ return styler.getStyleName(date);
+ }
+
+ /**
+ * Returns the selected date, or null if none is selected.
+ *
+ * @return the selected date, or null
+ */
+ public final Date getValue() {
+ return CalendarUtil.copyDate(value);
+ }
+
+ /**
+ * Is the visible date enabled?
+ *
+ * @param date the date, which must be visible
+ * @return is the date enabled?
+ */
+ public boolean isDateEnabled(Date date) {
+ assert isDateVisible(date) : date + " is not visible";
+ return getView().isDateEnabled(date);
+ }
+
+ /**
+ * Is the date currently shown in the date picker?
+ *
+ * @param date
+ * @return is the date currently shown
+ */
+ public boolean isDateVisible(Date date) {
+ CalendarView r = getView();
+ Date first = r.getFirstDate();
+ Date last = r.getLastDate();
+ return (date != null && (first.equals(date) || last.equals(date) || (first.before(date) && last.after(date))));
+ }
+
+ /**
+ * Removes the styleName from the given dates (even if it is transient).
+ */
+ public void removeStyleFromDates(String styleName, Date date) {
+ styler.setStyleName(date, styleName, false);
+ if (isDateVisible(date)) {
+ getView().removeStyleFromDate(styleName, date);
+ }
+ }
+
+ /**
+ * Removes the styleName from the given dates (even if it is transient).
+ */
+ public void removeStyleFromDates(String styleName, Date date, Date... moreDates) {
+ removeStyleFromDates(styleName, date);
+ for (Date d : moreDates) {
+ removeStyleFromDates(styleName, d);
+ }
+ }
+
+ /**
+ * Removes the styleName from the given dates (even if it is transient).
+ */
+ public void removeStyleFromDates(String styleName, Iterable<Date> dates) {
+ for (Date d : dates) {
+ removeStyleFromDates(styleName, d);
+ }
+ }
+
+ /**
+ * Sets the date picker to show the given month, use {@link #getFirstDate()}
+ * and {@link #getLastDate()} to access the exact date range the date picker
+ * chose to display.
+ * <p>
+ * A datepicker <b> may </b> show days not in the current month. It
+ * <b>must</b> show all days in the current month.
+ * </p>
+ *
+ * @param month the month to show
+ */
+ public void setCurrentMonth(Date month) {
+ getModel().setCurrentMonth(month);
+ refreshAll();
+ }
+
+ /**
+ * Sets the date picker style name.
+ */
+ @Override
+ public void setStyleName(String styleName) {
+ css = new StandardCss(styleName, "datePicker");
+ super.setStyleName(styleName);
+ }
+
+ /**
+ * Sets a visible date to be enabled or disabled. This is only set until the
+ * next time the DatePicker is refreshed.
+ */
+ public final void setTransientEnabledOnDates(boolean enabled, Date date) {
+ assert isDateVisible(date) : date + " must be visible";
+ getView().setEnabledOnDate(enabled, date);
+ }
+
+ /**
+ * Sets a visible date to be enabled or disabled. This is only set until the
+ * next time the DatePicker is refreshed.
+ */
+ public final void setTransientEnabledOnDates(boolean enabled,
+ Date date, Date... moreDates) {
+ setTransientEnabledOnDates(enabled, date);
+ for (Date d : moreDates) {
+ setTransientEnabledOnDates(enabled, d);
+ }
+ }
+
+ /**
+ * Sets a group of visible dates to be enabled or disabled. This is only set
+ * until the next time the DatePicker is refreshed.
+ */
+ public final void setTransientEnabledOnDates(boolean enabled,
+ Iterable<Date> dates) {
+ for (Date d : dates) {
+ setTransientEnabledOnDates(enabled, d);
+ }
+ }
+
+ /**
+ * Sets the {@link DatePicker}'s value.
+ *
+ * @param newValue the new value
+ */
+ public final void setValue(Date newValue) {
+ setValue(newValue, false);
+ }
+
+ /**
+ * Sets the {@link DatePicker}'s value.
+ *
+ * @param newValue the new value for this date picker
+ * @param fireEvents should events be fired.
+ */
+ public final void setValue(Date newValue, boolean fireEvents) {
+ Date oldValue = value;
+
+ if (oldValue != null) {
+ removeStyleFromDates(css().dayIsValue(), oldValue);
+ }
+
+ value = CalendarUtil.copyDate(newValue);
+ if (value != null) {
+ addStyleToDates(css().dayIsValue(), value);
+ }
+ if (fireEvents) {
+ DateChangeEvent.fireIfNotEqualDates(this, oldValue, newValue);
+ }
+ }
+
+ /**
+ * Gets the {@link CalendarModel} associated with this date picker.
+ *
+ * @return the model
+ */
+ protected final CalendarModel getModel() {
+ return model;
+ }
+
+ /**
+ * Gets the {@link MonthSelector} associated with this date picker.
+ *
+ * @return the month selector
+ */
+ protected final MonthSelector getMonthSelector() {
+ return monthSelector;
+ }
+
+ /**
+ * Gets the {@link CalendarView} associated with this date picker.
+ *
+ * @return the view
+ */
+ protected final CalendarView getView() {
+ return view;
+ }
+
+ /**
+ * Refreshes all components of this date picker.
+ */
+ protected final void refreshAll() {
+ highlighted = null;
+ getModel().refresh();
+ getView().refresh();
+ getMonthSelector().refresh();
+ ShowRangeEvent.fire(this, getFirstDate(), getLastDate());
+ }
+
+ /**
+ * Sets up the date picker.
+ */
+ protected void setup() {
+ /*
+ * Use a table (VerticalPanel) to get shrink-to-fit behavior. Divs expand to
+ * fill the available width, so we'd need to give it a size.
+ */
+ VerticalPanel panel = new VerticalPanel();
+ initWidget(panel);
+ setStyleName(panel.getElement(), css.datePicker());
+ setStyleName(css().datePicker());
+ panel.add(this.getMonthSelector());
+ panel.add(this.getView());
+ }
+
+ /**
+ * Gets the css associated with this date picker for use by extended month and
+ * cell grids.
+ *
+ * @return the css.
+ */
+ final StandardCss css() {
+ return css;
+ }
+
+ /**
+ * Sets the highlighted date.
+ *
+ * @param highlighted highlighted date
+ */
+ void setHighlightedDate(Date highlighted) {
+ this.highlighted = highlighted;
+ fireEvent(new DateHighlightEvent(highlighted));
+ }
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/DatePickerComponent.java b/user/src/com/google/gwt/user/datepicker/client/DatePickerComponent.java
new file mode 100644
index 0000000..6250316
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/DatePickerComponent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.user.client.ui.Composite;
+
+/**
+ * Package protected class used to combine functionality for the
+ * {@link MonthSelector} and {@link CalendarView} components.
+ *
+ */
+abstract class DatePickerComponent extends Composite {
+ private DatePicker datePicker;
+
+ public CalendarModel getModel() {
+ return datePicker.getModel();
+ }
+
+ protected void addMonths(int numMonths) {
+ getModel().shiftCurrentMonth(numMonths);
+ getDatePicker().refreshAll();
+ }
+
+ protected DatePicker getDatePicker() {
+ return datePicker;
+ }
+
+ /**
+ * Refresh the component. Usually called because the model's current date has
+ * changed. In general, only should be called by {@link DatePicker}. Use
+ * refreshAll() if you need to refresh all components.
+ */
+ protected abstract void refresh();
+
+ /**
+ * Refreshes the {@link DatePicker}, {@link CalendarView}, and
+ * {@link CalendarModel}.
+ */
+ protected void refreshAll() {
+ getDatePicker().refreshAll();
+ }
+
+ /**
+ * Set up the component.
+ */
+ protected abstract void setup();
+
+ DatePicker.StandardCss css() {
+ return datePicker.css();
+ }
+
+ void setDatePicker(DatePicker me) {
+ this.datePicker = me;
+ }
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/DefaultCalendarView.java b/user/src/com/google/gwt/user/datepicker/client/DefaultCalendarView.java
new file mode 100644
index 0000000..1f72e65
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/DefaultCalendarView.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+import com.google.gwt.user.datepicker.client.DefaultCalendarView.CellGrid.DateCell;
+
+import java.util.Date;
+
+/**
+ * Simple calendar view. Not extensible as we wish to evolve it freely over
+ * time.
+ */
+
+@SuppressWarnings(/* Date manipulation required */{"deprecation"})
+public final class DefaultCalendarView extends CalendarView {
+
+ /**
+ * Cell grid.
+ */
+ // Javac bug requires that date be fully specified here.
+ class CellGrid extends CellGridImpl<java.util.Date> {
+ /**
+ * A cell representing a date.
+ */
+ class DateCell extends Cell {
+ private String cellStyle;
+ private String dateStyle;
+
+ DateCell(Element td, boolean isWeekend) {
+ super(td, new Date());
+ cellStyle = css().day();
+ if (isWeekend) {
+ cellStyle += " " + css().dayIsWeekend();
+ }
+ }
+
+ @Override
+ public void addStyleName(String styleName) {
+ if (dateStyle.indexOf(" " + styleName + " ") == -1) {
+ dateStyle += styleName + " ";
+ }
+ updateStyle();
+ }
+
+ public boolean isFiller() {
+ return !getModel().isInCurrentMonth(getValue());
+ }
+
+ @Override
+ public void onHighlighted(boolean highlighted) {
+ setHighlightedDate(getValue());
+ updateStyle();
+ }
+
+ @Override
+ public void onSelected(boolean selected) {
+ if (selected) {
+ getDatePicker().setValue(getValue(), true);
+ if (isFiller()) {
+ getDatePicker().setCurrentMonth(getValue());
+ }
+ }
+ updateStyle();
+ }
+
+ @Override
+ public void removeStyleName(String styleName) {
+ dateStyle = dateStyle.replace(" " + styleName + " ", " ");
+ updateStyle();
+ }
+
+ public void update(Date current) {
+ setEnabled(true);
+ getValue().setTime(current.getTime());
+ String value = getModel().formatDayOfMonth(getValue());
+ setText(value);
+ dateStyle = cellStyle;
+ if (isFiller()) {
+ dateStyle += " " + css().dayIsFiller();
+ } else {
+ String extraStyle = getDatePicker().getStyleOfDate(current);
+ if (extraStyle != null) {
+ dateStyle += " " + extraStyle;
+ }
+ }
+ // We want to certify that all date styles have " " before and after
+ // them for ease of adding to and replacing them.
+ dateStyle += " ";
+ updateStyle();
+ }
+
+ @Override
+ public void updateStyle() {
+ String accum = dateStyle;
+
+ if (isHighlighted()) {
+ accum += " " + css().dayIsHighlighted();
+
+ if (isHighlighted() && isSelected()) {
+ accum += " " + css().dayIsValueAndHighlighted();
+ }
+ }
+ if (!isEnabled()) {
+ accum += " " + css().dayIsDisabled();
+ }
+ setStyleName(accum);
+ }
+
+ private void setText(String value) {
+ DOM.setInnerText(getElement(), value);
+ }
+ }
+
+ CellGrid() {
+ resize(CalendarModel.WEEKS_IN_MONTH + 1, CalendarModel.DAYS_IN_WEEK);
+ }
+
+ @Override
+ protected void onSelected(Cell lastSelected, Cell cell) {
+ }
+ }
+
+ private CellGrid grid = new CellGrid();
+
+ private Date firstDisplayed;
+
+ private Date lastDisplayed = new Date();
+
+ /**
+ * Constructor.
+ */
+ public DefaultCalendarView() {
+ }
+
+ @Override
+ public void addStyleToDate(String styleName, Date date) {
+ assert getDatePicker().isDateVisible(date) : "You tried to add style " + styleName + " to "
+ + date + ". The calendar is currently showing " + getFirstDate()
+ + " to " + getLastDate();
+ getCell(date).addStyleName(styleName);
+ }
+
+ @Override
+ public Date getFirstDate() {
+ return firstDisplayed;
+ }
+
+ @Override
+ public Date getLastDate() {
+ return lastDisplayed;
+ }
+
+ @Override
+ public boolean isDateEnabled(Date d) {
+ return getCell(d).isEnabled();
+ }
+
+ @Override
+ public void refresh() {
+ firstDisplayed = getModel().getCurrentFirstDayOfFirstWeek();
+
+ if (firstDisplayed.getDate() == 1) {
+ // show one empty week if date is Monday is the first in month.
+ CalendarUtil.addDaysToDate(firstDisplayed, -7);
+ }
+
+ lastDisplayed.setTime(firstDisplayed.getTime());
+
+ for (int i = 0; i < grid.getNumCells(); i++) {
+ if (i != 0) {
+ CalendarUtil.addDaysToDate(lastDisplayed, 1);
+ }
+ DateCell cell = (DateCell) grid.getCell(i);
+ cell.update(lastDisplayed);
+ }
+ }
+
+ @Override
+ public void removeStyleFromDate(String styleName, Date date) {
+ getCell(date).removeStyleName(styleName);
+ }
+
+ @Override
+ public void setEnabledOnDate(boolean enabled, Date date) {
+ getCell(date).setEnabled(enabled);
+ }
+
+ @Override
+ public void setup() {
+ // Preparation
+ CellFormatter formatter = grid.getCellFormatter();
+ int weekendStartColumn = -1;
+ int weekendEndColumn = -1;
+
+ // Set up the day labels.
+ for (int i = 0; i < CalendarModel.DAYS_IN_WEEK; i++) {
+ int shift = CalendarUtil.getStartingDayOfWeek();
+ int dayIdx = i + shift < CalendarModel.DAYS_IN_WEEK ? i + shift : i
+ + shift - CalendarModel.DAYS_IN_WEEK;
+ grid.setText(0, i, getModel().formatDayOfWeek(dayIdx));
+
+ if (CalendarUtil.isWeekend(dayIdx)) {
+ formatter.setStyleName(0, i, css().weekendLabel());
+ if (weekendStartColumn == -1) {
+ weekendStartColumn = i;
+ } else {
+ weekendEndColumn = i;
+ }
+ } else {
+ formatter.setStyleName(0, i, css().weekdayLabel());
+ }
+ }
+
+ // Set up the calendar grid.
+ for (int row = 1; row <= CalendarModel.WEEKS_IN_MONTH; row++) {
+ for (int column = 0; column < CalendarModel.DAYS_IN_WEEK; column++) {
+ // set up formatter.
+ Element e = formatter.getElement(row, column);
+ grid.new DateCell(e, column == weekendStartColumn
+ || column == weekendEndColumn);
+ }
+ }
+ initWidget(grid);
+ grid.setStyleName(css().days());
+ }
+
+ private DateCell getCell(Date d) {
+ int index = CalendarUtil.getDaysBetween(firstDisplayed, d);
+ assert (index >= 0);
+
+ DateCell cell = (DateCell) grid.getCell(index);
+ if (cell.getValue().getDate() != d.getDate()) {
+ throw new IllegalStateException(d + " cannot be associated with cell "
+ + cell + " as it has date " + cell.getValue());
+ }
+ return cell;
+ }
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/DefaultMonthSelector.java b/user/src/com/google/gwt/user/datepicker/client/DefaultMonthSelector.java
new file mode 100644
index 0000000..611b354
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/DefaultMonthSelector.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.PushButton;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+
+/**
+ * A simple {@link MonthSelector} used for the default date picker. Not
+ * extensible as we wish to evolve it freely over time.
+ */
+
+public final class DefaultMonthSelector extends MonthSelector {
+
+ private PushButton backwards;
+ private PushButton forwards;
+ private Grid grid;
+
+ /**
+ * Constructor.
+ */
+ public DefaultMonthSelector() {
+ }
+
+ @Override
+ protected void refresh() {
+ String formattedMonth = getModel().formatCurrentMonth();
+ grid.setText(0, 1, formattedMonth);
+ }
+
+ @Override
+ protected void setup() {
+ // Set up backwards.
+ backwards = new PushButton();
+ backwards.addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ addMonths(-1);
+ }
+ });
+
+ backwards.getUpFace().setHTML("«");
+ backwards.setStyleName(css().previousButton());
+
+ forwards = new PushButton();
+ forwards.getUpFace().setHTML("»");
+ forwards.setStyleName(css().nextButton());
+ forwards.addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ addMonths(+1);
+ }
+ });
+
+ // Set up grid.
+ grid = new Grid(1, 3);
+ grid.setWidget(0, 0, backwards);
+ grid.setWidget(0, 2, forwards);
+
+ CellFormatter formatter = grid.getCellFormatter();
+ formatter.setStyleName(0, 1, css().month());
+ formatter.setWidth(0, 0, "1");
+ formatter.setWidth(0, 1, "100%");
+ formatter.setWidth(0, 2, "1");
+ grid.setStyleName(css().monthSelector());
+ initWidget(grid);
+ }
+
+}
diff --git a/user/src/com/google/gwt/user/datepicker/client/ElementMapper.java b/user/src/com/google/gwt/user/datepicker/client/ElementMapper.java
new file mode 100644
index 0000000..a495ee1
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/ElementMapper.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.UIObject;
+
+import java.util.ArrayList;
+
+/**
+ * Creates a mapping from elements to their associated ui objects.
+ *
+ * @param <T> the type that the element is mapped to
+ */
+class ElementMapper<T extends UIObject> {
+
+ private static class FreeNode {
+ int index;
+ ElementMapper.FreeNode next;
+
+ public FreeNode(int index, ElementMapper.FreeNode next) {
+ this.index = index;
+ this.next = next;
+ }
+ }
+
+ private static native void clearIndex(Element elem) /*-{
+ elem["__uiObjectID"] = null;
+ }-*/;
+
+ private static native int getIndex(Element elem) /*-{
+ var index = elem["__uiObjectID"];
+ return (index == null) ? -1 : index;
+ }-*/;
+
+ private static native void setIndex(Element elem, int index) /*-{
+ elem["__uiObjectID"] = index;
+ }-*/;
+
+ private ElementMapper.FreeNode freeList = null;
+
+ private final ArrayList<T> uiObjectList = new ArrayList<T>();
+
+ /**
+ * Returns the uiObject associated with the given element.
+ *
+ * @param elem uiObject's element
+ * @return the uiObject
+ */
+ public T get(Element elem) {
+ int index = getIndex(elem);
+ if (index < 0) {
+ return null;
+ }
+ return uiObjectList.get(index);
+ }
+
+ /**
+ * Adds the MappedType.
+ *
+ * @param uiObject uiObject to add
+ */
+ public void put(T uiObject) {
+ int index;
+ if (freeList == null) {
+ index = uiObjectList.size();
+ uiObjectList.add(uiObject);
+ } else {
+ index = freeList.index;
+ uiObjectList.set(index, uiObject);
+ freeList = freeList.next;
+ }
+ setIndex(uiObject.getElement(), index);
+ }
+
+ /**
+ * Remove the uiObject associated with the given element.
+ *
+ * @param elem the uiObject's element
+ */
+ public void removeByElement(Element elem) {
+ int index = getIndex(elem);
+ removeImpl(elem, index);
+ }
+
+ private void removeImpl(Element elem, int index) {
+ clearIndex(elem);
+ uiObjectList.set(index, null);
+ freeList = new FreeNode(index, freeList);
+ }
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/datepicker/client/MonthSelector.java b/user/src/com/google/gwt/user/datepicker/client/MonthSelector.java
new file mode 100644
index 0000000..25e3dc7
--- /dev/null
+++ b/user/src/com/google/gwt/user/datepicker/client/MonthSelector.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+/**
+ * Abstract month selector widget.
+ */
+public abstract class MonthSelector extends DatePickerComponent {
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
index c109008..0cbeb4e 100644
--- a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
+++ b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
@@ -1083,3 +1083,83 @@
.gwt-Tree .gwt-TreeItem-selected {
background: #93c2f1 url(images/hborder.png) repeat-x 0px -1463px;
}
+
+.gwt-DateBox input {
+ width: 8em;
+}
+.dateBoxPopup {
+}
+
+.gwt-DatePicker {
+ border: 1px solid #888;
+ cursor: default;
+}
+.gwt-DatePicker td,
+.datePickerMonthSelector td:focus {
+ outline: none
+}
+.datePickerDays {
+ width: 100%;
+ background: white;
+}
+.datePickerDay,
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ font-size: 75%;
+ text-align: center;
+ padding: 4px;
+ outline: none;
+}
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ background: #c1c1c1;
+ padding: 0px 4px 2px;
+ cursor: default;
+}
+.datePickerDay {
+ padding: 4px;
+ cursor: hand;
+ cursor: pointer;
+}
+.datePickerDayIsToday {
+ border: 1px solid black;
+ padding: 3px;
+}
+.datePickerDayIsWeekend {
+ background: #EEEEEE;
+}
+.datePickerDayIsFiller {
+ color: #888888;
+}
+.datePickerDayIsValue {
+ background: #abf;
+}
+.datePickerDayIsDisabled {
+ color: #AAAAAA;
+ font-style: italic;
+}
+.datePickerDayIsHighlighted {
+ background: #dde;
+}
+.datePickerDayIsValueAndHighlighted {
+ background: #ccf;
+}
+.datePickerMonthSelector {
+ background: #c1c1c1;
+ width: 100%;
+}
+td.datePickerMonth {
+ text-align: center;
+ vertical-align: center;
+ white-space: nowrap;
+ font-size: 70%;
+ font-weight: bold;
+}
+.datePickerPreviousButton,
+.datePickerNextButton {
+ font-size: 120%;
+ line-height: 1em;
+ cursor: hand;
+ cursor: pointer;
+ padding: 0px 4px;
+}
diff --git a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
index 3e46467..c4c3746 100644
--- a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
+++ b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
@@ -1083,3 +1083,83 @@
.gwt-Tree .gwt-TreeItem-selected {
background: #93c2f1 url(images/hborder.png) repeat-x 0px -1463px;
}
+
+.gwt-DateBox input {
+ width: 8em;
+}
+.dateBoxPopup {
+}
+
+.gwt-DatePicker {
+ border: 1px solid #888;
+ cursor: default;
+}
+.gwt-DatePicker td,
+.datePickerMonthSelector td:focus {
+ outline: none
+}
+.datePickerDays {
+ width: 100%;
+ background: white;
+}
+.datePickerDay,
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ font-size: 75%;
+ text-align: center;
+ padding: 4px;
+ outline: none;
+}
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ background: #c1c1c1;
+ padding: 0px 4px 2px;
+ cursor: default;
+}
+.datePickerDay {
+ padding: 4px;
+ cursor: hand;
+ cursor: pointer;
+}
+.datePickerDayIsToday {
+ border: 1px solid black;
+ padding: 3px;
+}
+.datePickerDayIsWeekend {
+ background: #EEEEEE;
+}
+.datePickerDayIsFiller {
+ color: #888888;
+}
+.datePickerDayIsValue {
+ background: #abf;
+}
+.datePickerDayIsDisabled {
+ color: #AAAAAA;
+ font-style: italic;
+}
+.datePickerDayIsHighlighted {
+ background: #dde;
+}
+.datePickerDayIsValueAndHighlighted {
+ background: #ccf;
+}
+.datePickerMonthSelector {
+ background: #c1c1c1;
+ width: 100%;
+}
+td.datePickerMonth {
+ text-align: center;
+ vertical-align: center;
+ white-space: nowrap;
+ font-size: 70%;
+ font-weight: bold;
+}
+.datePickerPreviousButton,
+.datePickerNextButton {
+ font-size: 120%;
+ line-height: 1em;
+ cursor: hand;
+ cursor: pointer;
+ padding: 0px 4px;
+}
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
index 8e38b61..37ab4c6 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
@@ -17,7 +17,7 @@
body, table td, select {
font-family: Arial Unicode MS, Arial, sans-serif;
font-size: small;
- color: #bec7cc;
+ color: #bec7cc
}
select {
color: #000;
@@ -988,3 +988,89 @@
color: #0cf;
background: #1c1c1c;
}
+
+.gwt-DateBox input {
+ width: 8em;
+}
+.dateBoxPopup {
+}
+
+.gwt-DatePicker {
+ border: 1px solid #00CCFF;
+ cursor: default;
+}
+.gwt-DatePicker td,
+.datePickerMonthSelector td:focus {
+ outline: none
+}
+.datePickerDays {
+ width: 100%;
+ background: #4d4d4d;
+}
+.datePickerDay,
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ font-size: 75%;
+ text-align: center;
+ padding: 4px;
+ outline: none;
+ color: #dddddd;
+}
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ background: #222222;
+ padding: 0px 4px 2px;
+ cursor: default;
+}
+.datePickerDay {
+ padding: 4px;
+ cursor: hand;
+ cursor: pointer;
+}
+.datePickerDayIsToday {
+ border: 1px solid #00CCFF;
+ padding: 3px;
+}
+.datePickerDayIsWeekend {
+ background: #333333;
+}
+.datePickerDayIsFiller {
+ color: #959595;
+}
+.datePickerDayIsValue {
+ background: #1C1C1C;
+ color: #00CCFF;
+}
+.datePickerDayIsDisabled {
+ color: #AAAAAA;
+ font-style: italic;
+}
+.datePickerDayIsHighlighted {
+ background: #00CCFF;
+ color: #1C1C1C;
+}
+.datePickerDayIsValueAndHighlighted {
+ background: #1C1C77;
+ color: #00CCFF;
+}
+.datePickerMonthSelector {
+ background: #222222;
+ width: 100%;
+}
+td.datePickerMonth {
+ text-align: center;
+ vertical-align: center;
+ white-space: nowrap;
+ font-size: 70%;
+ font-weight: bold;
+ color: #dddddd;
+}
+.datePickerPreviousButton,
+.datePickerNextButton {
+ font-size: 120%;
+ line-height: 1em;
+ cursor: hand;
+ cursor: pointer;
+ padding: 0px 4px;
+ color: #dddddd;
+}
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
index 4c27422..6de5961 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
@@ -988,3 +988,89 @@
color: #0cf;
background: #1c1c1c;
}
+
+.gwt-DateBox input {
+ width: 8em;
+}
+.dateBoxPopup {
+}
+
+.gwt-DatePicker {
+ border: 1px solid #00CCFF;
+ cursor: default;
+}
+.gwt-DatePicker td,
+.datePickerMonthSelector td:focus {
+ outline: none
+}
+.datePickerDays {
+ width: 100%;
+ background: #4d4d4d;
+}
+.datePickerDay,
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ font-size: 75%;
+ text-align: center;
+ padding: 4px;
+ outline: none;
+ color: #dddddd;
+}
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ background: #222222;
+ padding: 0px 4px 2px;
+ cursor: default;
+}
+.datePickerDay {
+ padding: 4px;
+ cursor: hand;
+ cursor: pointer;
+}
+.datePickerDayIsToday {
+ border: 1px solid #00CCFF;
+ padding: 3px;
+}
+.datePickerDayIsWeekend {
+ background: #333333;
+}
+.datePickerDayIsFiller {
+ color: #959595;
+}
+.datePickerDayIsValue {
+ background: #1C1C1C;
+ color: #00CCFF;
+}
+.datePickerDayIsDisabled {
+ color: #AAAAAA;
+ font-style: italic;
+}
+.datePickerDayIsHighlighted {
+ background: #00CCFF;
+ color: #1C1C1C;
+}
+.datePickerDayIsValueAndHighlighted {
+ background: #1C1C77;
+ color: #00CCFF;
+}
+.datePickerMonthSelector {
+ background: #222222;
+ width: 100%;
+}
+td.datePickerMonth {
+ text-align: center;
+ vertical-align: center;
+ white-space: nowrap;
+ font-size: 70%;
+ font-weight: bold;
+ color: #dddddd;
+}
+.datePickerPreviousButton,
+.datePickerNextButton {
+ font-size: 120%;
+ line-height: 1em;
+ cursor: hand;
+ cursor: pointer;
+ padding: 0px 4px;
+ color: #dddddd;
+}
diff --git a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
index aecc9f8..76fb73a 100644
--- a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
+++ b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
@@ -1082,3 +1082,85 @@
.gwt-Tree .gwt-TreeItem-selected {
background: #93c2f1 url(images/hborder.png) repeat-x 0px -1463px;
}
+
+.gwt-DateBox input {
+ width: 8em;
+}
+.dateBoxPopup {
+}
+
+.gwt-DatePicker {
+ border: 1px solid #A2BBDD;
+ cursor: default;
+}
+.gwt-DatePicker td,
+.datePickerMonthSelector td:focus {
+ outline: none
+}
+.datePickerDays {
+ width: 100%;
+ background: white;
+}
+.datePickerDay,
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ font-size: 75%;
+ text-align: center;
+ padding: 4px;
+ outline: none;
+}
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ background: #C3D9FF;
+ padding: 0px 4px 2px;
+ cursor: default;
+}
+.datePickerDay {
+ padding: 4px;
+ cursor: hand;
+ cursor: pointer;
+}
+.datePickerDayIsToday {
+ border: 1px solid black;
+ padding: 3px;
+}
+.datePickerDayIsWeekend {
+ background: #EEEEEE;
+}
+.datePickerDayIsFiller {
+ color: #888888;
+}
+.datePickerDayIsValue {
+ background: #aaccee;
+}
+.datePickerDayIsDisabled {
+ color: #AAAAAA;
+ font-style: italic;
+}
+.datePickerDayIsHighlighted {
+ background: #F0E68C;
+}
+.datePickerDayIsValueAndHighlighted {
+ background: #bbddd9;
+}
+.datePickerMonthSelector {
+ background: #C3D9FF;
+ width: 100%;
+}
+td.datePickerMonth {
+ text-align: center;
+ vertical-align: center;
+ white-space: nowrap;
+ font-size: 70%;
+ font-weight: bold;
+ color: blue;
+}
+.datePickerPreviousButton,
+.datePickerNextButton {
+ font-size: 120%;
+ line-height: 1em;
+ color: blue;
+ cursor: hand;
+ cursor: pointer;
+ padding: 0px 4px;
+}
diff --git a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
index 6cecc14..916ea1f 100644
--- a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
+++ b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
@@ -1082,3 +1082,85 @@
.gwt-Tree .gwt-TreeItem-selected {
background: #93c2f1 url(images/hborder.png) repeat-x 0px -1463px;
}
+
+.gwt-DateBox input {
+ width: 8em;
+}
+.dateBoxPopup {
+}
+
+.gwt-DatePicker {
+ border: 1px solid #A2BBDD;
+ cursor: default;
+}
+.gwt-DatePicker td,
+.datePickerMonthSelector td:focus {
+ outline: none
+}
+.datePickerDays {
+ width: 100%;
+ background: white;
+}
+.datePickerDay,
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ font-size: 75%;
+ text-align: center;
+ padding: 4px;
+ outline: none;
+}
+.datePickerWeekdayLabel,
+.datePickerWeekendLabel {
+ background: #C3D9FF;
+ padding: 0px 4px 2px;
+ cursor: default;
+}
+.datePickerDay {
+ padding: 4px;
+ cursor: hand;
+ cursor: pointer;
+}
+.datePickerDayIsToday {
+ border: 1px solid black;
+ padding: 3px;
+}
+.datePickerDayIsWeekend {
+ background: #EEEEEE;
+}
+.datePickerDayIsFiller {
+ color: #888888;
+}
+.datePickerDayIsValue {
+ background: #aaccee;
+}
+.datePickerDayIsDisabled {
+ color: #AAAAAA;
+ font-style: italic;
+}
+.datePickerDayIsHighlighted {
+ background: #F0E68C;
+}
+.datePickerDayIsValueAndHighlighted {
+ background: #bbddd9;
+}
+.datePickerMonthSelector {
+ background: #C3D9FF;
+ width: 100%;
+}
+td.datePickerMonth {
+ text-align: center;
+ vertical-align: center;
+ white-space: nowrap;
+ font-size: 70%;
+ font-weight: bold;
+ color: blue;
+}
+.datePickerPreviousButton,
+.datePickerNextButton {
+ font-size: 120%;
+ line-height: 1em;
+ color: blue;
+ cursor: hand;
+ cursor: pointer;
+ padding: 0px 4px;
+}
diff --git a/user/test/com/google/gwt/event/logical/shared/LogicalEventsTest.java b/user/test/com/google/gwt/event/logical/shared/LogicalEventsTest.java
index 985c79a..dc03d2a 100644
--- a/user/test/com/google/gwt/event/logical/shared/LogicalEventsTest.java
+++ b/user/test/com/google/gwt/event/logical/shared/LogicalEventsTest.java
@@ -67,7 +67,7 @@
simpleFire(BeforeSelectionEvent.getType(),
new BeforeSelectionEvent<String>());
simpleFire(SelectionEvent.getType(), new SelectionEvent<String>(null));
- simpleFire(CloseEvent.getType(), new CloseEvent<String>(null,false));
+ simpleFire(CloseEvent.getType(), new CloseEvent<String>(null, false));
simpleFire(OpenEvent.getType(), new OpenEvent<String>(null));
simpleFire(ResizeEvent.getType(), new ResizeEvent(0, 0));
simpleFire(ValueChangeEvent.getType(), new ValueChangeEvent<String>(null));
diff --git a/user/test/com/google/gwt/user/UISuite.java b/user/test/com/google/gwt/user/UISuite.java
index 1f06f51..56d1d5b 100644
--- a/user/test/com/google/gwt/user/UISuite.java
+++ b/user/test/com/google/gwt/user/UISuite.java
@@ -26,12 +26,15 @@
import com.google.gwt.user.client.ui.CompositeTest;
import com.google.gwt.user.client.ui.CustomButtonTest;
import com.google.gwt.user.client.ui.DOMTest;
+import com.google.gwt.user.client.ui.DateBoxTest;
+import com.google.gwt.user.client.ui.DatePickerTest;
import com.google.gwt.user.client.ui.DeckPanelTest;
import com.google.gwt.user.client.ui.DecoratedPopupTest;
import com.google.gwt.user.client.ui.DecoratedStackPanelTest;
import com.google.gwt.user.client.ui.DecoratedTabBarTest;
import com.google.gwt.user.client.ui.DecoratedTabPanelTest;
import com.google.gwt.user.client.ui.DecoratorPanelTest;
+import com.google.gwt.user.client.ui.DelegatingKeyboardListenerCollectionTest;
import com.google.gwt.user.client.ui.DialogBoxTest;
import com.google.gwt.user.client.ui.DisclosurePanelTest;
import com.google.gwt.user.client.ui.DockPanelTest;
@@ -73,6 +76,7 @@
import com.google.gwt.user.client.ui.WidgetOnLoadTest;
import com.google.gwt.user.client.ui.WidgetSubclassingTest;
import com.google.gwt.user.client.ui.impl.ClippedImagePrototypeTest;
+import com.google.gwt.user.datepicker.client.DateChangeEventTest;
import com.google.gwt.user.rebind.ui.ImageBundleGeneratorTest;
import com.google.gwt.xml.client.XMLTest;
@@ -83,8 +87,7 @@
*/
public class UISuite {
public static Test suite() {
- GWTTestSuite suite = new GWTTestSuite(
- "Test for suite for the com.google.gwt.ui module");
+ GWTTestSuite suite = new GWTTestSuite("Test for suite for all user widgets");
suite.addTestSuite(AbsolutePanelTest.class);
suite.addTestSuite(AnchorTest.class);
@@ -95,14 +98,15 @@
suite.addTestSuite(CompositeTest.class);
suite.addTestSuite(CookieTest.class);
suite.addTestSuite(CustomButtonTest.class);
+ suite.addTestSuite(DateBoxTest.class);
+ suite.addTestSuite(DatePickerTest.class);
suite.addTestSuite(DeckPanelTest.class);
suite.addTestSuite(DecoratedPopupTest.class);
suite.addTestSuite(DecoratedStackPanelTest.class);
suite.addTestSuite(DecoratedTabBarTest.class);
suite.addTestSuite(DecoratedTabPanelTest.class);
suite.addTestSuite(DecoratorPanelTest.class);
- // TEMP
- // suite.addTestSuite(DelegatingKeyboardListenerCollectionTest.class);
+ suite.addTestSuite(DelegatingKeyboardListenerCollectionTest.class);
suite.addTestSuite(DialogBoxTest.class);
suite.addTestSuite(DisclosurePanelTest.class);
suite.addTestSuite(DockPanelTest.class);
@@ -149,7 +153,7 @@
suite.addTestSuite(WindowTest.class);
suite.addTestSuite(XMLTest.class);
suite.addTestSuite(ClassInitTest.class);
-
+ suite.addTestSuite(DateChangeEventTest.class);
return suite;
}
}
diff --git a/user/test/com/google/gwt/user/client/ui/DateBoxTest.java b/user/test/com/google/gwt/user/client/ui/DateBoxTest.java
new file mode 100644
index 0000000..624359a
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/ui/DateBoxTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.client.ui;
+
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.datepicker.client.DateBox;
+
+/**
+ * Tests DateBox.
+ */
+public class DateBoxTest extends GWTTestCase {
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ public void testValueChangeEvent() {
+ DateBox db = new DateBox();
+ RootPanel.get().add(db);
+ new DateValueChangeTester(db).run();
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/ui/DatePickerTest.java b/user/test/com/google/gwt/user/client/ui/DatePickerTest.java
new file mode 100644
index 0000000..cafac56
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/ui/DatePickerTest.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.client.ui;
+
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.datepicker.client.CalendarModel;
+import com.google.gwt.user.datepicker.client.CalendarView;
+import com.google.gwt.user.datepicker.client.DatePicker;
+import com.google.gwt.user.datepicker.client.DefaultMonthSelector;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tests DatePicker's public api.
+ */
+@SuppressWarnings("deprecation")
+// Due to Date
+public class DatePickerTest extends GWTTestCase {
+
+ private static class DatePickerWithView extends DatePicker {
+ DatePickerWithView(MockCalendarView view) {
+ super(new DefaultMonthSelector(), view, new CalendarModel());
+ }
+ }
+ /**
+ * Mock calendar view pretends to show datesVisibleList from the first of the month to
+ * the 30th day after that.
+ */
+ private static class MockCalendarView extends CalendarView {
+ Map<Date, Set<String>> dateStyles = new HashMap<Date, Set<String>>();
+ Set<Date> disabledDates = new HashSet<Date>();
+
+ MockCalendarView() {
+ initWidget(new Label());
+ }
+
+ @Override
+ public void addStyleToDate(String styleName, Date date) {
+ Set<String> fred = dateStyles.get(date);
+ if (fred == null) {
+ fred = new HashSet<String>();
+ dateStyles.put(date, fred);
+ }
+ fred.add(styleName);
+ }
+
+ @Override
+ public Date getFirstDate() {
+ Date thisMonth = getModel().getCurrentMonth();
+ return new Date(thisMonth.getYear(), thisMonth.getMonth(), 1);
+ }
+
+ @Override
+ public Date getLastDate() {
+ Date thisMonth = getModel().getCurrentMonth();
+ return new Date(thisMonth.getYear(), thisMonth.getMonth(), 30);
+ }
+
+ @Override
+ public boolean isDateEnabled(Date date) {
+ return !disabledDates.contains(date);
+ }
+
+ @Override
+ public void refresh() {
+ }
+
+ @Override
+ public void removeStyleFromDate(String styleName, Date date) {
+ Set<String> fred;
+ assertNotNull(fred = dateStyles.get(date));
+ assertTrue(fred.remove(styleName));
+ }
+
+ @Override
+ public void setEnabledOnDate(boolean enabled, Date date) {
+ if (enabled) {
+ disabledDates.remove(date);
+ } else {
+ disabledDates.add(date);
+ }
+ }
+
+ @Override
+ protected void setup() {
+ }
+ }
+
+ private static final String STYLE_LATER = "styleLater";
+
+ private static final String STYLE = "style1";
+
+ private DatePickerWithView mockedDatePicker;
+ private MockCalendarView view;
+
+ private final Date dateVisible1 = new Date(65, 6, 12);
+ private final Date dateVisible2 = new Date(65, 6, 13);
+ private final Date dateVisible3 = new Date(65, 6, 14);
+ private final Date dateVisible4 = new Date(65, 6, 15);
+ private final Date dateVisible5 = new Date(65, 6, 16);
+ private final List<Date> datesVisibleList = new ArrayList<Date>();
+ private final Date dateLater1 =
+ new Date(dateVisible1.getYear(), dateVisible1.getMonth() + 1,
+ dateVisible1.getDay());
+
+ private final Date dateLater2 =
+ new Date(dateVisible2.getYear(), dateVisible2.getMonth() + 1,
+ dateVisible2.getDay());
+ private final Date dateLater3 =
+ new Date(dateVisible1.getYear(), dateVisible3.getMonth() + 1,
+ dateVisible3.getDay());
+ private final Date dateLater4 =
+ new Date(dateVisible2.getYear(), dateVisible4.getMonth() + 1,
+ dateVisible4.getDay());
+ private final Date dateLater5 =
+ new Date(dateVisible1.getYear(), dateVisible5.getMonth() + 1,
+ dateVisible5.getDay());
+ private final List<Date> datesLaterList = new ArrayList<Date>();
+ {
+ datesVisibleList.add(dateVisible4);
+ datesVisibleList.add(dateVisible5);
+ }
+ {
+ datesLaterList.add(dateLater4);
+ datesLaterList.add(dateLater5);
+ }
+
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ @Override
+ public void gwtSetUp() throws Exception {
+ super.gwtSetUp();
+
+ view = new MockCalendarView();
+ mockedDatePicker = new DatePickerWithView(view);
+ mockedDatePicker.setCurrentMonth(dateVisible1);
+ }
+
+ public void testDisabling() {
+ mockedDatePicker.setTransientEnabledOnDates(false, dateVisible1);
+ mockedDatePicker.setTransientEnabledOnDates(false, dateVisible2,
+ dateVisible3);
+ mockedDatePicker.setTransientEnabledOnDates(false, datesVisibleList);
+
+ assertTrue(view.disabledDates.contains(dateVisible1));
+ assertTrue(view.disabledDates.contains(dateVisible2));
+ assertTrue(view.disabledDates.contains(dateVisible3));
+ assertTrue(view.disabledDates.contains(dateVisible4));
+ assertTrue(view.disabledDates.contains(dateVisible5));
+
+ mockedDatePicker.setTransientEnabledOnDates(true, dateVisible1);
+ mockedDatePicker.setTransientEnabledOnDates(true, dateVisible2,
+ dateVisible3);
+ mockedDatePicker.setTransientEnabledOnDates(true, datesVisibleList);
+
+ assertFalse(view.disabledDates.contains(dateVisible1));
+ assertFalse(view.disabledDates.contains(dateVisible2));
+ assertFalse(view.disabledDates.contains(dateVisible3));
+ assertFalse(view.disabledDates.contains(dateVisible4));
+ assertFalse(view.disabledDates.contains(dateVisible5));
+ }
+
+ public void testStyleSetting() {
+ mockedDatePicker.addStyleToDates(STYLE, dateVisible1);
+ mockedDatePicker.addStyleToDates(STYLE, dateVisible2, dateVisible3);
+ mockedDatePicker.addStyleToDates(STYLE, datesVisibleList);
+
+ assertViewHasStyleOnVisibleDates(STYLE);
+ assertPickerHasStyleOnVisibleDates(STYLE);
+
+ // See that styles on an invisible datesVisibleList don't
+
+ mockedDatePicker.addStyleToDates(STYLE_LATER, dateLater1);
+ mockedDatePicker.addStyleToDates(STYLE_LATER, dateLater2, dateLater3);
+ mockedDatePicker.addStyleToDates(STYLE_LATER, datesLaterList);
+
+ assertViewHasNoStyleOnHiddenDates();
+ assertPickerLacksStyleOnHiddenDates(STYLE_LATER);
+
+ // Remove a style from a visible date, and it should leave the view too
+ mockedDatePicker.removeStyleFromDates(STYLE, dateVisible1);
+ mockedDatePicker.removeStyleFromDates(STYLE, dateVisible2, dateVisible3);
+ mockedDatePicker.removeStyleFromDates(STYLE, datesVisibleList);
+
+ assertViewLacksStyleOnVisibleDates(STYLE);
+ assertPickerLacksStyleOnVisibleDates();
+
+ // Remove a style from an invisible date, and the view should not hear
+ // about it (the mock will explode if asked to remove a style it doesn't
+ // have)
+ mockedDatePicker.removeStyleFromDates(STYLE_LATER, dateLater1);
+ mockedDatePicker.removeStyleFromDates(STYLE_LATER, dateLater2, dateLater3);
+ mockedDatePicker.removeStyleFromDates(STYLE_LATER, datesLaterList);
+ assertPickerHasNoStyleOnInvisibleDates();
+ }
+
+ public void testTransientStyles() {
+ mockedDatePicker.addTransientStyleToDates(STYLE, dateVisible1);
+ mockedDatePicker.addTransientStyleToDates(STYLE, dateVisible2,
+ dateVisible3);
+ mockedDatePicker.addTransientStyleToDates(STYLE, datesVisibleList);
+ assertViewHasStyleOnVisibleDates(STYLE);
+ assertPickerLacksStyleOnVisibleDates();
+
+ mockedDatePicker.removeStyleFromDates(STYLE, dateVisible1);
+ mockedDatePicker.removeStyleFromDates(STYLE, dateVisible2, dateVisible3);
+ mockedDatePicker.removeStyleFromDates(STYLE, datesVisibleList);
+ assertViewLacksStyleOnVisibleDates(STYLE);
+ assertPickerLacksStyleOnVisibleDates();
+ }
+
+ public void testValueChangeEvent() {
+ DatePicker dp = new DatePicker();
+ RootPanel.get().add(dp);
+ new DateValueChangeTester(dp).run();
+ }
+
+ public void testValueStyle() {
+ assertNull(mockedDatePicker.getStyleOfDate(dateVisible4));
+
+ mockedDatePicker.setValue(dateVisible4);
+ assertTrue(mockedDatePicker.getStyleOfDate(dateVisible4).contains("datePickerDayIsValue"));
+ assertTrue(view.dateStyles.get(dateVisible4).contains("datePickerDayIsValue"));
+
+ mockedDatePicker.setValue(dateVisible5);
+ assertNull(mockedDatePicker.getStyleOfDate(dateVisible4));
+ assertFalse(view.dateStyles.get(dateVisible4).contains("datePickerDayIsValue"));
+ }
+
+ private void assertPickerHasNoStyleOnInvisibleDates() {
+ assertNull(mockedDatePicker.getStyleOfDate(dateLater1));
+ assertNull(mockedDatePicker.getStyleOfDate(dateLater2));
+ assertNull(mockedDatePicker.getStyleOfDate(dateLater3));
+ assertNull(mockedDatePicker.getStyleOfDate(dateLater4));
+ assertNull(mockedDatePicker.getStyleOfDate(dateLater5));
+ }
+
+ private void assertPickerHasStyleOnVisibleDates(String style) {
+ assertTrue(mockedDatePicker.getStyleOfDate(dateVisible1).contains(
+ style));
+ assertTrue(mockedDatePicker.getStyleOfDate(dateVisible2).contains(
+ style));
+ assertTrue(mockedDatePicker.getStyleOfDate(dateVisible3).contains(
+ style));
+ assertTrue(mockedDatePicker.getStyleOfDate(dateVisible4).contains(
+ style));
+ assertTrue(mockedDatePicker.getStyleOfDate(dateVisible5).contains(
+ style));
+ }
+
+ private void assertPickerLacksStyleOnHiddenDates(String styleLater) {
+ assertTrue(mockedDatePicker.getStyleOfDate(dateLater1).contains(
+ styleLater));
+ assertTrue(mockedDatePicker.getStyleOfDate(dateLater2).contains(
+ styleLater));
+ assertTrue(mockedDatePicker.getStyleOfDate(dateLater3).contains(
+ styleLater));
+ assertTrue(mockedDatePicker.getStyleOfDate(dateLater4).contains(
+ styleLater));
+ assertTrue(mockedDatePicker.getStyleOfDate(dateLater5).contains(
+ styleLater));
+ }
+
+ private void assertPickerLacksStyleOnVisibleDates() {
+ assertNull(mockedDatePicker.getStyleOfDate(dateVisible1));
+ assertNull(mockedDatePicker.getStyleOfDate(dateVisible2));
+ assertNull(mockedDatePicker.getStyleOfDate(dateVisible3));
+ assertNull(mockedDatePicker.getStyleOfDate(dateVisible4));
+ assertNull(mockedDatePicker.getStyleOfDate(dateVisible5));
+ }
+
+ private void assertViewHasNoStyleOnHiddenDates() {
+ assertNull(view.dateStyles.get(dateLater1));
+ assertNull(view.dateStyles.get(dateLater2));
+ assertNull(view.dateStyles.get(dateLater3));
+ assertNull(view.dateStyles.get(dateLater4));
+ assertNull(view.dateStyles.get(dateLater5));
+ }
+
+ private void assertViewHasStyleOnVisibleDates(String style) {
+ assertTrue(view.dateStyles.get(dateVisible1).contains(style));
+ assertTrue(view.dateStyles.get(dateVisible2).contains(style));
+ assertTrue(view.dateStyles.get(dateVisible3).contains(style));
+ assertTrue(view.dateStyles.get(dateVisible4).contains(style));
+ assertTrue(view.dateStyles.get(dateVisible5).contains(style));
+ }
+
+ private void assertViewLacksStyleOnVisibleDates(String style) {
+ assertFalse(view.dateStyles.get(dateVisible1).contains(style));
+ assertFalse(view.dateStyles.get(dateVisible2).contains(style));
+ assertFalse(view.dateStyles.get(dateVisible3).contains(style));
+ assertFalse(view.dateStyles.get(dateVisible4).contains(style));
+ assertFalse(view.dateStyles.get(dateVisible5).contains(style));
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/ui/DateValueChangeTester.java b/user/test/com/google/gwt/user/client/ui/DateValueChangeTester.java
new file mode 100644
index 0000000..0e9636f
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/ui/DateValueChangeTester.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.client.ui;
+
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+
+import junit.framework.TestCase;
+
+import java.util.Date;
+
+/**
+ * Handy tool for testing classes that implement {@link HasValue<Date>}.
+ */
+public class DateValueChangeTester {
+ static class Handler implements ValueChangeHandler<Date> {
+ Date received = null;
+
+ public void onValueChange(ValueChangeEvent<Date> event) {
+ received = event.getValue();
+ }
+ }
+
+ private final HasValue<Date> subject;
+
+ /**
+ * The HasValue<Date> to be tested. It should have been freshly created before
+ * handing it to this tester.
+ */
+ public DateValueChangeTester(HasValue<Date> subject) {
+ this.subject = subject;
+ }
+
+ /**
+ * Asserts that the default value is null, checks that value change events do
+ * and don't fire when appropriate, and that getValue() always returns what
+ * was handed to getValue().
+ */
+ @SuppressWarnings("deprecation")
+ public void run() {
+ TestCase.assertNull(subject.getValue());
+
+ DateValueChangeTester.Handler h = new Handler();
+ subject.addValueChangeHandler(h);
+
+ subject.setValue(null);
+ TestCase.assertNull(subject.getValue());
+ TestCase.assertNull(h.received);
+
+ Date able = new Date(1999, 5, 15);
+ subject.setValue(able);
+ TestCase.assertEquals(able, subject.getValue());
+ TestCase.assertNull(h.received);
+
+ subject.setValue(able);
+ TestCase.assertNull(h.received);
+
+ Date baker = new Date(1965, 12, 7);
+ subject.setValue(baker);
+ TestCase.assertNull(h.received);
+
+ // Value has not changed, so should not fire a change event even though
+ // fire event is true.
+ subject.setValue(baker, true);
+ TestCase.assertNull(h.received);
+
+ subject.setValue(able, true);
+ TestCase.assertEquals(able, h.received);
+ TestCase.assertNotSame(able, h.received);
+
+ subject.setValue(baker, true);
+ TestCase.assertEquals(baker, h.received);
+ TestCase.assertNotSame(baker, h.received);
+
+ h.received = null;
+ // Value has changed, but boolean is false.
+ subject.setValue(baker, false);
+ TestCase.assertNull(h.received);
+ }
+}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java b/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java
index bf47218..58aa3e2 100644
--- a/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java
+++ b/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java
@@ -98,22 +98,31 @@
public void testValueChangeEvent() {
TextBoxBase tb = createTextBoxBase();
-
// To work cross-platform, the tb must be added to the root panel.
RootPanel.get().add(tb);
+
Handler h = new Handler();
tb.addValueChangeHandler(h);
- tb.setText("able");
+
+ tb.setValue(null);
+ assertEquals("", tb.getValue());
assertNull(h.received);
- tb.setValue("able");
+ tb.setText("able");
+ assertEquals("able", tb.getValue());
assertNull(h.received);
+
+ tb.setValue("able");
+ assertEquals("able", tb.getValue());
+ assertNull(h.received);
+
tb.setValue("baker");
assertNull(h.received);
tb.setValue("baker", true);
+ assertEquals("baker", tb.getValue());
assertNull(h.received);
-
+
tb.setValue("able", true);
assertEquals("able", h.received);
diff --git a/user/test/com/google/gwt/user/datepicker/client/DateChangeEventTest.java b/user/test/com/google/gwt/user/datepicker/client/DateChangeEventTest.java
new file mode 100644
index 0000000..b8c5361
--- /dev/null
+++ b/user/test/com/google/gwt/user/datepicker/client/DateChangeEventTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * 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.google.gwt.user.datepicker.client;
+
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.ui.DateValueChangeTester;
+import com.google.gwt.user.client.ui.HasValue;
+
+import junit.framework.TestCase;
+
+import java.util.Date;
+
+/**
+ * Test the DateChangeEvent in isolation from GWT.
+ */
+public class DateChangeEventTest extends TestCase {
+
+ private class MockWidget implements HasValue<Date> {
+ private final HandlerManager handlers = new HandlerManager(this);
+ private Date value;
+
+ public HandlerRegistration addValueChangeHandler(
+ ValueChangeHandler<Date> handler) {
+ return handlers.addHandler(ValueChangeEvent.getType(), handler);
+ }
+
+ public HandlerManager getHandlers() {
+ return handlers;
+ }
+
+ public Date getValue() {
+ return value;
+ }
+
+ public void setValue(Date value) {
+ setValue(value, false);
+ }
+
+ public void setValue(Date value, boolean fireEvents) {
+ Date oldValue = this.value;
+ this.value = value;
+ if (fireEvents) {
+ DateChangeEvent.fireIfNotEqualDates(this, oldValue, value);
+ }
+ }
+ }
+
+ public void testValueChangeViaHasValue() {
+ new DateValueChangeTester(new MockWidget()).run();
+ }
+
+}