Setting svn props on some java files that don't have them.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1037 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/javadoc/com/google/gwt/examples/PushButtonExample.java b/user/javadoc/com/google/gwt/examples/PushButtonExample.java
index f08db62..1e85063 100644
--- a/user/javadoc/com/google/gwt/examples/PushButtonExample.java
+++ b/user/javadoc/com/google/gwt/examples/PushButtonExample.java
@@ -1,43 +1,43 @@
-/*
- * Copyright 2006 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.Window;
-import com.google.gwt.user.client.ui.ClickListener;
-import com.google.gwt.user.client.ui.PushButton;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-public class PushButtonExample implements EntryPoint {
-
- public void onModuleLoad() {
- // Make a new button that does something when you click it.
- PushButton b = new PushButton("Jump", "Jump?", new ClickListener() {
- public void onClick(Widget sender) {
- Window.alert("Crash...");
- Window.alert("Uh Oh...");
- }
- });
-
- // In a real application, you would have to have css styles defined for
- // gwt-PushButton-up,gwt-PushButton-up-hovering,gwt-PushButton-up-disabled,
- // gwt-PushButton-down,.gwt-PushButton-down-hovering,.gwt-PushButton-down-disabled
-
- // Add the push button to the root panel.
- RootPanel.get().add(b);
- }
+/*
+ * Copyright 2006 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.Window;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.PushButton;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+public class PushButtonExample implements EntryPoint {
+
+ public void onModuleLoad() {
+ // Make a new button that does something when you click it.
+ PushButton b = new PushButton("Jump", "Jump?", new ClickListener() {
+ public void onClick(Widget sender) {
+ Window.alert("Crash...");
+ Window.alert("Uh Oh...");
+ }
+ });
+
+ // In a real application, you would have to have css styles defined for
+ // gwt-PushButton-up,gwt-PushButton-up-hovering,gwt-PushButton-up-disabled,
+ // gwt-PushButton-down,.gwt-PushButton-down-hovering,.gwt-PushButton-down-disabled
+
+ // Add the push button to the root panel.
+ RootPanel.get().add(b);
+ }
}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/ToggleButtonExample.java b/user/javadoc/com/google/gwt/examples/ToggleButtonExample.java
index f6cb07e..5b119ea 100644
--- a/user/javadoc/com/google/gwt/examples/ToggleButtonExample.java
+++ b/user/javadoc/com/google/gwt/examples/ToggleButtonExample.java
@@ -1,46 +1,46 @@
-/*
- * Copyright 2006 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.Window;
-import com.google.gwt.user.client.ui.ClickListener;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.ToggleButton;
-import com.google.gwt.user.client.ui.Widget;
-
-public class ToggleButtonExample implements EntryPoint {
- public void onModuleLoad() {
- // Make a new button that does something when you click it.
- final ToggleButton toggleButton = new ToggleButton("Up", "Down");
- toggleButton.addClickListener(new ClickListener() {
- public void onClick(Widget sender) {
- if (toggleButton.isDown()) {
- Window.alert("I have been toggled down");
- } else {
- Window.alert("I have been toggled up");
- }
- }
- });
-
- // In a real application, you would have to have css styles defined for
- // gwt-ToggleButton-up,gwt-ToggleButton-up-hovering,gwt-ToggleButton-up-disabled,
- // gwt-ToggleButton-down,.gwt-ToggleButton-down-hovering,.gwt-ToggleButton-down-disabled
-
- // Add the ToggleButton to the root panel.
- RootPanel.get().add(toggleButton);
- }
+/*
+ * Copyright 2006 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.Window;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.ToggleButton;
+import com.google.gwt.user.client.ui.Widget;
+
+public class ToggleButtonExample implements EntryPoint {
+ public void onModuleLoad() {
+ // Make a new button that does something when you click it.
+ final ToggleButton toggleButton = new ToggleButton("Up", "Down");
+ toggleButton.addClickListener(new ClickListener() {
+ public void onClick(Widget sender) {
+ if (toggleButton.isDown()) {
+ Window.alert("I have been toggled down");
+ } else {
+ Window.alert("I have been toggled up");
+ }
+ }
+ });
+
+ // In a real application, you would have to have css styles defined for
+ // gwt-ToggleButton-up,gwt-ToggleButton-up-hovering,gwt-ToggleButton-up-disabled,
+ // gwt-ToggleButton-down,.gwt-ToggleButton-down-hovering,.gwt-ToggleButton-down-disabled
+
+ // Add the ToggleButton to the root panel.
+ RootPanel.get().add(toggleButton);
+ }
}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/i18n/client/DateRecord.java b/user/src/com/google/gwt/i18n/client/DateRecord.java
index 44253dd..6eecb1c 100644
--- a/user/src/com/google/gwt/i18n/client/DateRecord.java
+++ b/user/src/com/google/gwt/i18n/client/DateRecord.java
@@ -1,291 +1,291 @@
-/*
- * Copyright 2006 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.i18n.client;
-
-import java.util.Date;
-
-/**
- * DateRecord class exposes almost the same set of interface as Date class with
- * only a few exceptions. The main purpose is the record all the information
- * during parsing phase and resolve them in a later time when all information
- * can be processed together.
- */
-class DateRecord extends Date {
-
- /*
- * The serial version UID is only defined because this class is implicitly
- * serializable, causing warnings due to its absence. It will generally not be
- * used.
- */
- private static final long serialVersionUID = -1278816193740448162L;
-
- public static final int AM = 0;
- public static final int PM = 1;
-
- private static final int JS_START_YEAR = 1900;
-
- private int era;
- private int year;
- private int month;
- private int dayOfMonth;
- private int ampm;
- private int hours;
- private int minutes;
- private int seconds;
- private int milliseconds;
-
- private int tzOffset;
- private int dayOfWeek;
- private boolean ambiguousYear;
-
- /**
- * Initialize DateExt object with default value. Here we use -1 for most of
- * the field to indicate that field is not set.
- */
- public DateRecord() {
- era = -1;
- ambiguousYear = false;
- year = Integer.MIN_VALUE;
- month = -1;
- dayOfMonth = -1;
- ampm = -1;
- hours = -1;
- minutes = -1;
- seconds = -1;
- milliseconds = -1;
- dayOfWeek = -1;
- tzOffset = Integer.MIN_VALUE;
- };
-
- /**
- * calcDate uses all the field available so far to fill a Date object. For
- * those information that is not provided, the existing value in 'date' will
- * be kept. Ambiguouse year will be resolved after the date/time value are
- * resolved.
- *
- * @param date The Date object being filled. Its value should be set to a
- * accetable default before pass in to this method
- * @return true if sucessful, otherwise false.
- */
- public boolean calcDate(Date date) {
- // Year 0 is 1 BC, and so on.
- if (this.era == 0 && this.year > 0) {
- this.year = -(this.year - 1);
- }
-
- if (this.year > Integer.MIN_VALUE) {
- date.setYear(this.year - JS_START_YEAR);
- }
-
- // "setMonth" and "setDate" is a little bit tricky. Suppose content in
- // date is 11/30, switch month to 02 will lead to 03/02 since 02/30 does
- // not exist. And you certain won't like 02/12 turn out to be 03/12. So
- // here to set date to a smaller number before month, and later setMonth.
- // Real date is set after, and that might cause month switch. However,
- // that's desired.
- int orgDayOfMonth = date.getDate();
- date.setDate(1);
-
- if (this.month >= 0) {
- date.setMonth(this.month);
- }
-
- if (this.dayOfMonth >= 0) {
- date.setDate(this.dayOfMonth);
- } else {
- date.setDate(orgDayOfMonth);
- }
-
- // adjust ampm
- if (this.hours < 0) {
- this.hours = date.getHours();
- }
-
- if (this.ampm > 0) {
- if (this.hours < 12) {
- this.hours += 12;
- }
- }
- date.setHours(this.hours);
-
- if (this.minutes >= 0) {
- date.setMinutes(this.minutes);
- }
-
- if (this.seconds >= 0) {
- date.setSeconds(this.seconds);
- }
-
- if (this.milliseconds >= 0) {
- date.setTime(date.getTime() / 1000 * 1000 + this.milliseconds);
- }
-
- // Adjust time zone.
- if (this.tzOffset > Integer.MIN_VALUE) {
- int offset = date.getTimezoneOffset();
- date.setTime(date.getTime() + (this.tzOffset - offset) * 60 * 1000);
- // HBJ date.setTime(date.getTime() + this.tzOffset * 60 * 1000);
- }
-
- // Resolve ambiguous year if needed.
- if (this.ambiguousYear) { // the two-digit year == the default start year
- Date defaultCenturyStart = new Date();
- defaultCenturyStart.setYear(defaultCenturyStart.getYear() - 80);
- if (date.before(defaultCenturyStart)) {
- date.setYear(defaultCenturyStart.getYear() + 100);
- }
- }
-
- // Date is resolved to the nearest dayOfWeek if date is not explicitly
- // specified. There is one exception, if the nearest dayOfWeek falls
- // into a different month, the 2nd nearest dayOfWeek, which is on the
- // other direction, will be used.
- if (this.dayOfWeek >= 0) {
- if (this.dayOfMonth == -1) {
- // Adjust to the nearest day of the week.
- int adjustment = (7 + this.dayOfWeek - date.getDay()) % 7;
- if (adjustment > 3) {
- adjustment -= 7;
- }
- int orgMonth = date.getMonth();
- date.setDate(date.getDate() + adjustment);
-
- // If the nearest weekday fall into a different month, we will use the
- // 2nd nearest weekday, which will be on the other direction, and is
- // sure fall into the same month.
- if (date.getMonth() != orgMonth) {
- date.setDate(date.getDate() + (adjustment > 0 ? -7 : 7));
- }
- } else {
- if (date.getDay() != this.dayOfWeek) {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Set ambiguous year field. This flag indicates that a 2 digit years's
- * century need to be determined by its date/time value. This can only be
- * resolved after its date/time is known.
- *
- * @param ambiguousYear true if it is ambiguous year.
- */
- public void setAmbiguousYear(boolean ambiguousYear) {
- this.ambiguousYear = ambiguousYear;
- }
-
- /**
- * Set morning/afternoon field.
- *
- * @param ampm ampm value.
- */
- public void setAmpm(int ampm) {
- this.ampm = ampm;
- }
-
- /**
- * Set dayOfMonth field.
- *
- * @param day dayOfMonth value
- */
- public void setDayOfMonth(int day) {
- this.dayOfMonth = day;
- }
-
- /**
- * Set dayOfWeek field.
- *
- * @param dayOfWeek day of the week.
- */
- public void setDayOfWeek(int dayOfWeek) {
- this.dayOfWeek = dayOfWeek;
- }
-
- /**
- * Set Era field.
- *
- * @param era era value being set.
- */
- public void setEra(int era) {
- this.era = era;
- }
-
- /**
- * Set hour field.
- *
- * @param hours hour value.
- */
- public void setHours(int hours) {
- this.hours = hours;
- }
-
- /**
- * Set milliseconds field.
- *
- * @param milliseconds milliseconds value.
- */
- public void setMilliseconds(int milliseconds) {
- this.milliseconds = milliseconds;
- }
-
- /**
- * Set minute field.
- *
- * @param minutes minute value.
- */
- public void setMinutes(int minutes) {
- this.minutes = minutes;
- }
-
- /**
- * Set month field.
- *
- * @param month month value.
- */
- public void setMonth(int month) {
- this.month = month;
- }
-
- /**
- * Set seconds field.
- *
- * @param seconds second value.
- */
- public void setSeconds(int seconds) {
- this.seconds = seconds;
- }
-
- /**
- * Set timezone offset, in minutes.
- *
- * @param tzOffset timezone offset.
- */
- public void setTzOffset(int tzOffset) {
- this.tzOffset = tzOffset;
- }
-
- /**
- * Set year field.
- *
- * @param value year value.
- */
- public void setYear(int value) {
- this.year = value;
- }
-}
+/*
+ * Copyright 2006 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.i18n.client;
+
+import java.util.Date;
+
+/**
+ * DateRecord class exposes almost the same set of interface as Date class with
+ * only a few exceptions. The main purpose is the record all the information
+ * during parsing phase and resolve them in a later time when all information
+ * can be processed together.
+ */
+class DateRecord extends Date {
+
+ /*
+ * The serial version UID is only defined because this class is implicitly
+ * serializable, causing warnings due to its absence. It will generally not be
+ * used.
+ */
+ private static final long serialVersionUID = -1278816193740448162L;
+
+ public static final int AM = 0;
+ public static final int PM = 1;
+
+ private static final int JS_START_YEAR = 1900;
+
+ private int era;
+ private int year;
+ private int month;
+ private int dayOfMonth;
+ private int ampm;
+ private int hours;
+ private int minutes;
+ private int seconds;
+ private int milliseconds;
+
+ private int tzOffset;
+ private int dayOfWeek;
+ private boolean ambiguousYear;
+
+ /**
+ * Initialize DateExt object with default value. Here we use -1 for most of
+ * the field to indicate that field is not set.
+ */
+ public DateRecord() {
+ era = -1;
+ ambiguousYear = false;
+ year = Integer.MIN_VALUE;
+ month = -1;
+ dayOfMonth = -1;
+ ampm = -1;
+ hours = -1;
+ minutes = -1;
+ seconds = -1;
+ milliseconds = -1;
+ dayOfWeek = -1;
+ tzOffset = Integer.MIN_VALUE;
+ };
+
+ /**
+ * calcDate uses all the field available so far to fill a Date object. For
+ * those information that is not provided, the existing value in 'date' will
+ * be kept. Ambiguouse year will be resolved after the date/time value are
+ * resolved.
+ *
+ * @param date The Date object being filled. Its value should be set to a
+ * accetable default before pass in to this method
+ * @return true if sucessful, otherwise false.
+ */
+ public boolean calcDate(Date date) {
+ // Year 0 is 1 BC, and so on.
+ if (this.era == 0 && this.year > 0) {
+ this.year = -(this.year - 1);
+ }
+
+ if (this.year > Integer.MIN_VALUE) {
+ date.setYear(this.year - JS_START_YEAR);
+ }
+
+ // "setMonth" and "setDate" is a little bit tricky. Suppose content in
+ // date is 11/30, switch month to 02 will lead to 03/02 since 02/30 does
+ // not exist. And you certain won't like 02/12 turn out to be 03/12. So
+ // here to set date to a smaller number before month, and later setMonth.
+ // Real date is set after, and that might cause month switch. However,
+ // that's desired.
+ int orgDayOfMonth = date.getDate();
+ date.setDate(1);
+
+ if (this.month >= 0) {
+ date.setMonth(this.month);
+ }
+
+ if (this.dayOfMonth >= 0) {
+ date.setDate(this.dayOfMonth);
+ } else {
+ date.setDate(orgDayOfMonth);
+ }
+
+ // adjust ampm
+ if (this.hours < 0) {
+ this.hours = date.getHours();
+ }
+
+ if (this.ampm > 0) {
+ if (this.hours < 12) {
+ this.hours += 12;
+ }
+ }
+ date.setHours(this.hours);
+
+ if (this.minutes >= 0) {
+ date.setMinutes(this.minutes);
+ }
+
+ if (this.seconds >= 0) {
+ date.setSeconds(this.seconds);
+ }
+
+ if (this.milliseconds >= 0) {
+ date.setTime(date.getTime() / 1000 * 1000 + this.milliseconds);
+ }
+
+ // Adjust time zone.
+ if (this.tzOffset > Integer.MIN_VALUE) {
+ int offset = date.getTimezoneOffset();
+ date.setTime(date.getTime() + (this.tzOffset - offset) * 60 * 1000);
+ // HBJ date.setTime(date.getTime() + this.tzOffset * 60 * 1000);
+ }
+
+ // Resolve ambiguous year if needed.
+ if (this.ambiguousYear) { // the two-digit year == the default start year
+ Date defaultCenturyStart = new Date();
+ defaultCenturyStart.setYear(defaultCenturyStart.getYear() - 80);
+ if (date.before(defaultCenturyStart)) {
+ date.setYear(defaultCenturyStart.getYear() + 100);
+ }
+ }
+
+ // Date is resolved to the nearest dayOfWeek if date is not explicitly
+ // specified. There is one exception, if the nearest dayOfWeek falls
+ // into a different month, the 2nd nearest dayOfWeek, which is on the
+ // other direction, will be used.
+ if (this.dayOfWeek >= 0) {
+ if (this.dayOfMonth == -1) {
+ // Adjust to the nearest day of the week.
+ int adjustment = (7 + this.dayOfWeek - date.getDay()) % 7;
+ if (adjustment > 3) {
+ adjustment -= 7;
+ }
+ int orgMonth = date.getMonth();
+ date.setDate(date.getDate() + adjustment);
+
+ // If the nearest weekday fall into a different month, we will use the
+ // 2nd nearest weekday, which will be on the other direction, and is
+ // sure fall into the same month.
+ if (date.getMonth() != orgMonth) {
+ date.setDate(date.getDate() + (adjustment > 0 ? -7 : 7));
+ }
+ } else {
+ if (date.getDay() != this.dayOfWeek) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Set ambiguous year field. This flag indicates that a 2 digit years's
+ * century need to be determined by its date/time value. This can only be
+ * resolved after its date/time is known.
+ *
+ * @param ambiguousYear true if it is ambiguous year.
+ */
+ public void setAmbiguousYear(boolean ambiguousYear) {
+ this.ambiguousYear = ambiguousYear;
+ }
+
+ /**
+ * Set morning/afternoon field.
+ *
+ * @param ampm ampm value.
+ */
+ public void setAmpm(int ampm) {
+ this.ampm = ampm;
+ }
+
+ /**
+ * Set dayOfMonth field.
+ *
+ * @param day dayOfMonth value
+ */
+ public void setDayOfMonth(int day) {
+ this.dayOfMonth = day;
+ }
+
+ /**
+ * Set dayOfWeek field.
+ *
+ * @param dayOfWeek day of the week.
+ */
+ public void setDayOfWeek(int dayOfWeek) {
+ this.dayOfWeek = dayOfWeek;
+ }
+
+ /**
+ * Set Era field.
+ *
+ * @param era era value being set.
+ */
+ public void setEra(int era) {
+ this.era = era;
+ }
+
+ /**
+ * Set hour field.
+ *
+ * @param hours hour value.
+ */
+ public void setHours(int hours) {
+ this.hours = hours;
+ }
+
+ /**
+ * Set milliseconds field.
+ *
+ * @param milliseconds milliseconds value.
+ */
+ public void setMilliseconds(int milliseconds) {
+ this.milliseconds = milliseconds;
+ }
+
+ /**
+ * Set minute field.
+ *
+ * @param minutes minute value.
+ */
+ public void setMinutes(int minutes) {
+ this.minutes = minutes;
+ }
+
+ /**
+ * Set month field.
+ *
+ * @param month month value.
+ */
+ public void setMonth(int month) {
+ this.month = month;
+ }
+
+ /**
+ * Set seconds field.
+ *
+ * @param seconds second value.
+ */
+ public void setSeconds(int seconds) {
+ this.seconds = seconds;
+ }
+
+ /**
+ * Set timezone offset, in minutes.
+ *
+ * @param tzOffset timezone offset.
+ */
+ public void setTzOffset(int tzOffset) {
+ this.tzOffset = tzOffset;
+ }
+
+ /**
+ * Set year field.
+ *
+ * @param value year value.
+ */
+ public void setYear(int value) {
+ this.year = value;
+ }
+}
diff --git a/user/src/com/google/gwt/i18n/client/DateTimeFormat.java b/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
index 91da953..a6c1a72 100644
--- a/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
+++ b/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
@@ -1,1681 +1,1681 @@
-/*
- * Copyright 2007 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.i18n.client;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.i18n.client.constants.DateTimeConstants;
-
-import java.util.ArrayList;
-import java.util.Date;
-
-/**
- * Formats and parses dates and times using locale-sensitive patterns.
- *
- * <h3>Patterns</h3>
- *
- * <table>
- * <tr>
- * <th>Symbol</th>
- * <th>Meaning</th>
- * <th>Presentation</th>
- * <th>Example</th>
- * </tr>
- *
- * <tr>
- * <td><code>G</code></td>
- * <td>era designator</td>
- * <td>Text</td>
- * <td><code>AD</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>y</code></td>
- * <td>year</td>
- * <td>Number</td>
- * <td><code>1996</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>M</code></td>
- * <td>month in year</td>
- * <td>Text or Number</td>
- * <td><code>July (or) 07</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>d</code></td>
- * <td>day in month</td>
- * <td>Number</td>
- * <td><code>10</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>h</code></td>
- * <td>hour in am/pm (1-12)</td>
- * <td>Number</td>
- * <td><code>12</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>H</code></td>
- * <td>hour in day (0-23)</td>
- * <td>Number</td>
- * <td><code>0</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>m</code></td>
- * <td>minute in hour</td>
- * <td>Number</td>
- * <td><code>30</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>s</code></td>
- * <td>second in minute</td>
- * <td>Number</td>
- * <td><code>55</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>S</code></td>
- * <td>fractional second</td>
- * <td>Number</td>
- * <td><code>978</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>E</code></td>
- * <td>day of week</td>
- * <td>Text</td>
- * <td><code>Tuesday</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>a</code></td>
- * <td>am/pm marker</td>
- * <td>Text</td>
- * <td><code>PM</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>k</code></td>
- * <td>hour in day (1-24)</td>
- * <td>Number</td>
- * <td><code>24</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>K</code></td>
- * <td>hour in am/pm (0-11)</td>
- * <td>Number</td>
- * <td><code>0</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>z</code></td>
- * <td>time zone</td>
- * <td>Text</td>
- * <td><code>Pacific Standard Time</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>Z</code></td>
- * <td>time zone (RFC 822)</td>
- * <td>Number</td>
- * <td><code>-0800</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>v</code></td>
- * <td>time zone (generic)</td>
- * <td>Text</td>
- * <td><code>Pacific Time</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>'</code></td>
- * <td>escape for text</td>
- * <td>Delimiter</td>
- * <td><code>'Date='</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>''</code></td>
- * <td>single quote</td>
- * <td>Literal</td>
- * <td><code>'o''clock'</code></td>
- * </tr>
- * </table>
- *
- * <p>
- * The number of pattern letters influences the format, as follows:
- * </p>
- *
- * <dl>
- * <dt>Text</dt>
- * <dd>if 4 or more, then use the full form; if less than 4, use short or
- * abbreviated form if it exists (e.g., <code>"EEEE"</code> produces
- * <code>"Monday"</code>, <code>"EEE"</code> produces <code>"Mon"</code>)</dd>
- *
- * <dt>Number</dt>
- * <dd>the minimum number of digits. Shorter numbers are zero-padded to this
- * amount (e.g. if <code>"m"</code> produces <code>"6"</code>,
- * <code>"mm"</code> produces <code>"06"</code>). Year is handled
- * specially; that is, if the count of 'y' is 2, the Year will be truncated to 2
- * digits. (e.g., if <code>"yyyy"</code> produces <code>"1997"</code>,
- * <code>"yy"</code> produces <code>"97"</code>.) Unlike other fields,
- * fractional seconds are padded on the right with zero.</dd>
- *
- * <dt>Text or Number</dt>
- * <dd>3 or more, use text, otherwise use number. (e.g. <code>"M"</code>
- * produces <code>"1"</code>, <code>"MM"</code> produces <code>"01"</code>,
- * <code>"MMM"</code> produces <code>"Jan"</code>, and <code>"MMMM"</code>
- * produces <code>"January"</code>.</dd>
- * </dl>
- *
- * <p>
- * Any characters in the pattern that are not in the ranges of ['<code>a</code>'..'<code>z</code>']
- * and ['<code>A</code>'..'<code>Z</code>'] will be treated as quoted
- * text. For instance, characters like '<code>:</code>', '<code>.</code>', '<code> </code>'
- * (space), '<code>#</code>' and '<code>@</code>' will appear in the
- * resulting time text even they are not embraced within single quotes.
- * </p>
- *
- * <h3>Parsing Dates and Times</h3>
- * <p>
- * This implementation could parse partial date/time. Current date/time will be
- * used to fill in the unavailable part.
- * </p>
- *
- * <p>
- * As with formatting (described above), the count of pattern letters determine
- * the parsing behavior.
- * </p>
- *
- * <dl>
- * <dt>Text</dt>
- * <dd>4 or more pattern letters--use full form, less than 4--use short or
- * abbreviated form if one exists. In parsing, we will always try long format,
- * then short.</dd>
- *
- * <dt>Number</dt>
- * <dd>the minimum number of digits.</dd>
- *
- * <dt>Text or Number</dt>
- * <dd>3 or more characters means use text, otherwise use number</dd>
- * </dl>
- *
- * <p>
- * Although the current pattern specification doesn't not specify behavior for
- * all letters, it may in the future. It is strongly discouraged to used
- * unspecified letters as literal text without being surrounded by quotes.
- * </p>
- *
- * <h3>Examples</h3>
- * <table>
- * <tr>
- * <th>Pattern</th>
- * <th>Formatted Text</th>
- * </tr>
- *
- * <tr>
- * <td><code>"yyyy.MM.dd G 'at' HH:mm:ss vvvv"</code></td>
- * <td><code>1996.07.10 AD at 15:08:56 Pacific Time</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>"EEE, MMM d, ''yy"</code></td>
- * <td><code>Wed, July 10, '96</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>"h:mm a"</code></td>
- * <td><code>12:08 PM</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>"hh 'o''clock' a, zzzz"</code></td>
- * <td><code> 12 o'clock PM, Pacific Daylight Time</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>"K:mm a, vvv"</code></td>
- * <td><code> 0:00 PM, PT</code></td>
- * </tr>
- *
- * <tr>
- * <td><code>"yyyyy.MMMMM.dd GGG hh:mm aaa"</code></td>
- * <td><code>01996.July.10 AD 12:08 PM</code></td>
- * </tr>
- * </table>
- *
- * <h3>Additional Parsing Considerations</h3>
- * <p>
- * When parsing a date string using the abbreviated year pattern (<code>"yy"</code>),
- * the parser must interpret the abbreviated year relative to some century. It
- * does this by adjusting dates to be within 80 years before and 20 years after
- * the time the parser instance is created. For example, using a pattern of
- * <code>"MM/dd/yy"</code> and a <code>DateTimeFormat</code> object created
- * on Jan 1, 1997, the string <code>"01/11/12"</code> would be interpreted as
- * Jan 11, 2012 while the string <code>"05/04/64"</code> would be interpreted
- * as May 4, 1964. During parsing, only strings consisting of exactly two
- * digits, as defined by {@link java.lang.Character#isDigit(char)}, will be
- * parsed into the default century. If the year pattern does not have exactly
- * two 'y' characters, the year is interpreted literally, regardless of the
- * number of digits. For example, using the pattern <code>"MM/dd/yyyy"</code>,
- * "01/11/12" parses to Jan 11, 12 A.D.
- * </p>
- *
- * <p>
- * When numeric fields abut one another directly, with no intervening delimiter
- * characters, they constitute a run of abutting numeric fields. Such runs are
- * parsed specially. For example, the format "HHmmss" parses the input text
- * "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and fails to
- * parse "1234". In other words, the leftmost field of the run is flexible,
- * while the others keep a fixed width. If the parse fails anywhere in the run,
- * then the leftmost field is shortened by one character, and the entire run is
- * parsed again. This is repeated until either the parse succeeds or the
- * leftmost field is one character in length. If the parse still fails at that
- * point, the parse of the run fails.
- * </p>
- *
- * <p>
- * In the current implementation, timezone parsing only supports
- * <code>GMT:hhmm</code>, <code>GMT:+hhmm</code>, and
- * <code>GMT:-hhmm</code>.
- * </p>
- */
-public class DateTimeFormat {
- /**
- * Class PatternPart holds a "compiled" pattern part.
- */
- private class PatternPart {
- public String text;
- public int count; // 0 has a special meaning, it stands for literal
- public boolean abutStart;
-
- public PatternPart(String txt, int cnt) {
- text = txt;
- count = cnt;
- abutStart = false;
- }
- }
-
- private static final int FULL_DATE_FORMAT = 0;
- private static final int LONG_DATE_FORMAT = 1;
- private static final int MEDIUM_DATE_FORMAT = 2;
- private static final int SHORT_DATE_FORMAT = 3;
- private static final int FULL_TIME_FORMAT = 0;
- private static final int LONG_TIME_FORMAT = 1;
- private static final int MEDIUM_TIME_FORMAT = 2;
-
- private static final int SHORT_TIME_FORMAT = 3;
- private static final int NUMBER_BASE = 10;
- private static final int JS_START_YEAR = 1900;
-
- private static DateTimeFormat cachedFullDateFormat;
- private static DateTimeFormat cachedLongDateFormat;
- private static DateTimeFormat cachedMediumDateFormat;
-
- private static DateTimeFormat cachedShortDateFormat;
- private static DateTimeFormat cachedFullTimeFormat;
- private static DateTimeFormat cachedLongTimeFormat;
- private static DateTimeFormat cachedMediumTimeFormat;
-
- private static DateTimeFormat cachedShortTimeFormat;
- private static DateTimeFormat cachedFullDateTimeFormat;
- private static DateTimeFormat cachedLongDateTimeFormat;
- private static DateTimeFormat cachedMediumDateTimeFormat;
- private static DateTimeFormat cachedShortDateTimeFormat;
-
- private static final DateTimeConstants defaultDateTimeConstants = (DateTimeConstants) GWT.create(DateTimeConstants.class);
-
- private static final String PATTERN_CHARS = "GyMdkHmsSEDahKzZv";
-
- private static final String NUMERIC_FORMAT_CHARS = "MydhHmsSDkK";
-
- private static final String WHITE_SPACE = " \t\r\n";
-
- private static final String GMT = "GMT";
-
- private static final int MINUTES_PER_HOUR = 60;
-
- /**
- * Returns a format object using the specified pattern and the date time
- * constants for the default locale. If you need to format or parse repeatedly
- * using the same pattern, it is highly recommended that you cache the
- * returned <code>DateTimeFormat</code> object and reuse it rather than
- * calling this method repeatedly.
- *
- * @param pattern string to specify how the date should be formatted
- *
- * @return a <code>DateTimeFormat</code> object that can be used for format
- * or parse date/time values matching the specified pattern
- */
- public static DateTimeFormat getFormat(String pattern) {
- return new DateTimeFormat(pattern, defaultDateTimeConstants);
- }
-
- public static DateTimeFormat getFullDateFormat() {
- if (cachedFullDateFormat == null) {
- String pattern = defaultDateTimeConstants.dateFormats()[FULL_DATE_FORMAT];
- cachedFullDateFormat = new DateTimeFormat(pattern);
- }
- return cachedFullDateFormat;
- }
-
- public static DateTimeFormat getFullDateTimeFormat() {
- if (cachedFullDateTimeFormat == null) {
- String pattern = defaultDateTimeConstants.dateFormats()[FULL_DATE_FORMAT]
- + " " + defaultDateTimeConstants.timeFormats()[FULL_TIME_FORMAT];
- cachedFullDateTimeFormat = new DateTimeFormat(pattern);
- }
- return cachedFullDateTimeFormat;
- }
-
- public static DateTimeFormat getFullTimeFormat() {
- if (cachedFullTimeFormat == null) {
- String pattern = defaultDateTimeConstants.timeFormats()[FULL_TIME_FORMAT];
- cachedFullTimeFormat = new DateTimeFormat(pattern);
- }
- return cachedFullTimeFormat;
- }
-
- public static DateTimeFormat getLongDateFormat() {
- if (cachedLongDateFormat == null) {
- String pattern = defaultDateTimeConstants.dateFormats()[LONG_DATE_FORMAT];
- cachedLongDateFormat = new DateTimeFormat(pattern);
- }
- return cachedLongDateFormat;
- }
-
- public static DateTimeFormat getLongDateTimeFormat() {
- if (cachedLongDateTimeFormat == null) {
- String pattern = defaultDateTimeConstants.dateFormats()[LONG_DATE_FORMAT]
- + " " + defaultDateTimeConstants.timeFormats()[LONG_TIME_FORMAT];
- cachedLongDateTimeFormat = new DateTimeFormat(pattern);
- }
- return cachedLongDateTimeFormat;
- }
-
- public static DateTimeFormat getLongTimeFormat() {
- if (cachedLongTimeFormat == null) {
- String pattern = defaultDateTimeConstants.timeFormats()[LONG_TIME_FORMAT];
- cachedLongTimeFormat = new DateTimeFormat(pattern);
- }
- return cachedLongTimeFormat;
- }
-
- public static DateTimeFormat getMediumDateFormat() {
- if (cachedMediumDateFormat == null) {
- String pattern = defaultDateTimeConstants.dateFormats()[MEDIUM_DATE_FORMAT];
- cachedMediumDateFormat = new DateTimeFormat(pattern);
- }
- return cachedMediumDateFormat;
- };
-
- public static DateTimeFormat getMediumDateTimeFormat() {
- if (cachedMediumDateTimeFormat == null) {
- String pattern = defaultDateTimeConstants.dateFormats()[MEDIUM_DATE_FORMAT]
- + " " + defaultDateTimeConstants.timeFormats()[MEDIUM_TIME_FORMAT];
- cachedMediumDateTimeFormat = new DateTimeFormat(pattern);
- }
- return cachedMediumDateTimeFormat;
- }
-
- public static DateTimeFormat getMediumTimeFormat() {
- if (cachedMediumTimeFormat == null) {
- String pattern = defaultDateTimeConstants.timeFormats()[MEDIUM_TIME_FORMAT];
- cachedMediumTimeFormat = new DateTimeFormat(pattern);
- }
- return cachedMediumTimeFormat;
- }
-
- public static DateTimeFormat getShortDateFormat() {
- if (cachedShortDateFormat == null) {
- String pattern = defaultDateTimeConstants.dateFormats()[SHORT_DATE_FORMAT];
- cachedShortDateFormat = new DateTimeFormat(pattern);
- }
- return cachedShortDateFormat;
- }
-
- public static DateTimeFormat getShortDateTimeFormat() {
- if (cachedShortDateTimeFormat == null) {
- String pattern = defaultDateTimeConstants.dateFormats()[SHORT_DATE_FORMAT]
- + " " + defaultDateTimeConstants.timeFormats()[SHORT_TIME_FORMAT];
- cachedShortDateTimeFormat = new DateTimeFormat(pattern);
- }
- return cachedShortDateTimeFormat;
- }
-
- public static DateTimeFormat getShortTimeFormat() {
- if (cachedShortTimeFormat == null) {
- String pattern = defaultDateTimeConstants.timeFormats()[SHORT_TIME_FORMAT];
- cachedShortTimeFormat = new DateTimeFormat(pattern);
- }
- return cachedShortTimeFormat;
- }
-
- private final ArrayList patternParts = new ArrayList();
-
- private final DateTimeConstants dateTimeConstants;
-
- private final String pattern;;
-
- /**
- * Constructs a format object using the specified pattern and the date time
- * constants for the default locale.
- *
- * @param pattern string pattern specification
- */
- protected DateTimeFormat(String pattern) {
- this(pattern, defaultDateTimeConstants);
- };
-
- /**
- * Constructs a format object using the specified pattern and user-supplied
- * date time constants.
- *
- * @param pattern string pattern specification
- * @param dateTimeConstants locale specific symbol collection
- */
- protected DateTimeFormat(String pattern, DateTimeConstants dateTimeConstants) {
- this.pattern = pattern;
- this.dateTimeConstants = dateTimeConstants;
-
- /*
- * Even though the pattern is only compiled for use in parsing and parsing
- * is far less common than formatting, the pattern is still parsed eagerly
- * here to fail fast in case the pattern itself is malformed.
- */
- parsePattern(pattern);
- };
-
- /**
- * Format a date object.
- *
- * @param date the date object being formatted
- *
- * @return formatted date representation
- */
- public String format(Date date) {
- StringBuffer toAppendTo = new StringBuffer(64);
- int j, n = pattern.length();
- for (int i = 0; i < n;) {
- char ch = pattern.charAt(i);
- if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
- // ch is a date-time pattern character to be interpreted by subFormat().
- // Count the number of times it is repeated.
- for (j = i + 1; j < n && pattern.charAt(j) == ch; ++j) {
- }
- subFormat(toAppendTo, ch, j - i, date);
- i = j;
- } else if (ch == '\'') {
- // Handle an entire quoted string, included embedded
- // doubled apostrophes (as in 'o''clock').
-
- // i points after '.
- ++i;
-
- // If start with '', just add ' and continue.
- if (i < n && pattern.charAt(i) == '\'') {
- toAppendTo.append('\'');
- ++i;
- continue;
- }
-
- // Otherwise add the quoted string.
- boolean trailQuote = false;
- while (!trailQuote) {
- // j points to next ' or EOS.
- j = i;
- while (j < n && pattern.charAt(j) != '\'') {
- ++j;
- }
-
- if (j >= n) {
- // Trailing ' (pathological).
- throw new IllegalArgumentException("Missing trailing \'");
- }
-
- // Look ahead to detect '' within quotes.
- if (j + 1 < n && pattern.charAt(j + 1) == '\'') {
- ++j;
- } else {
- trailQuote = true;
- }
- toAppendTo.append(pattern.substring(i, j));
- i = j + 1;
- }
- } else {
- // Append unquoted literal characters.
- toAppendTo.append(ch);
- ++i;
- }
- }
-
- return toAppendTo.toString();
- };
-
- public String getPattern() {
- return pattern;
- };
-
- /**
- * Parses text to produce a {@link Date} value. An
- * {@link IllegalArgumentException} is thrown if either the text is empty or
- * if the parse does not consume all characters of the text.
- *
- * @param text the string being parsed
- * @return a parsed date/time value
- * @throws IllegalArgumentException if the entire text could not be converted
- * into a number
- */
- public Date parse(String text) {
- Date date = new Date();
- int charsConsumed = parse(text, 0, date);
- if (charsConsumed == 0 || charsConsumed < text.length()) {
- throw new IllegalArgumentException(text);
- }
- return date;
- }
-
- /**
- * This method parses the input string, fill its value into a {@link Date}.
- *
- * @param text the string that need to be parsed
- * @param start the character position in "text" where parsing should start
- * @param date the date object that will hold parsed value
- *
- * @return 0 if parsing failed, otherwise the number of characters advanced
- */
- public int parse(String text, int start, Date date) {
- DateRecord cal = new DateRecord();
- int[] parsePos = {start};
-
- // For parsing abutting numeric fields. 'abutPat' is the
- // offset into 'pattern' of the first of 2 or more abutting
- // numeric fields. 'abutStart' is the offset into 'text'
- // where parsing the fields begins. 'abutPass' starts off as 0
- // and increments each time we try to parse the fields.
- int abutPat = -1; // If >=0, we are in a run of abutting numeric fields.
- int abutStart = 0;
- int abutPass = 0;
-
- for (int i = 0; i < patternParts.size(); ++i) {
- PatternPart part = (PatternPart) patternParts.get(i);
-
- if (part.count > 0) {
- if (abutPat < 0 && part.abutStart) {
- abutPat = i;
- abutStart = start;
- abutPass = 0;
- }
-
- // Handle fields within a run of abutting numeric fields. Take
- // the pattern "HHmmss" as an example. We will try to parse
- // 2/2/2 characters of the input text, then if that fails,
- // 1/2/2. We only adjust the width of the leftmost field; the
- // others remain fixed. This allows "123456" => 12:34:56, but
- // "12345" => 1:23:45. Likewise, for the pattern "yyyyMMdd" we
- // try 4/2/2, 3/2/2, 2/2/2, and finally 1/2/2.
- if (abutPat >= 0) {
- // If we are at the start of a run of abutting fields, then
- // shorten this field in each pass. If we can't shorten
- // this field any more, then the parse of this set of
- // abutting numeric fields has failed.
- int count = part.count;
- if (i == abutPat) {
- count -= abutPass++;
- if (count == 0) {
- return 0;
- }
- }
-
- if (!subParse(text, parsePos, part, count, cal)) {
- // If the parse fails anywhere in the run, back up to the
- // start of the run and retry.
- i = abutPat - 1;
- parsePos[0] = abutStart;
- continue;
- }
- } else {
- // Handle non-numeric fields and non-abutting numeric fields.
- abutPat = -1;
- if (!subParse(text, parsePos, part, 0, cal)) {
- return 0;
- }
- }
- } else {
- // Handle literal pattern characters. These are any
- // quoted characters and non-alphabetic unquoted characters.
- abutPat = -1;
- // A run of white space in the pattern matches a run
- // of white space in the input text.
- if (part.text.charAt(0) == ' ') {
- // Advance over run in input text.
- int s = parsePos[0];
- skipSpace(text, parsePos);
-
- // Must see at least one white space char in input.
- if (parsePos[0] > s) {
- continue;
- }
- } else if (text.startsWith(part.text, parsePos[0])) {
- parsePos[0] += part.text.length();
- continue;
- }
-
- // We fall through to this point if the match fails.
- return 0;
- }
- }
-
- if (!cal.calcDate(date)) {
- return 0;
- }
-
- // Return progress.
- return parsePos[0] - start;
- };
-
- /**
- * Method append current content in buf as pattern part if there is any, and
- * clear buf for next part.
- *
- * @param buf pattern part text specification
- * @param count pattern part repeat count
- */
- private void addPart(StringBuffer buf, int count) {
- if (buf.length() > 0) {
- patternParts.add((new PatternPart(buf.toString(), count)));
- buf.setLength(0);
- }
- };
-
- /**
- * Generate GMT timezone string for given date.
- *
- * @param buf where timezone string will be appended to
- * @param date whose value being evaluated
- */
- private void appendGMT(StringBuffer buf, Date date) {
- int value = -date.getTimezoneOffset();
-
- if (value < 0) {
- buf.append("GMT-");
- value = -value; // suppress the '-' sign for text display.
- } else {
- buf.append("GMT+");
- }
-
- zeroPaddingNumber(buf, value / MINUTES_PER_HOUR, 2);
- buf.append(':');
- zeroPaddingNumber(buf, value % MINUTES_PER_HOUR, 2);
- };
-
- /**
- * Formats (0..11) Hours field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void format0To11Hours(StringBuffer buf, int count, Date date) {
- int value = date.getHours() % 12;
- zeroPaddingNumber(buf, value, count);
- };
-
- /**
- * Formats (0..23) Hours field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void format0To23Hours(StringBuffer buf, int count, Date date) {
- int value = date.getHours();
- zeroPaddingNumber(buf, value, count);
- };
-
- /**
- * Formats (1..12) Hours field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void format1To12Hours(StringBuffer buf, int count, Date date) {
- int value = date.getHours() % 12;
- if (value == 0) {
- zeroPaddingNumber(buf, 12, count);
- } else {
- zeroPaddingNumber(buf, value, count);
- }
- };
-
- /**
- * Formats (1..24) Hours field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void format24Hours(StringBuffer buf, int count, Date date) {
- int value = date.getHours();
- if (value == 0) {
- zeroPaddingNumber(buf, 24, count);
- } else {
- zeroPaddingNumber(buf, value, count);
- }
- }
-
- /**
- * Formats AM/PM field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatAmPm(StringBuffer buf, int count, Date date) {
- if (date.getHours() >= 12 && date.getHours() < 24) {
- buf.append(dateTimeConstants.ampms()[1]);
- } else {
- buf.append(dateTimeConstants.ampms()[0]);
- }
- };
-
- /**
- * Formats Date field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatDate(StringBuffer buf, int count, Date date) {
- int value = date.getDate();
- zeroPaddingNumber(buf, value, count);
- };
-
- /**
- * Formats Day of week field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatDayOfWeek(StringBuffer buf, int count, Date date) {
- int value = date.getDay();
- if (count >= 4) {
- buf.append(dateTimeConstants.weekdays()[value]);
- } else {
- buf.append(dateTimeConstants.shortWeekdays()[value]);
- }
- }
-
- /**
- * Formats Era field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatEra(StringBuffer buf, int count, Date date) {
- int value = date.getYear() >= -JS_START_YEAR ? 1 : 0;
- if (count >= 4) {
- buf.append(dateTimeConstants.eraNames()[value]);
- } else {
- buf.append(dateTimeConstants.eras()[value]);
- }
- }
-
- /**
- * Formats Fractional seconds field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatFractionalSeconds(StringBuffer buf, int count, Date date) {
- // Fractional seconds should be left-justified, ie. zero must be padded
- // from left. For example, if value in milliseconds is 5, and count is 3,
- // the output need to be "005".
- int value = (int) (date.getTime() % 1000);
- if (count == 1) {
- value = (value + 50) / 100; // Round to 100ms.
- buf.append(Integer.toString(value));
- } else if (count == 2) {
- value = (value + 5) / 10; // Round to 10ms.
- zeroPaddingNumber(buf, value, 2);
- } else {
- zeroPaddingNumber(buf, value, 3);
-
- if (count > 3) {
- zeroPaddingNumber(buf, 0, count - 3);
- }
- }
- }
-
- /**
- * Formats Minutes field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatMinutes(StringBuffer buf, int count, Date date) {
- int value = date.getMinutes();
- zeroPaddingNumber(buf, value, count);
- }
-
- /**
- * Formats Month field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatMonth(StringBuffer buf, int count, Date date) {
- int value = date.getMonth();
- switch (count) {
- case 5:
- buf.append(dateTimeConstants.narrowMonths()[value]);
- break;
- case 4:
- buf.append(dateTimeConstants.standaloneMonths()[value]);
- break;
- case 3:
- buf.append(dateTimeConstants.shortMonths()[value]);
- break;
- default:
- zeroPaddingNumber(buf, value + 1, count);
- }
- }
-
- /**
- * Formats Quarter field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatQuarter(StringBuffer buf, int count, Date date) {
- int value = date.getMonth() / 3;
- if (count < 4) {
- buf.append(dateTimeConstants.shortQuarters()[value]);
- } else {
- buf.append(dateTimeConstants.quarters()[value]);
- }
- }
-
- /**
- * Formats Seconds field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatSeconds(StringBuffer buf, int count, Date date) {
- int value = date.getSeconds();
- zeroPaddingNumber(buf, value, count);
- }
-
- /**
- * Formats Standalone weekday field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatStandaloneDay(StringBuffer buf, int count, Date date) {
- int value = date.getDay();
- if (count == 5) {
- buf.append(dateTimeConstants.standaloneNarrowWeekdays()[value]);
- } else if (count == 4) {
- buf.append(dateTimeConstants.standaloneWeekdays()[value]);
- } else if (count == 3) {
- buf.append(dateTimeConstants.standaloneShortWeekdays()[value]);
- } else {
- zeroPaddingNumber(buf, value, 1);
- }
- }
-
- /**
- * Formats Standalone Month field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatStandaloneMonth(StringBuffer buf, int count, Date date) {
- int value = date.getMonth();
- if (count == 5) {
- buf.append(dateTimeConstants.standaloneNarrowMonths()[value]);
- } else if (count == 4) {
- buf.append(dateTimeConstants.standaloneMonths()[value]);
- } else if (count == 3) {
- buf.append(dateTimeConstants.standaloneShortMonths()[value]);
- } else {
- zeroPaddingNumber(buf, value + 1, count);
- }
- }
-
- /**
- * Formats Timezone field following RFC.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatTimeZoneRFC(StringBuffer buf, int count, Date date) {
- if (count < 4) {
- // 'short' (standard Java) form, must use ASCII digits
- int val = date.getTimezoneOffset();
- char sign = '-';
- if (val < 0) {
- val = -val;
- sign = '+';
- }
-
- val = (val / 3) * 5 + (val % MINUTES_PER_HOUR); // minutes => KKmm
- buf.append(sign);
- zeroPaddingNumber(buf, val, 4);
- } else {
- appendGMT(buf, date);
- }
- }
-
- /**
- * Formats Year field according to pattern specified. Javascript Date object
- * seems incapable handling 1BC and year before. It can show you year 0 which
- * does not exists. following we just keep consistent with javascript's
- * toString method. But keep in mind those things should be unsupported.
- *
- * @param buf where formatted string will be appended to
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- */
- private void formatYear(StringBuffer buf, int count, Date date) {
- int value = date.getYear() + JS_START_YEAR;
- if (value < 0) {
- value = -value;
- }
- if (count == 2) {
- zeroPaddingNumber(buf, value % 100, 2);
- } else {
- // count != 2
- buf.append(Integer.toString(value));
- }
- }
-
- /**
- * Method getNextCharCountInPattern calculate character repeat count in
- * pattern.
- *
- * @param pattern describe the format of date string that need to be parsed
- * @param start the position of pattern character
- * @return repeat count
- */
- private int getNextCharCountInPattern(String pattern, int start) {
- char ch = pattern.charAt(start);
- int next = start + 1;
- while (next < pattern.length() && pattern.charAt(next) == ch) {
- ++next;
- }
- return next - start;
- }
-
- /**
- * Method identifies the start of a run of abutting numeric fields. Take the
- * pattern "HHmmss" as an example. We will try to parse 2/2/2 characters of
- * the input text, then if that fails, 1/2/2. We only adjust the width of the
- * leftmost field; the others remain fixed. This allows "123456" => 12:34:56,
- * but "12345" => 1:23:45. Likewise, for the pattern "yyyyMMdd" we try 4/2/2,
- * 3/2/2, 2/2/2, and finally 1/2/2. The first field of connected numeric
- * fields will be marked as abutStart, its width can be reduced to accomodate
- * others.
- */
- private void identifyAbutStart() {
- // 'abut' parts are continuous numeric parts. abutStart is the switch
- // point from non-abut to abut.
- boolean abut = false;
-
- int len = patternParts.size();
- for (int i = 0; i < len; i++) {
- if (isNumeric((PatternPart) patternParts.get(i))) {
- // If next part is not following abut sequence, and isNumeric.
- if (!abut && i + 1 < len
- && isNumeric((PatternPart) patternParts.get(i + 1))) {
- abut = true;
- ((PatternPart) patternParts.get(i)).abutStart = true;
- }
- } else {
- abut = false;
- }
- }
- }
-
- /**
- * Method checks if the pattern part is a numeric field.
- *
- * @param part pattern part to be examined
- * @return <code>true</code> if the pattern part is numberic field
- */
- private final boolean isNumeric(PatternPart part) {
- if (part.count <= 0) {
- return false;
- }
- int i = NUMERIC_FORMAT_CHARS.indexOf(part.text.charAt(0));
- return (i > 0 || (i == 0 && part.count < 3));
- }
-
- /**
- * Method attempts to match the text at a given position against an array of
- * strings. Since multiple strings in the array may match (for example, if the
- * array contains "a", "ab", and "abc", all will match the input string
- * "abcd") the longest match is returned.
- *
- * @param text the time text being parsed
- * @param start where to start parsing
- * @param data the string array to parsed
- * @param pos to receive where the match stopped
- * @return the new start position if matching succeeded; a negative number
- * indicating matching failure
- */
- private int matchString(String text, int start, String[] data, int[] pos) {
- int count = data.length;
-
- // There may be multiple strings in the data[] array which begin with
- // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
- // We keep track of the longest match, and return that. Note that this
- // unfortunately requires us to test all array elements.
- int bestMatchLength = 0, bestMatch = -1;
- String textInLowerCase = text.substring(start).toLowerCase();
- for (int i = 0; i < count; ++i) {
- int length = data[i].length();
- // Always compare if we have no match yet; otherwise only compare
- // against potentially better matches (longer strings).
- if (length > bestMatchLength
- && textInLowerCase.startsWith(data[i].toLowerCase())) {
- bestMatch = i;
- bestMatchLength = length;
- }
- }
- if (bestMatch >= 0) {
- pos[0] = start + bestMatchLength;
- }
- return bestMatch;
- }
-
- /**
- * Method parses a integer string and return integer value.
- *
- * @param text string being parsed
- * @param pos parse position
- *
- * @return integer value
- */
- private int parseInt(String text, int[] pos) {
- int ret = 0;
- int ind = pos[0];
- char ch = text.charAt(ind);
- while (ch >= '0' && ch <= '9') {
- ret = ret * 10 + (ch - '0');
- ind++;
- if (ind >= text.length()) {
- break;
- }
- ch = text.charAt(ind);
- }
- if (ind > pos[0]) {
- pos[0] = ind;
- } else {
- ret = -1;
- }
- return ret;
- }
-
- /**
- * Method parses the input pattern string a generate a vector of pattern
- * parts.
- *
- * @param pattern describe the format of date string that need to be parsed
- */
- private void parsePattern(String pattern) {
- StringBuffer buf = new StringBuffer(32);
- boolean inQuote = false;
-
- for (int i = 0; i < pattern.length(); i++) {
- char ch = pattern.charAt(i);
-
- // Handle space, add literal part (if exist), and add space part.
- if (ch == ' ') {
- addPart(buf, 0);
- buf.append(' ');
- addPart(buf, 0);
- while (i + 1 < pattern.length() && pattern.charAt(i + 1) == ' ') {
- i++;
- }
- continue;
- }
-
- // If inside quote, except two quote connected, just copy or exit.
- if (inQuote) {
- if (ch == '\'') {
- if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') {
- // Quote appeared twice continuously, interpret as one quote.
- buf.append(ch);
- ++i;
- } else {
- inQuote = false;
- }
- } else {
- // Literal.
- buf.append(ch);
- }
- continue;
- }
-
- // Outside quote now.
- if (PATTERN_CHARS.indexOf(ch) > 0) {
- addPart(buf, 0);
- buf.append(ch);
- int count = getNextCharCountInPattern(pattern, i);
- addPart(buf, count);
- i += count - 1;
- continue;
- }
-
- // Two consecutive quotes is a quote literal, inside or outside of quotes.
- if (ch == '\'') {
- if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') {
- buf.append('\'');
- i++;
- } else {
- inQuote = true;
- }
- } else {
- buf.append(ch);
- }
- }
-
- addPart(buf, 0);
-
- identifyAbutStart();
- }
-
- /**
- * Method parses time zone offset.
- *
- * @param text the time text to be parsed
- * @param pos Parse position
- * @param cal DateRecord object that holds parsed value
- *
- * @return <code>true</code> if parsing successful, otherwise
- * <code>false</code>
- */
- private boolean parseTimeZoneOffset(String text, int[] pos, DateRecord cal) {
- if (pos[0] >= text.length()) {
- cal.setTzOffset(0);
- return true;
- }
-
- int sign;
- switch (text.charAt(pos[0])) {
- case '+':
- sign = 1;
- break;
- case '-':
- sign = -1;
- break;
- default:
- cal.setTzOffset(0);
- return true;
- }
- ++(pos[0]);
-
- // Look for hours:minutes or hhmm.
- int st = pos[0];
- int value = parseInt(text, pos);
- if (value == 0 && pos[0] == st) {
- return false;
- }
-
- int offset;
- if (pos[0] < text.length() && text.charAt(pos[0]) == ':') {
- // This is the hours:minutes case.
- offset = value * MINUTES_PER_HOUR;
- ++(pos[0]);
- st = pos[0];
- value = parseInt(text, pos);
- if (value == 0 && pos[0] == st) {
- return false;
- }
- offset += value;
- } else {
- // This is the hhmm case.
- offset = value;
- // Assume "-23".."+23" refers to hours.
- if (offset < 24 && (pos[0] - st) <= 2) {
- offset *= MINUTES_PER_HOUR;
- } else {
- offset = offset % 100 + offset / 100 * MINUTES_PER_HOUR;
- }
- }
-
- offset *= sign;
- cal.setTzOffset(-offset);
- return true;
- }
-
- /**
- * Method skips space in the string as pointed by pos.
- *
- * @param text input string
- * @param pos where skip start, and return back where skip stop
- */
- private void skipSpace(String text, int[] pos) {
- while (pos[0] < text.length()
- && WHITE_SPACE.indexOf(text.charAt(pos[0])) >= 0) {
- ++(pos[0]);
- }
- }
-
- /**
- * Formats a single field according to pattern specified.
- *
- * @param buf where formatted string will be appended to
- * @param ch pattern for this field
- * @param count number of time pattern char repeats; this controls how a field
- * should be formatted
- * @param date hold the date object to be formatted
- *
- * @return <code>true</code> if pattern valid, otherwise <code>false</code>
- */
- private boolean subFormat(StringBuffer buf, char ch, int count, Date date) {
- switch (ch) {
- case 'G':
- formatEra(buf, count, date);
- break;
- case 'y':
- formatYear(buf, count, date);
- break;
- case 'M':
- formatMonth(buf, count, date);
- break;
- case 'k':
- format24Hours(buf, count, date);
- break;
- case 'S':
- formatFractionalSeconds(buf, count, date);
- break;
- case 'E':
- formatDayOfWeek(buf, count, date);
- break;
- case 'a':
- formatAmPm(buf, count, date);
- break;
- case 'h':
- format1To12Hours(buf, count, date);
- break;
- case 'K':
- format0To11Hours(buf, count, date);
- break;
- case 'H':
- format0To23Hours(buf, count, date);
- break;
- case 'c':
- formatStandaloneDay(buf, count, date);
- break;
- case 'L':
- formatStandaloneMonth(buf, count, date);
- break;
- case 'Q':
- formatQuarter(buf, count, date);
- break;
- case 'd':
- formatDate(buf, count, date);
- break;
- case 'm':
- formatMinutes(buf, count, date);
- break;
- case 's':
- formatSeconds(buf, count, date);
- break;
- case 'z':
- case 'v':
- appendGMT(buf, date);
- break;
- case 'Z':
- formatTimeZoneRFC(buf, count, date);
- break;
- default:
- return false;
- }
- return true;
- }
-
- /**
- * Converts one field of the input string into a numeric field value. Returns
- * <code>false</code> if failed.
- *
- * @param text the time text to be parsed
- * @param pos Parse position
- * @param part the pattern part for this field
- * @param digitCount when greater than 0, numeric parsing must obey the count
- * @param cal DateRecord object that will hold parsed value
- *
- * @return <code>true</code> if parsing successful
- */
- private boolean subParse(String text, int[] pos, PatternPart part,
- int digitCount, DateRecord cal) {
-
- skipSpace(text, pos);
-
- int start = pos[0];
- char ch = part.text.charAt(0);
-
- // Parse integer value if it is a numeric field.
- int value = -1; // initialize value to be -1,
- if (isNumeric(part)) {
- if (digitCount > 0) {
- if ((start + digitCount) > text.length()) {
- return false;
- }
- value = parseInt(text.substring(0, start + digitCount), pos);
- } else {
- value = parseInt(text, pos);
- }
- }
-
- switch (ch) {
- case 'G': // 'G' - ERA
- value = matchString(text, start, dateTimeConstants.eras(), pos);
- cal.setEra(value);
- return true;
- case 'M': // 'M' - MONTH
- return subParseMonth(text, pos, cal, value, start);
- case 'E':
- return subParseDayOfWeek(text, pos, start, cal);
- case 'a': // 'a' - AM_PM
- value = matchString(text, start, dateTimeConstants.ampms(), pos);
- cal.setAmpm(value);
- return true;
- case 'y': // 'y' - YEAR
- return subParseYear(text, pos, start, value, part, cal);
- case 'd': // 'd' - DATE
- cal.setDayOfMonth(value);
- return true;
- case 'S': // 'S' - FRACTIONAL_SECOND
- return subParseFractionalSeconds(value, start, pos[0], cal);
- case 'h': // 'h' - HOUR (1..12)
- if (value == 12) {
- value = 0;
- }
- // fall through
- case 'K': // 'K' - HOUR (0..11)
- case 'H': // 'H' - HOUR_OF_DAY (0..23)
- cal.setHours(value);
- return true;
- case 'k': // 'k' - HOUR_OF_DAY (1..24)
- cal.setHours(value);
- return true;
- case 'm': // 'm' - MINUTE
- cal.setMinutes(value);
- return true;
- case 's': // 's' - SECOND
- cal.setSeconds(value);
- return true;
-
- case 'z': // 'z' - ZONE_OFFSET
- case 'Z': // 'Z' - TIMEZONE_RFC
- case 'v': // 'v' - TIMEZONE_GENERIC
- return subParseTimeZoneInGMT(text, start, pos, cal);
- default:
- return false;
- }
- }
-
- /**
- * Method subParseDayOfWeek parses day of the week field.
- *
- * @param text the time text to be parsed
- * @param pos Parse position
- * @param start from where parse start
- * @param cal DateRecord object that holds parsed value
- *
- * @return <code>true</code> if parsing successful, otherwise
- * <code>false</code>
- */
- private boolean subParseDayOfWeek(String text, int[] pos, int start,
- DateRecord cal) {
- int value;
- // 'E' - DAY_OF_WEEK
- // Want to be able to parse both short and long forms.
- // Try count == 4 (DDDD) first:
- value = matchString(text, start, dateTimeConstants.weekdays(), pos);
- if (value < 0) {
- value = matchString(text, start, dateTimeConstants.shortWeekdays(), pos);
- }
- if (value < 0) {
- return false;
- }
- cal.setDayOfWeek(value);
- return true;
- }
-
- /**
- * Method subParseFractionalSeconds parses fractional seconds field.
- *
- * @param value parsed numberic value
- * @param start
- * @param end parse position
- * @param cal DateRecord object that holds parsed value
- * @return <code>true</code> if parsing successful, otherwise
- * <code>false</code>
- */
- private boolean subParseFractionalSeconds(int value, int start, int end,
- DateRecord cal) {
- // Fractional seconds left-justify.
- int i = end - start;
- if (i < 3) {
- while (i < 3) {
- value *= 10;
- i++;
- }
- } else {
- int a = 1;
- while (i > 3) {
- a *= 10;
- i--;
- }
- value = (value + (a >> 1)) / a;
- }
- cal.setMilliseconds(value);
- return true;
- }
-
- /**
- * Method subParseMonth parses Month field.
- *
- * @param text the time text to be parsed
- * @param pos Parse position
- * @param cal DateRecord object that will hold parsed value
- * @param value numeric value if this field is expressed using numberic
- * pattern
- * @param start from where parse start
- *
- * @return <code>true</code> if parsing successful
- */
- private boolean subParseMonth(String text, int[] pos, DateRecord cal,
- int value, int start) {
- // When month is symbols, i.e., MMM or MMMM, value will be -1.
- if (value < 0) {
- // Want to be able to parse both short and long forms.
- // Try count == 4 first:
- value = matchString(text, start, dateTimeConstants.months(), pos);
- if (value < 0) { // count == 4 failed, now try count == 3.
- value = matchString(text, start, dateTimeConstants.shortMonths(), pos);
- }
- if (value < 0) {
- return false;
- }
- cal.setMonth(value);
- return true;
- } else {
- cal.setMonth(value - 1);
- return true;
- }
- }
-
- /**
- * Method parses GMT type timezone.
- *
- * @param text the time text to be parsed
- * @param start from where parse start
- * @param pos Parse position
- * @param cal DateRecord object that holds parsed value
- *
- * @return <code>true</code> if parsing successful, otherwise
- * <code>false</code>
- */
- private boolean subParseTimeZoneInGMT(String text, int start, int[] pos,
- DateRecord cal) {
- // First try to parse generic forms such as GMT-07:00. Do this first
- // in case localized DateFormatZoneData contains the string "GMT"
- // for a zone; in that case, we don't want to match the first three
- // characters of GMT+/-HH:MM etc.
-
- // For time zones that have no known names, look for strings
- // of the form:
- // GMT[+-]hours:minutes or
- // GMT[+-]hhmm or
- // GMT.
- if (text.startsWith(GMT, start)) {
- pos[0] = start + GMT.length();
- return parseTimeZoneOffset(text, pos, cal);
- }
-
- // At this point, check for named time zones by looking through
- // the locale data from the DateFormatZoneData strings.
- // Want to be able to parse both short and long forms.
- /*
- * i = subParseZoneString(text, start, cal); if (i != 0) return i;
- */
-
- // As a last resort, look for numeric timezones of the form
- // [+-]hhmm as specified by RFC 822. This code is actually
- // a little more permissive than RFC 822. It will try to do
- // its best with numbers that aren't strictly 4 digits long.
- return parseTimeZoneOffset(text, pos, cal);
- }
-
- /**
- * Method subParseYear parse year field. Year field is special because 1, two
- * digit year need to be resolved. 2, we allow year to take a sign. 3, year
- * field participate in abut processing. In my testing, negative year does not
- * seem working due to JDK (or redpill implementation) limitation. It is not a
- * big deal so we don't worry about it. But keep the logic here so that we
- * might want to replace DateRecord with our a calendar class.
- *
- * @param text the time text to be parsed
- * @param pos parse position
- * @param start where this field star
- * @param value integer value of yea
- * @param part the pattern part for this field
- * @param cal DateRecord object that will hold parsed value
- *
- * @return <code>true</code> if successful
- */
- private boolean subParseYear(String text, int[] pos, int start, int value,
- PatternPart part, DateRecord cal) {
- char ch = ' ';
- if (value < 0) {
- ch = text.charAt(pos[0]);
- // Check if it is a sign.
- if (ch != '+' && ch != '-') {
- return false;
- }
- ++(pos[0]);
- value = parseInt(text, pos);
- if (value < 0) {
- return false;
- }
- if (ch == '-') {
- value = -value;
- }
- }
-
- // no sign, only 2 digit was actually parsed, pattern say it has 2 digit.
- if (ch == ' ' && (pos[0] - start) == 2 && part.count == 2) {
- // Assume for example that the defaultCenturyStart is 6/18/1903.
- // This means that two-digit years will be forced into the range
- // 6/18/1903 to 6/17/2003. As a result, years 00, 01, and 02
- // correspond to 2000, 2001, and 2002. Years 04, 05, etc. correspond
- // to 1904, 1905, etc. If the year is 03, then it is 2003 if the
- // other fields specify a date before 6/18, or 1903 if they specify a
- // date afterwards. As a result, 03 is an ambiguous year. All other
- // two-digit years are unambiguous.
- Date date = new Date();
- int defaultCenturyStartYear = date.getYear() + 1900 - 80;
- int ambiguousTwoDigitYear = defaultCenturyStartYear % 100;
- cal.setAmbiguousYear(value == ambiguousTwoDigitYear);
- value += (defaultCenturyStartYear / 100) * 100
- + (value < ambiguousTwoDigitYear ? 100 : 0);
- }
- cal.setYear(value);
- return true;
- };
-
- /**
- * Formats a number with the specified minimum number of digits, using zero to
- * fill the gap.
- *
- * @param buf where zero padded string will be written to
- * @param value the number value being formatted
- * @param minWidth minimum width of the formatted string; zero will be padded
- * to reach this width
- */
- private void zeroPaddingNumber(StringBuffer buf, int value, int minWidth) {
- int b = NUMBER_BASE;
- for (int i = 0; i < minWidth - 1; i++) {
- if (value < b) {
- buf.append('0');
- }
- b *= NUMBER_BASE;
- }
- buf.append(Integer.toString(value));
- }
-}
+/*
+ * Copyright 2007 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.i18n.client;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.constants.DateTimeConstants;
+
+import java.util.ArrayList;
+import java.util.Date;
+
+/**
+ * Formats and parses dates and times using locale-sensitive patterns.
+ *
+ * <h3>Patterns</h3>
+ *
+ * <table>
+ * <tr>
+ * <th>Symbol</th>
+ * <th>Meaning</th>
+ * <th>Presentation</th>
+ * <th>Example</th>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>G</code></td>
+ * <td>era designator</td>
+ * <td>Text</td>
+ * <td><code>AD</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>y</code></td>
+ * <td>year</td>
+ * <td>Number</td>
+ * <td><code>1996</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>M</code></td>
+ * <td>month in year</td>
+ * <td>Text or Number</td>
+ * <td><code>July (or) 07</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>d</code></td>
+ * <td>day in month</td>
+ * <td>Number</td>
+ * <td><code>10</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>h</code></td>
+ * <td>hour in am/pm (1-12)</td>
+ * <td>Number</td>
+ * <td><code>12</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>H</code></td>
+ * <td>hour in day (0-23)</td>
+ * <td>Number</td>
+ * <td><code>0</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>m</code></td>
+ * <td>minute in hour</td>
+ * <td>Number</td>
+ * <td><code>30</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>s</code></td>
+ * <td>second in minute</td>
+ * <td>Number</td>
+ * <td><code>55</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>S</code></td>
+ * <td>fractional second</td>
+ * <td>Number</td>
+ * <td><code>978</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>E</code></td>
+ * <td>day of week</td>
+ * <td>Text</td>
+ * <td><code>Tuesday</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>a</code></td>
+ * <td>am/pm marker</td>
+ * <td>Text</td>
+ * <td><code>PM</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>k</code></td>
+ * <td>hour in day (1-24)</td>
+ * <td>Number</td>
+ * <td><code>24</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>K</code></td>
+ * <td>hour in am/pm (0-11)</td>
+ * <td>Number</td>
+ * <td><code>0</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>z</code></td>
+ * <td>time zone</td>
+ * <td>Text</td>
+ * <td><code>Pacific Standard Time</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>Z</code></td>
+ * <td>time zone (RFC 822)</td>
+ * <td>Number</td>
+ * <td><code>-0800</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>v</code></td>
+ * <td>time zone (generic)</td>
+ * <td>Text</td>
+ * <td><code>Pacific Time</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>'</code></td>
+ * <td>escape for text</td>
+ * <td>Delimiter</td>
+ * <td><code>'Date='</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>''</code></td>
+ * <td>single quote</td>
+ * <td>Literal</td>
+ * <td><code>'o''clock'</code></td>
+ * </tr>
+ * </table>
+ *
+ * <p>
+ * The number of pattern letters influences the format, as follows:
+ * </p>
+ *
+ * <dl>
+ * <dt>Text</dt>
+ * <dd>if 4 or more, then use the full form; if less than 4, use short or
+ * abbreviated form if it exists (e.g., <code>"EEEE"</code> produces
+ * <code>"Monday"</code>, <code>"EEE"</code> produces <code>"Mon"</code>)</dd>
+ *
+ * <dt>Number</dt>
+ * <dd>the minimum number of digits. Shorter numbers are zero-padded to this
+ * amount (e.g. if <code>"m"</code> produces <code>"6"</code>,
+ * <code>"mm"</code> produces <code>"06"</code>). Year is handled
+ * specially; that is, if the count of 'y' is 2, the Year will be truncated to 2
+ * digits. (e.g., if <code>"yyyy"</code> produces <code>"1997"</code>,
+ * <code>"yy"</code> produces <code>"97"</code>.) Unlike other fields,
+ * fractional seconds are padded on the right with zero.</dd>
+ *
+ * <dt>Text or Number</dt>
+ * <dd>3 or more, use text, otherwise use number. (e.g. <code>"M"</code>
+ * produces <code>"1"</code>, <code>"MM"</code> produces <code>"01"</code>,
+ * <code>"MMM"</code> produces <code>"Jan"</code>, and <code>"MMMM"</code>
+ * produces <code>"January"</code>.</dd>
+ * </dl>
+ *
+ * <p>
+ * Any characters in the pattern that are not in the ranges of ['<code>a</code>'..'<code>z</code>']
+ * and ['<code>A</code>'..'<code>Z</code>'] will be treated as quoted
+ * text. For instance, characters like '<code>:</code>', '<code>.</code>', '<code> </code>'
+ * (space), '<code>#</code>' and '<code>@</code>' will appear in the
+ * resulting time text even they are not embraced within single quotes.
+ * </p>
+ *
+ * <h3>Parsing Dates and Times</h3>
+ * <p>
+ * This implementation could parse partial date/time. Current date/time will be
+ * used to fill in the unavailable part.
+ * </p>
+ *
+ * <p>
+ * As with formatting (described above), the count of pattern letters determine
+ * the parsing behavior.
+ * </p>
+ *
+ * <dl>
+ * <dt>Text</dt>
+ * <dd>4 or more pattern letters--use full form, less than 4--use short or
+ * abbreviated form if one exists. In parsing, we will always try long format,
+ * then short.</dd>
+ *
+ * <dt>Number</dt>
+ * <dd>the minimum number of digits.</dd>
+ *
+ * <dt>Text or Number</dt>
+ * <dd>3 or more characters means use text, otherwise use number</dd>
+ * </dl>
+ *
+ * <p>
+ * Although the current pattern specification doesn't not specify behavior for
+ * all letters, it may in the future. It is strongly discouraged to used
+ * unspecified letters as literal text without being surrounded by quotes.
+ * </p>
+ *
+ * <h3>Examples</h3>
+ * <table>
+ * <tr>
+ * <th>Pattern</th>
+ * <th>Formatted Text</th>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>"yyyy.MM.dd G 'at' HH:mm:ss vvvv"</code></td>
+ * <td><code>1996.07.10 AD at 15:08:56 Pacific Time</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>"EEE, MMM d, ''yy"</code></td>
+ * <td><code>Wed, July 10, '96</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>"h:mm a"</code></td>
+ * <td><code>12:08 PM</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>"hh 'o''clock' a, zzzz"</code></td>
+ * <td><code> 12 o'clock PM, Pacific Daylight Time</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>"K:mm a, vvv"</code></td>
+ * <td><code> 0:00 PM, PT</code></td>
+ * </tr>
+ *
+ * <tr>
+ * <td><code>"yyyyy.MMMMM.dd GGG hh:mm aaa"</code></td>
+ * <td><code>01996.July.10 AD 12:08 PM</code></td>
+ * </tr>
+ * </table>
+ *
+ * <h3>Additional Parsing Considerations</h3>
+ * <p>
+ * When parsing a date string using the abbreviated year pattern (<code>"yy"</code>),
+ * the parser must interpret the abbreviated year relative to some century. It
+ * does this by adjusting dates to be within 80 years before and 20 years after
+ * the time the parser instance is created. For example, using a pattern of
+ * <code>"MM/dd/yy"</code> and a <code>DateTimeFormat</code> object created
+ * on Jan 1, 1997, the string <code>"01/11/12"</code> would be interpreted as
+ * Jan 11, 2012 while the string <code>"05/04/64"</code> would be interpreted
+ * as May 4, 1964. During parsing, only strings consisting of exactly two
+ * digits, as defined by {@link java.lang.Character#isDigit(char)}, will be
+ * parsed into the default century. If the year pattern does not have exactly
+ * two 'y' characters, the year is interpreted literally, regardless of the
+ * number of digits. For example, using the pattern <code>"MM/dd/yyyy"</code>,
+ * "01/11/12" parses to Jan 11, 12 A.D.
+ * </p>
+ *
+ * <p>
+ * When numeric fields abut one another directly, with no intervening delimiter
+ * characters, they constitute a run of abutting numeric fields. Such runs are
+ * parsed specially. For example, the format "HHmmss" parses the input text
+ * "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and fails to
+ * parse "1234". In other words, the leftmost field of the run is flexible,
+ * while the others keep a fixed width. If the parse fails anywhere in the run,
+ * then the leftmost field is shortened by one character, and the entire run is
+ * parsed again. This is repeated until either the parse succeeds or the
+ * leftmost field is one character in length. If the parse still fails at that
+ * point, the parse of the run fails.
+ * </p>
+ *
+ * <p>
+ * In the current implementation, timezone parsing only supports
+ * <code>GMT:hhmm</code>, <code>GMT:+hhmm</code>, and
+ * <code>GMT:-hhmm</code>.
+ * </p>
+ */
+public class DateTimeFormat {
+ /**
+ * Class PatternPart holds a "compiled" pattern part.
+ */
+ private class PatternPart {
+ public String text;
+ public int count; // 0 has a special meaning, it stands for literal
+ public boolean abutStart;
+
+ public PatternPart(String txt, int cnt) {
+ text = txt;
+ count = cnt;
+ abutStart = false;
+ }
+ }
+
+ private static final int FULL_DATE_FORMAT = 0;
+ private static final int LONG_DATE_FORMAT = 1;
+ private static final int MEDIUM_DATE_FORMAT = 2;
+ private static final int SHORT_DATE_FORMAT = 3;
+ private static final int FULL_TIME_FORMAT = 0;
+ private static final int LONG_TIME_FORMAT = 1;
+ private static final int MEDIUM_TIME_FORMAT = 2;
+
+ private static final int SHORT_TIME_FORMAT = 3;
+ private static final int NUMBER_BASE = 10;
+ private static final int JS_START_YEAR = 1900;
+
+ private static DateTimeFormat cachedFullDateFormat;
+ private static DateTimeFormat cachedLongDateFormat;
+ private static DateTimeFormat cachedMediumDateFormat;
+
+ private static DateTimeFormat cachedShortDateFormat;
+ private static DateTimeFormat cachedFullTimeFormat;
+ private static DateTimeFormat cachedLongTimeFormat;
+ private static DateTimeFormat cachedMediumTimeFormat;
+
+ private static DateTimeFormat cachedShortTimeFormat;
+ private static DateTimeFormat cachedFullDateTimeFormat;
+ private static DateTimeFormat cachedLongDateTimeFormat;
+ private static DateTimeFormat cachedMediumDateTimeFormat;
+ private static DateTimeFormat cachedShortDateTimeFormat;
+
+ private static final DateTimeConstants defaultDateTimeConstants = (DateTimeConstants) GWT.create(DateTimeConstants.class);
+
+ private static final String PATTERN_CHARS = "GyMdkHmsSEDahKzZv";
+
+ private static final String NUMERIC_FORMAT_CHARS = "MydhHmsSDkK";
+
+ private static final String WHITE_SPACE = " \t\r\n";
+
+ private static final String GMT = "GMT";
+
+ private static final int MINUTES_PER_HOUR = 60;
+
+ /**
+ * Returns a format object using the specified pattern and the date time
+ * constants for the default locale. If you need to format or parse repeatedly
+ * using the same pattern, it is highly recommended that you cache the
+ * returned <code>DateTimeFormat</code> object and reuse it rather than
+ * calling this method repeatedly.
+ *
+ * @param pattern string to specify how the date should be formatted
+ *
+ * @return a <code>DateTimeFormat</code> object that can be used for format
+ * or parse date/time values matching the specified pattern
+ */
+ public static DateTimeFormat getFormat(String pattern) {
+ return new DateTimeFormat(pattern, defaultDateTimeConstants);
+ }
+
+ public static DateTimeFormat getFullDateFormat() {
+ if (cachedFullDateFormat == null) {
+ String pattern = defaultDateTimeConstants.dateFormats()[FULL_DATE_FORMAT];
+ cachedFullDateFormat = new DateTimeFormat(pattern);
+ }
+ return cachedFullDateFormat;
+ }
+
+ public static DateTimeFormat getFullDateTimeFormat() {
+ if (cachedFullDateTimeFormat == null) {
+ String pattern = defaultDateTimeConstants.dateFormats()[FULL_DATE_FORMAT]
+ + " " + defaultDateTimeConstants.timeFormats()[FULL_TIME_FORMAT];
+ cachedFullDateTimeFormat = new DateTimeFormat(pattern);
+ }
+ return cachedFullDateTimeFormat;
+ }
+
+ public static DateTimeFormat getFullTimeFormat() {
+ if (cachedFullTimeFormat == null) {
+ String pattern = defaultDateTimeConstants.timeFormats()[FULL_TIME_FORMAT];
+ cachedFullTimeFormat = new DateTimeFormat(pattern);
+ }
+ return cachedFullTimeFormat;
+ }
+
+ public static DateTimeFormat getLongDateFormat() {
+ if (cachedLongDateFormat == null) {
+ String pattern = defaultDateTimeConstants.dateFormats()[LONG_DATE_FORMAT];
+ cachedLongDateFormat = new DateTimeFormat(pattern);
+ }
+ return cachedLongDateFormat;
+ }
+
+ public static DateTimeFormat getLongDateTimeFormat() {
+ if (cachedLongDateTimeFormat == null) {
+ String pattern = defaultDateTimeConstants.dateFormats()[LONG_DATE_FORMAT]
+ + " " + defaultDateTimeConstants.timeFormats()[LONG_TIME_FORMAT];
+ cachedLongDateTimeFormat = new DateTimeFormat(pattern);
+ }
+ return cachedLongDateTimeFormat;
+ }
+
+ public static DateTimeFormat getLongTimeFormat() {
+ if (cachedLongTimeFormat == null) {
+ String pattern = defaultDateTimeConstants.timeFormats()[LONG_TIME_FORMAT];
+ cachedLongTimeFormat = new DateTimeFormat(pattern);
+ }
+ return cachedLongTimeFormat;
+ }
+
+ public static DateTimeFormat getMediumDateFormat() {
+ if (cachedMediumDateFormat == null) {
+ String pattern = defaultDateTimeConstants.dateFormats()[MEDIUM_DATE_FORMAT];
+ cachedMediumDateFormat = new DateTimeFormat(pattern);
+ }
+ return cachedMediumDateFormat;
+ };
+
+ public static DateTimeFormat getMediumDateTimeFormat() {
+ if (cachedMediumDateTimeFormat == null) {
+ String pattern = defaultDateTimeConstants.dateFormats()[MEDIUM_DATE_FORMAT]
+ + " " + defaultDateTimeConstants.timeFormats()[MEDIUM_TIME_FORMAT];
+ cachedMediumDateTimeFormat = new DateTimeFormat(pattern);
+ }
+ return cachedMediumDateTimeFormat;
+ }
+
+ public static DateTimeFormat getMediumTimeFormat() {
+ if (cachedMediumTimeFormat == null) {
+ String pattern = defaultDateTimeConstants.timeFormats()[MEDIUM_TIME_FORMAT];
+ cachedMediumTimeFormat = new DateTimeFormat(pattern);
+ }
+ return cachedMediumTimeFormat;
+ }
+
+ public static DateTimeFormat getShortDateFormat() {
+ if (cachedShortDateFormat == null) {
+ String pattern = defaultDateTimeConstants.dateFormats()[SHORT_DATE_FORMAT];
+ cachedShortDateFormat = new DateTimeFormat(pattern);
+ }
+ return cachedShortDateFormat;
+ }
+
+ public static DateTimeFormat getShortDateTimeFormat() {
+ if (cachedShortDateTimeFormat == null) {
+ String pattern = defaultDateTimeConstants.dateFormats()[SHORT_DATE_FORMAT]
+ + " " + defaultDateTimeConstants.timeFormats()[SHORT_TIME_FORMAT];
+ cachedShortDateTimeFormat = new DateTimeFormat(pattern);
+ }
+ return cachedShortDateTimeFormat;
+ }
+
+ public static DateTimeFormat getShortTimeFormat() {
+ if (cachedShortTimeFormat == null) {
+ String pattern = defaultDateTimeConstants.timeFormats()[SHORT_TIME_FORMAT];
+ cachedShortTimeFormat = new DateTimeFormat(pattern);
+ }
+ return cachedShortTimeFormat;
+ }
+
+ private final ArrayList patternParts = new ArrayList();
+
+ private final DateTimeConstants dateTimeConstants;
+
+ private final String pattern;;
+
+ /**
+ * Constructs a format object using the specified pattern and the date time
+ * constants for the default locale.
+ *
+ * @param pattern string pattern specification
+ */
+ protected DateTimeFormat(String pattern) {
+ this(pattern, defaultDateTimeConstants);
+ };
+
+ /**
+ * Constructs a format object using the specified pattern and user-supplied
+ * date time constants.
+ *
+ * @param pattern string pattern specification
+ * @param dateTimeConstants locale specific symbol collection
+ */
+ protected DateTimeFormat(String pattern, DateTimeConstants dateTimeConstants) {
+ this.pattern = pattern;
+ this.dateTimeConstants = dateTimeConstants;
+
+ /*
+ * Even though the pattern is only compiled for use in parsing and parsing
+ * is far less common than formatting, the pattern is still parsed eagerly
+ * here to fail fast in case the pattern itself is malformed.
+ */
+ parsePattern(pattern);
+ };
+
+ /**
+ * Format a date object.
+ *
+ * @param date the date object being formatted
+ *
+ * @return formatted date representation
+ */
+ public String format(Date date) {
+ StringBuffer toAppendTo = new StringBuffer(64);
+ int j, n = pattern.length();
+ for (int i = 0; i < n;) {
+ char ch = pattern.charAt(i);
+ if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
+ // ch is a date-time pattern character to be interpreted by subFormat().
+ // Count the number of times it is repeated.
+ for (j = i + 1; j < n && pattern.charAt(j) == ch; ++j) {
+ }
+ subFormat(toAppendTo, ch, j - i, date);
+ i = j;
+ } else if (ch == '\'') {
+ // Handle an entire quoted string, included embedded
+ // doubled apostrophes (as in 'o''clock').
+
+ // i points after '.
+ ++i;
+
+ // If start with '', just add ' and continue.
+ if (i < n && pattern.charAt(i) == '\'') {
+ toAppendTo.append('\'');
+ ++i;
+ continue;
+ }
+
+ // Otherwise add the quoted string.
+ boolean trailQuote = false;
+ while (!trailQuote) {
+ // j points to next ' or EOS.
+ j = i;
+ while (j < n && pattern.charAt(j) != '\'') {
+ ++j;
+ }
+
+ if (j >= n) {
+ // Trailing ' (pathological).
+ throw new IllegalArgumentException("Missing trailing \'");
+ }
+
+ // Look ahead to detect '' within quotes.
+ if (j + 1 < n && pattern.charAt(j + 1) == '\'') {
+ ++j;
+ } else {
+ trailQuote = true;
+ }
+ toAppendTo.append(pattern.substring(i, j));
+ i = j + 1;
+ }
+ } else {
+ // Append unquoted literal characters.
+ toAppendTo.append(ch);
+ ++i;
+ }
+ }
+
+ return toAppendTo.toString();
+ };
+
+ public String getPattern() {
+ return pattern;
+ };
+
+ /**
+ * Parses text to produce a {@link Date} value. An
+ * {@link IllegalArgumentException} is thrown if either the text is empty or
+ * if the parse does not consume all characters of the text.
+ *
+ * @param text the string being parsed
+ * @return a parsed date/time value
+ * @throws IllegalArgumentException if the entire text could not be converted
+ * into a number
+ */
+ public Date parse(String text) {
+ Date date = new Date();
+ int charsConsumed = parse(text, 0, date);
+ if (charsConsumed == 0 || charsConsumed < text.length()) {
+ throw new IllegalArgumentException(text);
+ }
+ return date;
+ }
+
+ /**
+ * This method parses the input string, fill its value into a {@link Date}.
+ *
+ * @param text the string that need to be parsed
+ * @param start the character position in "text" where parsing should start
+ * @param date the date object that will hold parsed value
+ *
+ * @return 0 if parsing failed, otherwise the number of characters advanced
+ */
+ public int parse(String text, int start, Date date) {
+ DateRecord cal = new DateRecord();
+ int[] parsePos = {start};
+
+ // For parsing abutting numeric fields. 'abutPat' is the
+ // offset into 'pattern' of the first of 2 or more abutting
+ // numeric fields. 'abutStart' is the offset into 'text'
+ // where parsing the fields begins. 'abutPass' starts off as 0
+ // and increments each time we try to parse the fields.
+ int abutPat = -1; // If >=0, we are in a run of abutting numeric fields.
+ int abutStart = 0;
+ int abutPass = 0;
+
+ for (int i = 0; i < patternParts.size(); ++i) {
+ PatternPart part = (PatternPart) patternParts.get(i);
+
+ if (part.count > 0) {
+ if (abutPat < 0 && part.abutStart) {
+ abutPat = i;
+ abutStart = start;
+ abutPass = 0;
+ }
+
+ // Handle fields within a run of abutting numeric fields. Take
+ // the pattern "HHmmss" as an example. We will try to parse
+ // 2/2/2 characters of the input text, then if that fails,
+ // 1/2/2. We only adjust the width of the leftmost field; the
+ // others remain fixed. This allows "123456" => 12:34:56, but
+ // "12345" => 1:23:45. Likewise, for the pattern "yyyyMMdd" we
+ // try 4/2/2, 3/2/2, 2/2/2, and finally 1/2/2.
+ if (abutPat >= 0) {
+ // If we are at the start of a run of abutting fields, then
+ // shorten this field in each pass. If we can't shorten
+ // this field any more, then the parse of this set of
+ // abutting numeric fields has failed.
+ int count = part.count;
+ if (i == abutPat) {
+ count -= abutPass++;
+ if (count == 0) {
+ return 0;
+ }
+ }
+
+ if (!subParse(text, parsePos, part, count, cal)) {
+ // If the parse fails anywhere in the run, back up to the
+ // start of the run and retry.
+ i = abutPat - 1;
+ parsePos[0] = abutStart;
+ continue;
+ }
+ } else {
+ // Handle non-numeric fields and non-abutting numeric fields.
+ abutPat = -1;
+ if (!subParse(text, parsePos, part, 0, cal)) {
+ return 0;
+ }
+ }
+ } else {
+ // Handle literal pattern characters. These are any
+ // quoted characters and non-alphabetic unquoted characters.
+ abutPat = -1;
+ // A run of white space in the pattern matches a run
+ // of white space in the input text.
+ if (part.text.charAt(0) == ' ') {
+ // Advance over run in input text.
+ int s = parsePos[0];
+ skipSpace(text, parsePos);
+
+ // Must see at least one white space char in input.
+ if (parsePos[0] > s) {
+ continue;
+ }
+ } else if (text.startsWith(part.text, parsePos[0])) {
+ parsePos[0] += part.text.length();
+ continue;
+ }
+
+ // We fall through to this point if the match fails.
+ return 0;
+ }
+ }
+
+ if (!cal.calcDate(date)) {
+ return 0;
+ }
+
+ // Return progress.
+ return parsePos[0] - start;
+ };
+
+ /**
+ * Method append current content in buf as pattern part if there is any, and
+ * clear buf for next part.
+ *
+ * @param buf pattern part text specification
+ * @param count pattern part repeat count
+ */
+ private void addPart(StringBuffer buf, int count) {
+ if (buf.length() > 0) {
+ patternParts.add((new PatternPart(buf.toString(), count)));
+ buf.setLength(0);
+ }
+ };
+
+ /**
+ * Generate GMT timezone string for given date.
+ *
+ * @param buf where timezone string will be appended to
+ * @param date whose value being evaluated
+ */
+ private void appendGMT(StringBuffer buf, Date date) {
+ int value = -date.getTimezoneOffset();
+
+ if (value < 0) {
+ buf.append("GMT-");
+ value = -value; // suppress the '-' sign for text display.
+ } else {
+ buf.append("GMT+");
+ }
+
+ zeroPaddingNumber(buf, value / MINUTES_PER_HOUR, 2);
+ buf.append(':');
+ zeroPaddingNumber(buf, value % MINUTES_PER_HOUR, 2);
+ };
+
+ /**
+ * Formats (0..11) Hours field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void format0To11Hours(StringBuffer buf, int count, Date date) {
+ int value = date.getHours() % 12;
+ zeroPaddingNumber(buf, value, count);
+ };
+
+ /**
+ * Formats (0..23) Hours field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void format0To23Hours(StringBuffer buf, int count, Date date) {
+ int value = date.getHours();
+ zeroPaddingNumber(buf, value, count);
+ };
+
+ /**
+ * Formats (1..12) Hours field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void format1To12Hours(StringBuffer buf, int count, Date date) {
+ int value = date.getHours() % 12;
+ if (value == 0) {
+ zeroPaddingNumber(buf, 12, count);
+ } else {
+ zeroPaddingNumber(buf, value, count);
+ }
+ };
+
+ /**
+ * Formats (1..24) Hours field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void format24Hours(StringBuffer buf, int count, Date date) {
+ int value = date.getHours();
+ if (value == 0) {
+ zeroPaddingNumber(buf, 24, count);
+ } else {
+ zeroPaddingNumber(buf, value, count);
+ }
+ }
+
+ /**
+ * Formats AM/PM field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatAmPm(StringBuffer buf, int count, Date date) {
+ if (date.getHours() >= 12 && date.getHours() < 24) {
+ buf.append(dateTimeConstants.ampms()[1]);
+ } else {
+ buf.append(dateTimeConstants.ampms()[0]);
+ }
+ };
+
+ /**
+ * Formats Date field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatDate(StringBuffer buf, int count, Date date) {
+ int value = date.getDate();
+ zeroPaddingNumber(buf, value, count);
+ };
+
+ /**
+ * Formats Day of week field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatDayOfWeek(StringBuffer buf, int count, Date date) {
+ int value = date.getDay();
+ if (count >= 4) {
+ buf.append(dateTimeConstants.weekdays()[value]);
+ } else {
+ buf.append(dateTimeConstants.shortWeekdays()[value]);
+ }
+ }
+
+ /**
+ * Formats Era field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatEra(StringBuffer buf, int count, Date date) {
+ int value = date.getYear() >= -JS_START_YEAR ? 1 : 0;
+ if (count >= 4) {
+ buf.append(dateTimeConstants.eraNames()[value]);
+ } else {
+ buf.append(dateTimeConstants.eras()[value]);
+ }
+ }
+
+ /**
+ * Formats Fractional seconds field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatFractionalSeconds(StringBuffer buf, int count, Date date) {
+ // Fractional seconds should be left-justified, ie. zero must be padded
+ // from left. For example, if value in milliseconds is 5, and count is 3,
+ // the output need to be "005".
+ int value = (int) (date.getTime() % 1000);
+ if (count == 1) {
+ value = (value + 50) / 100; // Round to 100ms.
+ buf.append(Integer.toString(value));
+ } else if (count == 2) {
+ value = (value + 5) / 10; // Round to 10ms.
+ zeroPaddingNumber(buf, value, 2);
+ } else {
+ zeroPaddingNumber(buf, value, 3);
+
+ if (count > 3) {
+ zeroPaddingNumber(buf, 0, count - 3);
+ }
+ }
+ }
+
+ /**
+ * Formats Minutes field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatMinutes(StringBuffer buf, int count, Date date) {
+ int value = date.getMinutes();
+ zeroPaddingNumber(buf, value, count);
+ }
+
+ /**
+ * Formats Month field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatMonth(StringBuffer buf, int count, Date date) {
+ int value = date.getMonth();
+ switch (count) {
+ case 5:
+ buf.append(dateTimeConstants.narrowMonths()[value]);
+ break;
+ case 4:
+ buf.append(dateTimeConstants.standaloneMonths()[value]);
+ break;
+ case 3:
+ buf.append(dateTimeConstants.shortMonths()[value]);
+ break;
+ default:
+ zeroPaddingNumber(buf, value + 1, count);
+ }
+ }
+
+ /**
+ * Formats Quarter field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatQuarter(StringBuffer buf, int count, Date date) {
+ int value = date.getMonth() / 3;
+ if (count < 4) {
+ buf.append(dateTimeConstants.shortQuarters()[value]);
+ } else {
+ buf.append(dateTimeConstants.quarters()[value]);
+ }
+ }
+
+ /**
+ * Formats Seconds field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatSeconds(StringBuffer buf, int count, Date date) {
+ int value = date.getSeconds();
+ zeroPaddingNumber(buf, value, count);
+ }
+
+ /**
+ * Formats Standalone weekday field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatStandaloneDay(StringBuffer buf, int count, Date date) {
+ int value = date.getDay();
+ if (count == 5) {
+ buf.append(dateTimeConstants.standaloneNarrowWeekdays()[value]);
+ } else if (count == 4) {
+ buf.append(dateTimeConstants.standaloneWeekdays()[value]);
+ } else if (count == 3) {
+ buf.append(dateTimeConstants.standaloneShortWeekdays()[value]);
+ } else {
+ zeroPaddingNumber(buf, value, 1);
+ }
+ }
+
+ /**
+ * Formats Standalone Month field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatStandaloneMonth(StringBuffer buf, int count, Date date) {
+ int value = date.getMonth();
+ if (count == 5) {
+ buf.append(dateTimeConstants.standaloneNarrowMonths()[value]);
+ } else if (count == 4) {
+ buf.append(dateTimeConstants.standaloneMonths()[value]);
+ } else if (count == 3) {
+ buf.append(dateTimeConstants.standaloneShortMonths()[value]);
+ } else {
+ zeroPaddingNumber(buf, value + 1, count);
+ }
+ }
+
+ /**
+ * Formats Timezone field following RFC.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatTimeZoneRFC(StringBuffer buf, int count, Date date) {
+ if (count < 4) {
+ // 'short' (standard Java) form, must use ASCII digits
+ int val = date.getTimezoneOffset();
+ char sign = '-';
+ if (val < 0) {
+ val = -val;
+ sign = '+';
+ }
+
+ val = (val / 3) * 5 + (val % MINUTES_PER_HOUR); // minutes => KKmm
+ buf.append(sign);
+ zeroPaddingNumber(buf, val, 4);
+ } else {
+ appendGMT(buf, date);
+ }
+ }
+
+ /**
+ * Formats Year field according to pattern specified. Javascript Date object
+ * seems incapable handling 1BC and year before. It can show you year 0 which
+ * does not exists. following we just keep consistent with javascript's
+ * toString method. But keep in mind those things should be unsupported.
+ *
+ * @param buf where formatted string will be appended to
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ */
+ private void formatYear(StringBuffer buf, int count, Date date) {
+ int value = date.getYear() + JS_START_YEAR;
+ if (value < 0) {
+ value = -value;
+ }
+ if (count == 2) {
+ zeroPaddingNumber(buf, value % 100, 2);
+ } else {
+ // count != 2
+ buf.append(Integer.toString(value));
+ }
+ }
+
+ /**
+ * Method getNextCharCountInPattern calculate character repeat count in
+ * pattern.
+ *
+ * @param pattern describe the format of date string that need to be parsed
+ * @param start the position of pattern character
+ * @return repeat count
+ */
+ private int getNextCharCountInPattern(String pattern, int start) {
+ char ch = pattern.charAt(start);
+ int next = start + 1;
+ while (next < pattern.length() && pattern.charAt(next) == ch) {
+ ++next;
+ }
+ return next - start;
+ }
+
+ /**
+ * Method identifies the start of a run of abutting numeric fields. Take the
+ * pattern "HHmmss" as an example. We will try to parse 2/2/2 characters of
+ * the input text, then if that fails, 1/2/2. We only adjust the width of the
+ * leftmost field; the others remain fixed. This allows "123456" => 12:34:56,
+ * but "12345" => 1:23:45. Likewise, for the pattern "yyyyMMdd" we try 4/2/2,
+ * 3/2/2, 2/2/2, and finally 1/2/2. The first field of connected numeric
+ * fields will be marked as abutStart, its width can be reduced to accomodate
+ * others.
+ */
+ private void identifyAbutStart() {
+ // 'abut' parts are continuous numeric parts. abutStart is the switch
+ // point from non-abut to abut.
+ boolean abut = false;
+
+ int len = patternParts.size();
+ for (int i = 0; i < len; i++) {
+ if (isNumeric((PatternPart) patternParts.get(i))) {
+ // If next part is not following abut sequence, and isNumeric.
+ if (!abut && i + 1 < len
+ && isNumeric((PatternPart) patternParts.get(i + 1))) {
+ abut = true;
+ ((PatternPart) patternParts.get(i)).abutStart = true;
+ }
+ } else {
+ abut = false;
+ }
+ }
+ }
+
+ /**
+ * Method checks if the pattern part is a numeric field.
+ *
+ * @param part pattern part to be examined
+ * @return <code>true</code> if the pattern part is numberic field
+ */
+ private final boolean isNumeric(PatternPart part) {
+ if (part.count <= 0) {
+ return false;
+ }
+ int i = NUMERIC_FORMAT_CHARS.indexOf(part.text.charAt(0));
+ return (i > 0 || (i == 0 && part.count < 3));
+ }
+
+ /**
+ * Method attempts to match the text at a given position against an array of
+ * strings. Since multiple strings in the array may match (for example, if the
+ * array contains "a", "ab", and "abc", all will match the input string
+ * "abcd") the longest match is returned.
+ *
+ * @param text the time text being parsed
+ * @param start where to start parsing
+ * @param data the string array to parsed
+ * @param pos to receive where the match stopped
+ * @return the new start position if matching succeeded; a negative number
+ * indicating matching failure
+ */
+ private int matchString(String text, int start, String[] data, int[] pos) {
+ int count = data.length;
+
+ // There may be multiple strings in the data[] array which begin with
+ // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
+ // We keep track of the longest match, and return that. Note that this
+ // unfortunately requires us to test all array elements.
+ int bestMatchLength = 0, bestMatch = -1;
+ String textInLowerCase = text.substring(start).toLowerCase();
+ for (int i = 0; i < count; ++i) {
+ int length = data[i].length();
+ // Always compare if we have no match yet; otherwise only compare
+ // against potentially better matches (longer strings).
+ if (length > bestMatchLength
+ && textInLowerCase.startsWith(data[i].toLowerCase())) {
+ bestMatch = i;
+ bestMatchLength = length;
+ }
+ }
+ if (bestMatch >= 0) {
+ pos[0] = start + bestMatchLength;
+ }
+ return bestMatch;
+ }
+
+ /**
+ * Method parses a integer string and return integer value.
+ *
+ * @param text string being parsed
+ * @param pos parse position
+ *
+ * @return integer value
+ */
+ private int parseInt(String text, int[] pos) {
+ int ret = 0;
+ int ind = pos[0];
+ char ch = text.charAt(ind);
+ while (ch >= '0' && ch <= '9') {
+ ret = ret * 10 + (ch - '0');
+ ind++;
+ if (ind >= text.length()) {
+ break;
+ }
+ ch = text.charAt(ind);
+ }
+ if (ind > pos[0]) {
+ pos[0] = ind;
+ } else {
+ ret = -1;
+ }
+ return ret;
+ }
+
+ /**
+ * Method parses the input pattern string a generate a vector of pattern
+ * parts.
+ *
+ * @param pattern describe the format of date string that need to be parsed
+ */
+ private void parsePattern(String pattern) {
+ StringBuffer buf = new StringBuffer(32);
+ boolean inQuote = false;
+
+ for (int i = 0; i < pattern.length(); i++) {
+ char ch = pattern.charAt(i);
+
+ // Handle space, add literal part (if exist), and add space part.
+ if (ch == ' ') {
+ addPart(buf, 0);
+ buf.append(' ');
+ addPart(buf, 0);
+ while (i + 1 < pattern.length() && pattern.charAt(i + 1) == ' ') {
+ i++;
+ }
+ continue;
+ }
+
+ // If inside quote, except two quote connected, just copy or exit.
+ if (inQuote) {
+ if (ch == '\'') {
+ if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') {
+ // Quote appeared twice continuously, interpret as one quote.
+ buf.append(ch);
+ ++i;
+ } else {
+ inQuote = false;
+ }
+ } else {
+ // Literal.
+ buf.append(ch);
+ }
+ continue;
+ }
+
+ // Outside quote now.
+ if (PATTERN_CHARS.indexOf(ch) > 0) {
+ addPart(buf, 0);
+ buf.append(ch);
+ int count = getNextCharCountInPattern(pattern, i);
+ addPart(buf, count);
+ i += count - 1;
+ continue;
+ }
+
+ // Two consecutive quotes is a quote literal, inside or outside of quotes.
+ if (ch == '\'') {
+ if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') {
+ buf.append('\'');
+ i++;
+ } else {
+ inQuote = true;
+ }
+ } else {
+ buf.append(ch);
+ }
+ }
+
+ addPart(buf, 0);
+
+ identifyAbutStart();
+ }
+
+ /**
+ * Method parses time zone offset.
+ *
+ * @param text the time text to be parsed
+ * @param pos Parse position
+ * @param cal DateRecord object that holds parsed value
+ *
+ * @return <code>true</code> if parsing successful, otherwise
+ * <code>false</code>
+ */
+ private boolean parseTimeZoneOffset(String text, int[] pos, DateRecord cal) {
+ if (pos[0] >= text.length()) {
+ cal.setTzOffset(0);
+ return true;
+ }
+
+ int sign;
+ switch (text.charAt(pos[0])) {
+ case '+':
+ sign = 1;
+ break;
+ case '-':
+ sign = -1;
+ break;
+ default:
+ cal.setTzOffset(0);
+ return true;
+ }
+ ++(pos[0]);
+
+ // Look for hours:minutes or hhmm.
+ int st = pos[0];
+ int value = parseInt(text, pos);
+ if (value == 0 && pos[0] == st) {
+ return false;
+ }
+
+ int offset;
+ if (pos[0] < text.length() && text.charAt(pos[0]) == ':') {
+ // This is the hours:minutes case.
+ offset = value * MINUTES_PER_HOUR;
+ ++(pos[0]);
+ st = pos[0];
+ value = parseInt(text, pos);
+ if (value == 0 && pos[0] == st) {
+ return false;
+ }
+ offset += value;
+ } else {
+ // This is the hhmm case.
+ offset = value;
+ // Assume "-23".."+23" refers to hours.
+ if (offset < 24 && (pos[0] - st) <= 2) {
+ offset *= MINUTES_PER_HOUR;
+ } else {
+ offset = offset % 100 + offset / 100 * MINUTES_PER_HOUR;
+ }
+ }
+
+ offset *= sign;
+ cal.setTzOffset(-offset);
+ return true;
+ }
+
+ /**
+ * Method skips space in the string as pointed by pos.
+ *
+ * @param text input string
+ * @param pos where skip start, and return back where skip stop
+ */
+ private void skipSpace(String text, int[] pos) {
+ while (pos[0] < text.length()
+ && WHITE_SPACE.indexOf(text.charAt(pos[0])) >= 0) {
+ ++(pos[0]);
+ }
+ }
+
+ /**
+ * Formats a single field according to pattern specified.
+ *
+ * @param buf where formatted string will be appended to
+ * @param ch pattern for this field
+ * @param count number of time pattern char repeats; this controls how a field
+ * should be formatted
+ * @param date hold the date object to be formatted
+ *
+ * @return <code>true</code> if pattern valid, otherwise <code>false</code>
+ */
+ private boolean subFormat(StringBuffer buf, char ch, int count, Date date) {
+ switch (ch) {
+ case 'G':
+ formatEra(buf, count, date);
+ break;
+ case 'y':
+ formatYear(buf, count, date);
+ break;
+ case 'M':
+ formatMonth(buf, count, date);
+ break;
+ case 'k':
+ format24Hours(buf, count, date);
+ break;
+ case 'S':
+ formatFractionalSeconds(buf, count, date);
+ break;
+ case 'E':
+ formatDayOfWeek(buf, count, date);
+ break;
+ case 'a':
+ formatAmPm(buf, count, date);
+ break;
+ case 'h':
+ format1To12Hours(buf, count, date);
+ break;
+ case 'K':
+ format0To11Hours(buf, count, date);
+ break;
+ case 'H':
+ format0To23Hours(buf, count, date);
+ break;
+ case 'c':
+ formatStandaloneDay(buf, count, date);
+ break;
+ case 'L':
+ formatStandaloneMonth(buf, count, date);
+ break;
+ case 'Q':
+ formatQuarter(buf, count, date);
+ break;
+ case 'd':
+ formatDate(buf, count, date);
+ break;
+ case 'm':
+ formatMinutes(buf, count, date);
+ break;
+ case 's':
+ formatSeconds(buf, count, date);
+ break;
+ case 'z':
+ case 'v':
+ appendGMT(buf, date);
+ break;
+ case 'Z':
+ formatTimeZoneRFC(buf, count, date);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Converts one field of the input string into a numeric field value. Returns
+ * <code>false</code> if failed.
+ *
+ * @param text the time text to be parsed
+ * @param pos Parse position
+ * @param part the pattern part for this field
+ * @param digitCount when greater than 0, numeric parsing must obey the count
+ * @param cal DateRecord object that will hold parsed value
+ *
+ * @return <code>true</code> if parsing successful
+ */
+ private boolean subParse(String text, int[] pos, PatternPart part,
+ int digitCount, DateRecord cal) {
+
+ skipSpace(text, pos);
+
+ int start = pos[0];
+ char ch = part.text.charAt(0);
+
+ // Parse integer value if it is a numeric field.
+ int value = -1; // initialize value to be -1,
+ if (isNumeric(part)) {
+ if (digitCount > 0) {
+ if ((start + digitCount) > text.length()) {
+ return false;
+ }
+ value = parseInt(text.substring(0, start + digitCount), pos);
+ } else {
+ value = parseInt(text, pos);
+ }
+ }
+
+ switch (ch) {
+ case 'G': // 'G' - ERA
+ value = matchString(text, start, dateTimeConstants.eras(), pos);
+ cal.setEra(value);
+ return true;
+ case 'M': // 'M' - MONTH
+ return subParseMonth(text, pos, cal, value, start);
+ case 'E':
+ return subParseDayOfWeek(text, pos, start, cal);
+ case 'a': // 'a' - AM_PM
+ value = matchString(text, start, dateTimeConstants.ampms(), pos);
+ cal.setAmpm(value);
+ return true;
+ case 'y': // 'y' - YEAR
+ return subParseYear(text, pos, start, value, part, cal);
+ case 'd': // 'd' - DATE
+ cal.setDayOfMonth(value);
+ return true;
+ case 'S': // 'S' - FRACTIONAL_SECOND
+ return subParseFractionalSeconds(value, start, pos[0], cal);
+ case 'h': // 'h' - HOUR (1..12)
+ if (value == 12) {
+ value = 0;
+ }
+ // fall through
+ case 'K': // 'K' - HOUR (0..11)
+ case 'H': // 'H' - HOUR_OF_DAY (0..23)
+ cal.setHours(value);
+ return true;
+ case 'k': // 'k' - HOUR_OF_DAY (1..24)
+ cal.setHours(value);
+ return true;
+ case 'm': // 'm' - MINUTE
+ cal.setMinutes(value);
+ return true;
+ case 's': // 's' - SECOND
+ cal.setSeconds(value);
+ return true;
+
+ case 'z': // 'z' - ZONE_OFFSET
+ case 'Z': // 'Z' - TIMEZONE_RFC
+ case 'v': // 'v' - TIMEZONE_GENERIC
+ return subParseTimeZoneInGMT(text, start, pos, cal);
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Method subParseDayOfWeek parses day of the week field.
+ *
+ * @param text the time text to be parsed
+ * @param pos Parse position
+ * @param start from where parse start
+ * @param cal DateRecord object that holds parsed value
+ *
+ * @return <code>true</code> if parsing successful, otherwise
+ * <code>false</code>
+ */
+ private boolean subParseDayOfWeek(String text, int[] pos, int start,
+ DateRecord cal) {
+ int value;
+ // 'E' - DAY_OF_WEEK
+ // Want to be able to parse both short and long forms.
+ // Try count == 4 (DDDD) first:
+ value = matchString(text, start, dateTimeConstants.weekdays(), pos);
+ if (value < 0) {
+ value = matchString(text, start, dateTimeConstants.shortWeekdays(), pos);
+ }
+ if (value < 0) {
+ return false;
+ }
+ cal.setDayOfWeek(value);
+ return true;
+ }
+
+ /**
+ * Method subParseFractionalSeconds parses fractional seconds field.
+ *
+ * @param value parsed numberic value
+ * @param start
+ * @param end parse position
+ * @param cal DateRecord object that holds parsed value
+ * @return <code>true</code> if parsing successful, otherwise
+ * <code>false</code>
+ */
+ private boolean subParseFractionalSeconds(int value, int start, int end,
+ DateRecord cal) {
+ // Fractional seconds left-justify.
+ int i = end - start;
+ if (i < 3) {
+ while (i < 3) {
+ value *= 10;
+ i++;
+ }
+ } else {
+ int a = 1;
+ while (i > 3) {
+ a *= 10;
+ i--;
+ }
+ value = (value + (a >> 1)) / a;
+ }
+ cal.setMilliseconds(value);
+ return true;
+ }
+
+ /**
+ * Method subParseMonth parses Month field.
+ *
+ * @param text the time text to be parsed
+ * @param pos Parse position
+ * @param cal DateRecord object that will hold parsed value
+ * @param value numeric value if this field is expressed using numberic
+ * pattern
+ * @param start from where parse start
+ *
+ * @return <code>true</code> if parsing successful
+ */
+ private boolean subParseMonth(String text, int[] pos, DateRecord cal,
+ int value, int start) {
+ // When month is symbols, i.e., MMM or MMMM, value will be -1.
+ if (value < 0) {
+ // Want to be able to parse both short and long forms.
+ // Try count == 4 first:
+ value = matchString(text, start, dateTimeConstants.months(), pos);
+ if (value < 0) { // count == 4 failed, now try count == 3.
+ value = matchString(text, start, dateTimeConstants.shortMonths(), pos);
+ }
+ if (value < 0) {
+ return false;
+ }
+ cal.setMonth(value);
+ return true;
+ } else {
+ cal.setMonth(value - 1);
+ return true;
+ }
+ }
+
+ /**
+ * Method parses GMT type timezone.
+ *
+ * @param text the time text to be parsed
+ * @param start from where parse start
+ * @param pos Parse position
+ * @param cal DateRecord object that holds parsed value
+ *
+ * @return <code>true</code> if parsing successful, otherwise
+ * <code>false</code>
+ */
+ private boolean subParseTimeZoneInGMT(String text, int start, int[] pos,
+ DateRecord cal) {
+ // First try to parse generic forms such as GMT-07:00. Do this first
+ // in case localized DateFormatZoneData contains the string "GMT"
+ // for a zone; in that case, we don't want to match the first three
+ // characters of GMT+/-HH:MM etc.
+
+ // For time zones that have no known names, look for strings
+ // of the form:
+ // GMT[+-]hours:minutes or
+ // GMT[+-]hhmm or
+ // GMT.
+ if (text.startsWith(GMT, start)) {
+ pos[0] = start + GMT.length();
+ return parseTimeZoneOffset(text, pos, cal);
+ }
+
+ // At this point, check for named time zones by looking through
+ // the locale data from the DateFormatZoneData strings.
+ // Want to be able to parse both short and long forms.
+ /*
+ * i = subParseZoneString(text, start, cal); if (i != 0) return i;
+ */
+
+ // As a last resort, look for numeric timezones of the form
+ // [+-]hhmm as specified by RFC 822. This code is actually
+ // a little more permissive than RFC 822. It will try to do
+ // its best with numbers that aren't strictly 4 digits long.
+ return parseTimeZoneOffset(text, pos, cal);
+ }
+
+ /**
+ * Method subParseYear parse year field. Year field is special because 1, two
+ * digit year need to be resolved. 2, we allow year to take a sign. 3, year
+ * field participate in abut processing. In my testing, negative year does not
+ * seem working due to JDK (or redpill implementation) limitation. It is not a
+ * big deal so we don't worry about it. But keep the logic here so that we
+ * might want to replace DateRecord with our a calendar class.
+ *
+ * @param text the time text to be parsed
+ * @param pos parse position
+ * @param start where this field star
+ * @param value integer value of yea
+ * @param part the pattern part for this field
+ * @param cal DateRecord object that will hold parsed value
+ *
+ * @return <code>true</code> if successful
+ */
+ private boolean subParseYear(String text, int[] pos, int start, int value,
+ PatternPart part, DateRecord cal) {
+ char ch = ' ';
+ if (value < 0) {
+ ch = text.charAt(pos[0]);
+ // Check if it is a sign.
+ if (ch != '+' && ch != '-') {
+ return false;
+ }
+ ++(pos[0]);
+ value = parseInt(text, pos);
+ if (value < 0) {
+ return false;
+ }
+ if (ch == '-') {
+ value = -value;
+ }
+ }
+
+ // no sign, only 2 digit was actually parsed, pattern say it has 2 digit.
+ if (ch == ' ' && (pos[0] - start) == 2 && part.count == 2) {
+ // Assume for example that the defaultCenturyStart is 6/18/1903.
+ // This means that two-digit years will be forced into the range
+ // 6/18/1903 to 6/17/2003. As a result, years 00, 01, and 02
+ // correspond to 2000, 2001, and 2002. Years 04, 05, etc. correspond
+ // to 1904, 1905, etc. If the year is 03, then it is 2003 if the
+ // other fields specify a date before 6/18, or 1903 if they specify a
+ // date afterwards. As a result, 03 is an ambiguous year. All other
+ // two-digit years are unambiguous.
+ Date date = new Date();
+ int defaultCenturyStartYear = date.getYear() + 1900 - 80;
+ int ambiguousTwoDigitYear = defaultCenturyStartYear % 100;
+ cal.setAmbiguousYear(value == ambiguousTwoDigitYear);
+ value += (defaultCenturyStartYear / 100) * 100
+ + (value < ambiguousTwoDigitYear ? 100 : 0);
+ }
+ cal.setYear(value);
+ return true;
+ };
+
+ /**
+ * Formats a number with the specified minimum number of digits, using zero to
+ * fill the gap.
+ *
+ * @param buf where zero padded string will be written to
+ * @param value the number value being formatted
+ * @param minWidth minimum width of the formatted string; zero will be padded
+ * to reach this width
+ */
+ private void zeroPaddingNumber(StringBuffer buf, int value, int minWidth) {
+ int b = NUMBER_BASE;
+ for (int i = 0; i < minWidth - 1; i++) {
+ if (value < b) {
+ buf.append('0');
+ }
+ b *= NUMBER_BASE;
+ }
+ buf.append(Integer.toString(value));
+ }
+}
diff --git a/user/src/com/google/gwt/i18n/client/constants/DateTimeConstants.java b/user/src/com/google/gwt/i18n/client/constants/DateTimeConstants.java
index a844990..81b695e 100644
--- a/user/src/com/google/gwt/i18n/client/constants/DateTimeConstants.java
+++ b/user/src/com/google/gwt/i18n/client/constants/DateTimeConstants.java
@@ -1,48 +1,48 @@
-/*
- * Copyright 2007 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.i18n.client.constants;
-
-import com.google.gwt.i18n.client.Constants;
-
-/**
- * DateTimeConstants class encapsulate a collection of DateTime formatting
- * symbols for use with DateTime format and parse services. This class extends
- * GWT's Constants class. The actual symbol collections are defined in a set
- * of property files named like "DateTimeConstants_xx.properties". GWT will
- * will perform late binding to the property file that specific to user's
- * locale.
- */
-public interface DateTimeConstants extends Constants {
- String[] ampms();
- String[] dateFormats();
- String[] eraNames ();
- String[] eras ();
- String[] months ();
- String[] narrowMonths ();
- String[] narrowWeekdays();
- String[] quarters ();
- String[] shortMonths();
- String[] shortQuarters();
- String[] shortWeekdays();
- String[] standaloneMonths();
- String[] standaloneNarrowMonths();
- String[] standaloneNarrowWeekdays();
- String[] standaloneShortMonths();
- String[] standaloneShortWeekdays ();
- String[] standaloneWeekdays();
- String[] timeFormats();
- String[] weekdays();
-}
+/*
+ * Copyright 2007 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.i18n.client.constants;
+
+import com.google.gwt.i18n.client.Constants;
+
+/**
+ * DateTimeConstants class encapsulate a collection of DateTime formatting
+ * symbols for use with DateTime format and parse services. This class extends
+ * GWT's Constants class. The actual symbol collections are defined in a set
+ * of property files named like "DateTimeConstants_xx.properties". GWT will
+ * will perform late binding to the property file that specific to user's
+ * locale.
+ */
+public interface DateTimeConstants extends Constants {
+ String[] ampms();
+ String[] dateFormats();
+ String[] eraNames ();
+ String[] eras ();
+ String[] months ();
+ String[] narrowMonths ();
+ String[] narrowWeekdays();
+ String[] quarters ();
+ String[] shortMonths();
+ String[] shortQuarters();
+ String[] shortWeekdays();
+ String[] standaloneMonths();
+ String[] standaloneNarrowMonths();
+ String[] standaloneNarrowWeekdays();
+ String[] standaloneShortMonths();
+ String[] standaloneShortWeekdays ();
+ String[] standaloneWeekdays();
+ String[] timeFormats();
+ String[] weekdays();
+}
diff --git a/user/src/com/google/gwt/user/client/ImageBundle.java b/user/src/com/google/gwt/user/client/ImageBundle.java
index f541a48..753babc 100644
--- a/user/src/com/google/gwt/user/client/ImageBundle.java
+++ b/user/src/com/google/gwt/user/client/ImageBundle.java
@@ -1,138 +1,138 @@
-/*
- * Copyright 2007 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;
-
-/**
- * A tag interface that is used in the generation of image bundles. An image
- * bundle is a composition of multiple images into a single large image, along
- * with an interface for accessing a specific image's
- * {@link com.google.gwt.user.client.ui.AbstractImagePrototype prototype}
- * from within the composition. Using <code>GWT.create(<i>class</i>)</code> to
- * instantiate a type that directly extends or implements <code>ImageBundle</code>
- * generates an image bundle.
- *
- * <p>
- * To create and use an image bundle, users must extend the
- * <code>ImageBundle</code> interface, and add a method declaration for each
- * image that is to be part of the bundle.
- * </p>
- *
- * <p>
- * Methods must have a return type of
- * {@link com.google.gwt.user.client.ui.AbstractImagePrototype AbstractImagePrototype},
- * and take no parameters. The image name can be specified by using the
- * <code>gwt.resource</code> metadata tag. Valid image name extensions are
- * <code>png</code>, <code>gif</code>, or <code>jpg</code>. If the image name
- * contains '/' characters, it is assumed to be the name of a resource
- * on the classpath, formatted as would be expected by
- * <code>ClassLoader.getResource(String)</code>. Otherwise, the image must
- * be located in the same package as the user-defined image bundle.
- * </p>
- *
- * <p>
- * An image bundle that uses the metadata tag to specify image names might look
- * something like this:
- *
- * <pre class="code">
- * public interface MyImageBundle extends ImageBundle {
- *
- * // The metadata tag contains no '/' characters, so btn_submit_icon.gif
- * // must be located in the same package as MyImageBundle.
- *
- * /**
- * * @gwt.resource btn_submit_icon.gif
- * */
- * public AbstractImagePrototype submitButtonIcon();
- *
- * // btn_cancel_icon.png must be located in the package com.mycompany.myapp.icons,
- * // and this package must be on the classpath.
- *
- * /**
- * * @gwt.resource com/mycompany/myapp/icons/btn_cancel_icon.png
- * */
- * public AbstractImagePrototype cancelButtonIcon();
- *
- * }
- * </pre>
- *
- * </p>
- *
- * <p>
- * Another way to specify the image name is to omit the metadata tag, and name
- * the method the same as the image name, excluding the extension. When the
- * image name is provided in this manner, the image name's extension is assumed
- * to be either <code>png</code>, <code>gif</code>, or <code>jpg</code>, and the
- * image location must be in the same package as the user-defined image bundle.
- * In the event that there are multiple image files that have the same name with
- * different extensions, the order of extension precedence is <code>png</code>,
- * <code>gif</code>, <code>jpg</code>. A conversion of the example above to use
- * the method names as the image names would look like this:
- *
- * <pre class="code">
- * public interface MyImageBundle extends ImageBundle {
- *
- * // One of btn_submit_icon.png, btn_submit_icon.gif, or btn_submit_icon.jpg
- * // must be located in the same package as MyImageBundle.
- * // Notice that the gwt.resource metadata tag is not present.
- *
- * public void btn_submit_icon();
- *
- * // Since the image is not located in the same package as MyImageBundle, we
- * // have to use the metadata tag to specify the image name
- *
- * /**
- * * @gwt.resource com/mycompany/myapp/icons/btn_cancel_icon.png
- * */
- * public void cancelButtonIcon();
- *
- * }
- * </pre>
- *
- * </p>
- *
- * <p>
- * Here is how MyImageBundle might be used in an application:
- *
- * <pre class="code">
- * ...
- *
- * // Create a new instance of MyImageBundle using GWT.create.
- * // This only needs to be done once - a reference to myImageBundle should
- * // be kept for use by other parts of the application.
- * MyImageBundle myImageBundle = (MyImageBundle) GWT.create(MyImageBundle.class);
- *
- * // Retrieve the image prototypes from myImageBundle.
- * AbstractImagePrototype submitButtonImgPrototype = myImageBundle.btn_submit_icon();
- * AbstractImagePrototype cancelButtonImgPrototype = myImageBundle.cancelButtonIcon();
- *
- * // Add the images that are created based on the prototypes to the panel.
- * panel.add(submitButtonImgPrototype.createImage());
- * panel.add(cancelButtonImgPrototype.createImage());
- *
- * ...
- * </pre>
- *
- * </p>
- *
- * <h3>For More Information</h3>
- * See the GWT Developer Guide for an introduction to image bundles.
- * @see com.google.gwt.user.client.ui.AbstractImagePrototype
- * @see com.google.gwt.user.client.ui.Image#Image(String, int, int, int, int)
- * @see com.google.gwt.user.client.ui.Image#setVisibleRect(int, int, int, int)
- * @see com.google.gwt.user.client.ui.Image#setUrlAndVisibleRect(String, int, int, int, int)
- */
-public interface ImageBundle {
-}
+/*
+ * Copyright 2007 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;
+
+/**
+ * A tag interface that is used in the generation of image bundles. An image
+ * bundle is a composition of multiple images into a single large image, along
+ * with an interface for accessing a specific image's
+ * {@link com.google.gwt.user.client.ui.AbstractImagePrototype prototype}
+ * from within the composition. Using <code>GWT.create(<i>class</i>)</code> to
+ * instantiate a type that directly extends or implements <code>ImageBundle</code>
+ * generates an image bundle.
+ *
+ * <p>
+ * To create and use an image bundle, users must extend the
+ * <code>ImageBundle</code> interface, and add a method declaration for each
+ * image that is to be part of the bundle.
+ * </p>
+ *
+ * <p>
+ * Methods must have a return type of
+ * {@link com.google.gwt.user.client.ui.AbstractImagePrototype AbstractImagePrototype},
+ * and take no parameters. The image name can be specified by using the
+ * <code>gwt.resource</code> metadata tag. Valid image name extensions are
+ * <code>png</code>, <code>gif</code>, or <code>jpg</code>. If the image name
+ * contains '/' characters, it is assumed to be the name of a resource
+ * on the classpath, formatted as would be expected by
+ * <code>ClassLoader.getResource(String)</code>. Otherwise, the image must
+ * be located in the same package as the user-defined image bundle.
+ * </p>
+ *
+ * <p>
+ * An image bundle that uses the metadata tag to specify image names might look
+ * something like this:
+ *
+ * <pre class="code">
+ * public interface MyImageBundle extends ImageBundle {
+ *
+ * // The metadata tag contains no '/' characters, so btn_submit_icon.gif
+ * // must be located in the same package as MyImageBundle.
+ *
+ * /**
+ * * @gwt.resource btn_submit_icon.gif
+ * */
+ * public AbstractImagePrototype submitButtonIcon();
+ *
+ * // btn_cancel_icon.png must be located in the package com.mycompany.myapp.icons,
+ * // and this package must be on the classpath.
+ *
+ * /**
+ * * @gwt.resource com/mycompany/myapp/icons/btn_cancel_icon.png
+ * */
+ * public AbstractImagePrototype cancelButtonIcon();
+ *
+ * }
+ * </pre>
+ *
+ * </p>
+ *
+ * <p>
+ * Another way to specify the image name is to omit the metadata tag, and name
+ * the method the same as the image name, excluding the extension. When the
+ * image name is provided in this manner, the image name's extension is assumed
+ * to be either <code>png</code>, <code>gif</code>, or <code>jpg</code>, and the
+ * image location must be in the same package as the user-defined image bundle.
+ * In the event that there are multiple image files that have the same name with
+ * different extensions, the order of extension precedence is <code>png</code>,
+ * <code>gif</code>, <code>jpg</code>. A conversion of the example above to use
+ * the method names as the image names would look like this:
+ *
+ * <pre class="code">
+ * public interface MyImageBundle extends ImageBundle {
+ *
+ * // One of btn_submit_icon.png, btn_submit_icon.gif, or btn_submit_icon.jpg
+ * // must be located in the same package as MyImageBundle.
+ * // Notice that the gwt.resource metadata tag is not present.
+ *
+ * public void btn_submit_icon();
+ *
+ * // Since the image is not located in the same package as MyImageBundle, we
+ * // have to use the metadata tag to specify the image name
+ *
+ * /**
+ * * @gwt.resource com/mycompany/myapp/icons/btn_cancel_icon.png
+ * */
+ * public void cancelButtonIcon();
+ *
+ * }
+ * </pre>
+ *
+ * </p>
+ *
+ * <p>
+ * Here is how MyImageBundle might be used in an application:
+ *
+ * <pre class="code">
+ * ...
+ *
+ * // Create a new instance of MyImageBundle using GWT.create.
+ * // This only needs to be done once - a reference to myImageBundle should
+ * // be kept for use by other parts of the application.
+ * MyImageBundle myImageBundle = (MyImageBundle) GWT.create(MyImageBundle.class);
+ *
+ * // Retrieve the image prototypes from myImageBundle.
+ * AbstractImagePrototype submitButtonImgPrototype = myImageBundle.btn_submit_icon();
+ * AbstractImagePrototype cancelButtonImgPrototype = myImageBundle.cancelButtonIcon();
+ *
+ * // Add the images that are created based on the prototypes to the panel.
+ * panel.add(submitButtonImgPrototype.createImage());
+ * panel.add(cancelButtonImgPrototype.createImage());
+ *
+ * ...
+ * </pre>
+ *
+ * </p>
+ *
+ * <h3>For More Information</h3>
+ * See the GWT Developer Guide for an introduction to image bundles.
+ * @see com.google.gwt.user.client.ui.AbstractImagePrototype
+ * @see com.google.gwt.user.client.ui.Image#Image(String, int, int, int, int)
+ * @see com.google.gwt.user.client.ui.Image#setVisibleRect(int, int, int, int)
+ * @see com.google.gwt.user.client.ui.Image#setUrlAndVisibleRect(String, int, int, int, int)
+ */
+public interface ImageBundle {
+}
diff --git a/user/src/com/google/gwt/user/client/ui/AbstractImagePrototype.java b/user/src/com/google/gwt/user/client/ui/AbstractImagePrototype.java
index 8656716..3490f58 100644
--- a/user/src/com/google/gwt/user/client/ui/AbstractImagePrototype.java
+++ b/user/src/com/google/gwt/user/client/ui/AbstractImagePrototype.java
@@ -1,70 +1,70 @@
-/*
- * Copyright 2007 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;
-
-/**
- * An opaque representation of a particular image such that the image can be
- * accessed either as an HTML fragment or as an {@link Image} object. An image
- * protype can be thought of as an abstract image factory with additional
- * capabilities.
- *
- * <p>
- * The {@link #applyTo(Image)} method provides an efficient way to replace the
- * contents of an existing <code>Image</code>. This is useful in cases where
- * an image changes its appearance based on a user's action. Instead of creating
- * two <code>Image</code> objects then alternately hiding/showing them, one
- * can use the {@link #applyTo(Image)} method of two
- * <code>AbstractImagePrototype</code> objects to transform a single
- * <code>Image</code> object between two (or more) visual representations. The
- * use of <code>AbstractImagePrototypes</code> results in an cleaner and more
- * efficient implementation.
- * </p>
- *
- * <p>
- * This class is also a useful way to encapsulate complex HTML that represents
- * an image without actually instantiating <code>Image</code> objects. When
- * constructing large HTML fragments, especially those that contain many images,
- * {@link #getHTML()} can be much more efficient.
- * </p>
- */
-public abstract class AbstractImagePrototype {
-
- /**
- * Transforms an existing {@link Image} into the image represented by this
- * prototype.
- *
- * @param image the instance to be transformed to match this prototype
- */
- public abstract void applyTo(Image image);
-
- /**
- * Creates a new {@link Image} instance based on the image represented by this
- * prototype.
- *
- * @return a new <code>Image</code> based on this prototype
- */
- public abstract Image createImage();
-
- /**
- * Gets an HTML fragment that displays the image represented by this
- * prototype. The HTML returned is not necessarily a simple
- * <code><img></code> element. It may be a more complex structure that
- * should be treated opaquely.
- *
- * @return the HTML representation of this prototype
- */
- public abstract String getHTML();
-}
+/*
+ * Copyright 2007 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;
+
+/**
+ * An opaque representation of a particular image such that the image can be
+ * accessed either as an HTML fragment or as an {@link Image} object. An image
+ * protype can be thought of as an abstract image factory with additional
+ * capabilities.
+ *
+ * <p>
+ * The {@link #applyTo(Image)} method provides an efficient way to replace the
+ * contents of an existing <code>Image</code>. This is useful in cases where
+ * an image changes its appearance based on a user's action. Instead of creating
+ * two <code>Image</code> objects then alternately hiding/showing them, one
+ * can use the {@link #applyTo(Image)} method of two
+ * <code>AbstractImagePrototype</code> objects to transform a single
+ * <code>Image</code> object between two (or more) visual representations. The
+ * use of <code>AbstractImagePrototypes</code> results in an cleaner and more
+ * efficient implementation.
+ * </p>
+ *
+ * <p>
+ * This class is also a useful way to encapsulate complex HTML that represents
+ * an image without actually instantiating <code>Image</code> objects. When
+ * constructing large HTML fragments, especially those that contain many images,
+ * {@link #getHTML()} can be much more efficient.
+ * </p>
+ */
+public abstract class AbstractImagePrototype {
+
+ /**
+ * Transforms an existing {@link Image} into the image represented by this
+ * prototype.
+ *
+ * @param image the instance to be transformed to match this prototype
+ */
+ public abstract void applyTo(Image image);
+
+ /**
+ * Creates a new {@link Image} instance based on the image represented by this
+ * prototype.
+ *
+ * @return a new <code>Image</code> based on this prototype
+ */
+ public abstract Image createImage();
+
+ /**
+ * Gets an HTML fragment that displays the image represented by this
+ * prototype. The HTML returned is not necessarily a simple
+ * <code><img></code> element. It may be a more complex structure that
+ * should be treated opaquely.
+ *
+ * @return the HTML representation of this prototype
+ */
+ public abstract String getHTML();
+}
diff --git a/user/src/com/google/gwt/user/client/ui/CustomButton.java b/user/src/com/google/gwt/user/client/ui/CustomButton.java
index 7728ccc..3694fa4 100644
--- a/user/src/com/google/gwt/user/client/ui/CustomButton.java
+++ b/user/src/com/google/gwt/user/client/ui/CustomButton.java
@@ -1,838 +1,838 @@
-/*
- * Copyright 2007 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.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-
-/**
- * Custom Button is a base button class with built in support for a set number
- * of button faces.
- *
- * Each face has its own style modifier. For example, the state for down and
- * hovering is assigned the CSS modifier <i>down-hovering</i>. So, if the
- * button's overall style name is <i>gwt-PushButton</i> then when showing the
- * <code>down-hovering</code> face, the button's style is <i>
- * gwt-PushButton-down-hovering</i>.
- *
- * <p>
- * Each button face can be assigned is own image, text, or html contents. If no
- * content is defined for a face, then the face will use the contents of another
- * face. For example, if <code>down-hovering</code> does not have defined
- * contents, it will use the contents defined by the <code>down</code> face.
- * </p>
- *
- * <p>
- * The supported faces are defined below:
- * </p>
- * <p>
- * <table border="4">
- * <tr>
- *
- * <td><b>CSS style name</b></td>
- * <td><b>Getter method</b></td>
- * <td><b>description of face</b></td>
- * <td><b>defaults to contents of face</b></td>
- * </tr>
- *
- * <tr>
- * <td>up</td>
- * <td> {@link #getUpFace()} </td>
- * <td>face shown when button is up</td>
- * <td> none</td>
- * </tr>
- *
- * <tr>
- * <td>down</td>
- * <td> {@link #getDownFace()} </td>
- * <td>face shown when button is down</td>
- * <td> up </td>
- * </tr>
- *
- * <tr>
- * <td>up-hovering</td>
- * <td> {@link #getUpHoveringFace()} </td>
- * <td>face shown when button is up and hovering</td>
- * <td> up </td>
- * </tr>
- *
- * <tr>
- * <td>up-disabled</td>
- * <td> {@link #getUpDisabledFace()} </td>
- * <td>face shown when button is up and disabled</td>
- * <td> up</td>
- * </tr>
- *
- * <tr>
- * <td>down-hovering</td>
- * <td> {@link #getDownHoveringFace()} </td>
- * <td>face shown when button is down and hovering</td>
- * <td> down</td>
- * </tr>
- *
- * <tr>
- * <td>down-disabled</td>
- * <td> {@link #getDownDisabledFace()} </td>
- * <td>face shown when button is down and disabled</td>
- * <td>down</td>
- * </tr>
- * </table>
- * </p>
- *
- */
-public abstract class CustomButton extends ButtonBase implements
- SourcesKeyboardEvents {
- /**
- * Represents a button's face. Each face is associated with its own style
- * modifier and, optionally, its own contents html, text, or image.
- */
- public abstract class Face implements HasHTML, HasText {
- private static final String STYLENAME_HTML_FACE = "html-face";
- private final Face delegateTo;
- private Element face;
-
- /**
- * Constructor for <code>Face</code>. Creates a new face that delegates
- * to the supplied face.
- *
- * @param delegateTo default content provider
- */
- private Face(Face delegateTo) {
- this.delegateTo = delegateTo;
- }
-
- /**
- * Gets the face's contents as html.
- *
- * @return face's contents as html
- *
- */
- public String getHTML() {
- return DOM.getInnerHTML(getFace());
- }
-
- /**
- * Gets the face's contents as text.
- *
- * @return face's contents as text
- *
- */
- public String getText() {
- return DOM.getInnerText(getFace());
- }
-
- /**
- * Set the face's contents as html.
- *
- * @param html html to set as face's contents html
- *
- */
- public void setHTML(String html) {
- face = DOM.createDiv();
- UIObject.setStyleName(face, STYLENAME_HTML_FACE, true);
- DOM.setInnerHTML(face, html);
- updateButtonFace();
- }
-
- /**
- * Set the face's contents as an image.
- *
- * @param image image to set as face contents
- */
- public final void setImage(Image image) {
- face = image.getElement();
- updateButtonFace();
- }
-
- /**
- * Sets the face's contents as text.
- *
- * @param text text to set as face's contents
- */
- public final void setText(String text) {
- face = DOM.createDiv();
- UIObject.setStyleName(face, STYLENAME_HTML_FACE, true);
- DOM.setInnerText(face, text);
- updateButtonFace();
- }
-
- public final String toString() {
- return this.getName();
- }
-
- /**
- * Gets the ID associated with this face. This will be a bitwise and of all
- * of the attributes that comprise this face.
- */
- abstract int getFaceID();
-
- /**
- * Get the name of the face. This property is also used as a modifier on the
- * <code>CustomButton</code> style. <p/> For instance, if the
- * <code>CustomButton</code> style is "gwt-PushButton" and the face name
- * is "up", then the CSS class name will be "gwt-PushButton-up".
- *
- * @return the face's name
- */
- abstract String getName();
-
- /**
- * Gets the contents associated with this face.
- */
- private Element getFace() {
- if (face == null) {
- if (delegateTo == null) {
- // provide a default face as none was supplied.
- face = DOM.createDiv();
- return face;
- } else {
- return delegateTo.getFace();
- }
- } else {
- return face;
- }
- }
-
- private void updateButtonFace() {
- if (curFace != null && curFace.getFace() == this.getFace()) {
- setCurrentFaceElement(face);
- }
- }
- }
-
- private static final String STYLENAME_DEFAULT = "gwt-CustomButton";
-
- /**
- * Pressed Attribute bit.
- */
- private static final int DOWN_ATTRIBUTE = 1;
-
- /**
- * Hovering Attribute bit.
- */
- private static final int HOVERING_ATTRIBUTE = 2;
-
- /**
- * Disabled Attribute bit.
- */
- private static final int DISABLED_ATTRIBUTE = 4;
-
- /**
- * ID for up face.
- */
- private static final int UP = 0;
-
- /**
- * ID for down face.
- */
- private static final int DOWN = DOWN_ATTRIBUTE;
-
- /**
- * ID for upHovering face.
- */
- private static final int UP_HOVERING = HOVERING_ATTRIBUTE;
-
- /**
- * ID for downHovering face.
- */
- private static final int DOWN_HOVERING = DOWN_ATTRIBUTE | HOVERING_ATTRIBUTE;
-
- /**
- * ID for upDisabled face.
- */
- private static final int UP_DISABLED = DISABLED_ATTRIBUTE;
-
- /**
- * ID for downDisabled face.
- */
- private static final int DOWN_DISABLED = DOWN | DISABLED_ATTRIBUTE;
-
- /**
- * Base style name. By default gwt-CustomButton.
- */
- private String baseStyleName;
-
- /**
- * The button's current face element.
- */
- private Element curFaceElement;
-
- /**
- * The button's current face.
- */
- private Face curFace;
-
- /**
- * Face for up.
- */
- private Face up;
-
- /**
- * Face for down.
- */
- private Face down;
-
- /**
- * Face for downHover.
- */
- private Face downHovering;
-
- /**
- * Face for upHover.
- */
- private Face upHovering;
-
- /**
- * Face for upDisabled.
- */
- private Face upDisabled;
-
- /**
- * Face for downDisabled.
- */
- private Face downDisabled;
-
- /**
- * Constructor for <code>CustomButton</code>.
- *
- * @param upImage image for the default (up) face of the button
- */
- public CustomButton(Image upImage) {
- this();
- getUpFace().setImage(upImage);
- }
-
- /**
- * Constructor for <code>CustomButton</code>.
- *
- * @param upImage image for the default (up) face of the button
- * @param downImage image for the down face of the button
- */
- public CustomButton(Image upImage, Image downImage) {
- this(upImage);
- getDownFace().setImage(downImage);
- }
-
- /**
- * Constructor for <code>CustomButton</code>.
- *
- * @param upImage image for the default (up) face of the button
- * @param downImage image for the down face of the button
- * @param listener clickListener
- */
- public CustomButton(Image upImage, Image downImage, ClickListener listener) {
- this(upImage, listener);
- getDownFace().setImage(downImage);
- }
-
- /**
- * Constructor for <code>CustomButton</code>.
- *
- * @param upImage image for the default (up) face of the button
- * @param listener the click listener
- */
- public CustomButton(Image upImage, ClickListener listener) {
- this(upImage);
- addClickListener(listener);
- }
-
- /**
- * Constructor for <code>CustomButton</code>.
- *
- * @param upText the text for the default (up) face of the button.
- */
- public CustomButton(String upText) {
- this();
- getUpFace().setText(upText);
- }
-
- /**
- * Constructor for <code>CustomButton</code>.
- *
- * @param upText the text for the default (up) face of the button
- * @param listener the click listener
- */
- public CustomButton(String upText, ClickListener listener) {
- this(upText);
- addClickListener(listener);
- }
-
- /**
- * Constructor for <code>CustomButton</code>.
- *
- * @param upText the text for the default (up) face of the button
- * @param downText the text for the down face of the button
- */
- public CustomButton(String upText, String downText) {
- this(upText);
- getDownFace().setText(downText);
- }
-
- /**
- * Constructor for <code>CustomButton</code>.
- *
- * @param upText the text for the default (up) face of the button
- * @param downText the text for the down face of the button
- * @param listener the click listener
- */
- public CustomButton(String upText, String downText, ClickListener listener) {
- this(upText, downText);
- addClickListener(listener);
- }
-
- /**
- * Constructor for <code>CustomButton</code>.
- */
- protected CustomButton() {
- // Use FocusPanel.impl rather than FocusWidget because only FocusPanel.impl
- // works across browsers to create a focusable element.
- super(FocusPanel.impl.createFocusable());
- sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.FOCUSEVENTS);
- setUpFace(createFace(null, "up", UP));
- setStyleName(STYLENAME_DEFAULT);
- }
-
- /**
- * Gets the downDisabled face of the button.
- *
- * @return the downDisabled face
- */
- public final Face getDownDisabledFace() {
- if (downDisabled == null) {
- setDownDisabledFace(createFace(getDownFace(), "down-disabled",
- DOWN_DISABLED));
- }
- return downDisabled;
- }
-
- /**
- * Gets the down face of the button.
- *
- * @return the down face
- */
- public final Face getDownFace() {
- if (down == null) {
- setDownFace(createFace(getUpFace(), "down", DOWN));
- }
- return down;
- }
-
- /**
- * Gets the downHovering face of the button.
- *
- * @return the downHovering face
- */
- public final Face getDownHoveringFace() {
- if (downHovering == null) {
- setDownHoveringFace(createFace(getDownFace(), "down-hovering",
- DOWN_HOVERING));
- }
- return downHovering;
- }
-
- /**
- * Gets the current face's html.
- *
- * @return current face's html
- */
- public String getHTML() {
- return getCurrentFace().getHTML();
- }
-
- /**
- * Gets the style name associated with the object. The actual CSS style name
- * for the button will be this name + "-" + current face name.
- *
- * @return the object's style name
- * @see #setStyleName(String)
- */
- public final String getStyleName() {
- return baseStyleName;
- }
-
- public int getTabIndex() {
- return FocusPanel.impl.getTabIndex(getElement());
- }
-
- /**
- * Gets the current face's text.
- *
- * @return current face's text
- */
- public String getText() {
- return getCurrentFace().getText();
- }
-
- /**
- * Gets the upDisabled face of the button.
- *
- * @return the upDisabled face
- */
- public final Face getUpDisabledFace() {
- if (upDisabled == null) {
- setUpDisabledFace(createFace(getUpFace(), "up-disabled", UP_DISABLED));
- }
- return upDisabled;
- }
-
- /**
- * Gets the up face of the button.
- *
- * @return the up face
- */
- public final Face getUpFace() {
- return up;
- }
-
- /**
- * Gets the upHovering face of the button.
- *
- * @return the upHovering face
- */
- public final Face getUpHoveringFace() {
- if (upHovering == null) {
- setUpHoveringFace(createFace(getUpFace(), "up-hovering", UP_HOVERING));
- }
- return upHovering;
- }
-
- public void onBrowserEvent(Event event) {
- // Should not act on button if disabled.
- if (isEnabled() == false) {
- // This can happen when events are bubbled up from non-disabled children
- return;
- }
-
- int type = DOM.eventGetType(event);
- switch (type) {
- case Event.ONMOUSEOUT:
- setHovering(false);
- break;
- case Event.ONMOUSEOVER:
- setHovering(true);
- break;
- }
- super.onBrowserEvent(event);
- }
-
- public void setAccessKey(char key) {
- FocusPanel.impl.setAccessKey(getElement(), key);
- }
-
- /**
- * Sets whether this button is enabled.
- *
- * @param enabled <code>true</code> to enable the button, <code>false</code>
- * to disable it
- */
- public final void setEnabled(boolean enabled) {
- if (isEnabled() != enabled) {
- toggleDisabled();
- super.setEnabled(enabled);
- }
- }
-
- public void setFocus(boolean focused) {
- if (focused) {
- FocusPanel.impl.focus(getElement());
- } else {
- FocusPanel.impl.blur(getElement());
- }
- }
-
- /**
- * Sets the current face's html.
- *
- * @param html html to set
- */
- public void setHTML(String html) {
- getCurrentFace().setHTML(html);
- }
-
- /**
- * Sets the style name associated with the object. The actual CSS style name
- * for the button will be this name + "-" + current face name.
- *
- * @param styleName the object's style name
- * @see #setStyleName(String)
- */
- public final void setStyleName(String styleName) {
- if (styleName == null) {
- throw new IllegalStateException("Cannot set the base style name to null");
- }
- if (curFace != null) {
- super.removeStyleName(getCSSStyleName());
- baseStyleName = styleName;
- super.addStyleName(getCSSStyleName());
- } else {
- baseStyleName = styleName;
- }
- }
-
- public void setTabIndex(int index) {
- FocusPanel.impl.setTabIndex(getElement(), index);
- }
-
- /**
- * Sets the current face's text.
- *
- * @param text text to set
- */
- public void setText(String text) {
- getCurrentFace().setText(text);
- }
-
- /**
- * Is this button down?
- *
- * @return <code>true</code> if the button is down
- */
- protected boolean isDown() {
- return (DOWN_ATTRIBUTE & getCurrentFace().getFaceID()) > 0;
- }
-
- /**
- * Overridden on attach to ensure that a button face has been chosen before
- * the button is displayed.
- */
- protected void onAttach() {
- finishSetup();
- super.onAttach();
- }
-
- /**
- * Sets whether this button is down.
- *
- * @param down <code>true</code> to press the button, <code>false</code>
- * otherwise
- */
- protected void setDown(boolean down) {
- if (down != isDown()) {
- toggleDown();
- }
- }
-
- /**
- * Common setup between constructors.
- */
- void finishSetup() {
- if (curFace == null) {
- setCurrentFace(getUpFace());
- }
- }
-
- /**
- * Gets the current face of the button.
- *
- * @return the current face
- */
-
- Face getCurrentFace() {
- /*
- * Implementation note: Package protected so we can use it when testing the
- * button.
- */
-
- finishSetup();
-
- return curFace;
- }
-
- /**
- * Is the mouse hovering over this button?
- *
- * @return <code>true</code> if the mouse is hovering
- */
- final boolean isHovering() {
- return (HOVERING_ATTRIBUTE & getCurrentFace().getFaceID()) > 0;
- }
-
- void setCurrentFace(Face newFace) {
- /*
- * Implementation note: default access for testing.
- */
- if (curFace != newFace) {
- if (curFace != null) {
- super.removeStyleName(getCSSStyleName());
- }
- curFace = newFace;
- setCurrentFaceElement(newFace.getFace());
- super.addStyleName(getCSSStyleName());
- }
- }
-
- /**
- * Sets whether this button is hovering.
- *
- * @param hovering is this button hovering?
- */
- final void setHovering(boolean hovering) {
- if (hovering != isHovering()) {
- toggleHover();
- }
- }
-
- /**
- * Toggle the up/down attribute.
- */
- void toggleDown() {
- int newFaceID = getCurrentFace().getFaceID() ^ DOWN_ATTRIBUTE;
- setCurrentFace(newFaceID);
- }
-
- private Face createFace(Face delegateTo, final String name, final int faceID) {
- return new Face(delegateTo) {
-
- public String getName() {
- return name;
- }
-
- int getFaceID() {
- return faceID;
- }
- };
- }
-
- /**
- * Gets the modified style name.
- *
- * @return the modified style name
- */
- private String getCSSStyleName() {
- return baseStyleName + "-" + curFace.getName();
- }
-
- private Face getFaceFromID(int id) {
- switch (id) {
- case DOWN:
- return getDownFace();
- case UP:
- return getUpFace();
- case DOWN_HOVERING:
- return getDownHoveringFace();
- case UP_HOVERING:
- return getUpHoveringFace();
- case UP_DISABLED:
- return getUpDisabledFace();
- case DOWN_DISABLED:
- return getDownDisabledFace();
- default:
- throw new IllegalStateException(id + " is not a known face id.");
- }
- }
-
- /**
- * Sets the current face based on the faceID.
- *
- * @param faceID sets the new face of the button
- */
- private void setCurrentFace(int faceID) {
- Face newFace = getFaceFromID(faceID);
- setCurrentFace(newFace);
- }
-
- private void setCurrentFaceElement(Element newFaceElement) {
- if (curFaceElement != newFaceElement) {
- if (curFaceElement != null) {
- DOM.removeChild(getElement(), curFaceElement);
- }
- curFaceElement = newFaceElement;
- DOM.appendChild(getElement(), curFaceElement);
- }
- }
-
- /**
- * Sets the downDisabled face of the button.
- *
- * @param downDisabled downDisabled face
- */
- private void setDownDisabledFace(Face downDisabled) {
- this.downDisabled = downDisabled;
- }
-
- /**
- * Sets the down face of the button.
- *
- * @param down the down face
- */
- private void setDownFace(Face down) {
- this.down = down;
- }
-
- /**
- * Sets the downHovering face of the button.
- *
- * @param downHovering hoverDown face
- */
- private void setDownHoveringFace(Face downHovering) {
- this.downHovering = downHovering;
- }
-
- /**
- * Sets the upDisabled face of the button.
- *
- * @param upDisabled upDisabled face
- */
- private void setUpDisabledFace(Face upDisabled) {
- this.upDisabled = upDisabled;
- }
-
- /**
- * Sets the up face of the button.
- *
- * @param up up face
- */
- private void setUpFace(Face up) {
- this.up = up;
- }
-
- /**
- * Sets the upHovering face of the button.
- *
- * @param upHovering upHovering face
- */
- private void setUpHoveringFace(Face upHovering) {
- this.upHovering = upHovering;
- }
-
- /**
- * Toggle the disabled attribute.
- */
- private void toggleDisabled() {
- // Toggle disabled.
- int newFaceID = getCurrentFace().getFaceID() ^ DISABLED_ATTRIBUTE;
-
- // Remove hovering.
- newFaceID &= ~HOVERING_ATTRIBUTE;
-
- // Sets the current face.
- setCurrentFace(newFaceID);
- }
-
- /**
- * Toggle the hovering attribute.
- */
- private void toggleHover() {
- // Toggle hovering.
- int newFaceID = getCurrentFace().getFaceID() ^ HOVERING_ATTRIBUTE;
-
- // Remove disabled.
- newFaceID &= ~DISABLED_ATTRIBUTE;
- setCurrentFace(newFaceID);
- }
-}
+/*
+ * Copyright 2007 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.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+
+/**
+ * Custom Button is a base button class with built in support for a set number
+ * of button faces.
+ *
+ * Each face has its own style modifier. For example, the state for down and
+ * hovering is assigned the CSS modifier <i>down-hovering</i>. So, if the
+ * button's overall style name is <i>gwt-PushButton</i> then when showing the
+ * <code>down-hovering</code> face, the button's style is <i>
+ * gwt-PushButton-down-hovering</i>.
+ *
+ * <p>
+ * Each button face can be assigned is own image, text, or html contents. If no
+ * content is defined for a face, then the face will use the contents of another
+ * face. For example, if <code>down-hovering</code> does not have defined
+ * contents, it will use the contents defined by the <code>down</code> face.
+ * </p>
+ *
+ * <p>
+ * The supported faces are defined below:
+ * </p>
+ * <p>
+ * <table border="4">
+ * <tr>
+ *
+ * <td><b>CSS style name</b></td>
+ * <td><b>Getter method</b></td>
+ * <td><b>description of face</b></td>
+ * <td><b>defaults to contents of face</b></td>
+ * </tr>
+ *
+ * <tr>
+ * <td>up</td>
+ * <td> {@link #getUpFace()} </td>
+ * <td>face shown when button is up</td>
+ * <td> none</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>down</td>
+ * <td> {@link #getDownFace()} </td>
+ * <td>face shown when button is down</td>
+ * <td> up </td>
+ * </tr>
+ *
+ * <tr>
+ * <td>up-hovering</td>
+ * <td> {@link #getUpHoveringFace()} </td>
+ * <td>face shown when button is up and hovering</td>
+ * <td> up </td>
+ * </tr>
+ *
+ * <tr>
+ * <td>up-disabled</td>
+ * <td> {@link #getUpDisabledFace()} </td>
+ * <td>face shown when button is up and disabled</td>
+ * <td> up</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>down-hovering</td>
+ * <td> {@link #getDownHoveringFace()} </td>
+ * <td>face shown when button is down and hovering</td>
+ * <td> down</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>down-disabled</td>
+ * <td> {@link #getDownDisabledFace()} </td>
+ * <td>face shown when button is down and disabled</td>
+ * <td>down</td>
+ * </tr>
+ * </table>
+ * </p>
+ *
+ */
+public abstract class CustomButton extends ButtonBase implements
+ SourcesKeyboardEvents {
+ /**
+ * Represents a button's face. Each face is associated with its own style
+ * modifier and, optionally, its own contents html, text, or image.
+ */
+ public abstract class Face implements HasHTML, HasText {
+ private static final String STYLENAME_HTML_FACE = "html-face";
+ private final Face delegateTo;
+ private Element face;
+
+ /**
+ * Constructor for <code>Face</code>. Creates a new face that delegates
+ * to the supplied face.
+ *
+ * @param delegateTo default content provider
+ */
+ private Face(Face delegateTo) {
+ this.delegateTo = delegateTo;
+ }
+
+ /**
+ * Gets the face's contents as html.
+ *
+ * @return face's contents as html
+ *
+ */
+ public String getHTML() {
+ return DOM.getInnerHTML(getFace());
+ }
+
+ /**
+ * Gets the face's contents as text.
+ *
+ * @return face's contents as text
+ *
+ */
+ public String getText() {
+ return DOM.getInnerText(getFace());
+ }
+
+ /**
+ * Set the face's contents as html.
+ *
+ * @param html html to set as face's contents html
+ *
+ */
+ public void setHTML(String html) {
+ face = DOM.createDiv();
+ UIObject.setStyleName(face, STYLENAME_HTML_FACE, true);
+ DOM.setInnerHTML(face, html);
+ updateButtonFace();
+ }
+
+ /**
+ * Set the face's contents as an image.
+ *
+ * @param image image to set as face contents
+ */
+ public final void setImage(Image image) {
+ face = image.getElement();
+ updateButtonFace();
+ }
+
+ /**
+ * Sets the face's contents as text.
+ *
+ * @param text text to set as face's contents
+ */
+ public final void setText(String text) {
+ face = DOM.createDiv();
+ UIObject.setStyleName(face, STYLENAME_HTML_FACE, true);
+ DOM.setInnerText(face, text);
+ updateButtonFace();
+ }
+
+ public final String toString() {
+ return this.getName();
+ }
+
+ /**
+ * Gets the ID associated with this face. This will be a bitwise and of all
+ * of the attributes that comprise this face.
+ */
+ abstract int getFaceID();
+
+ /**
+ * Get the name of the face. This property is also used as a modifier on the
+ * <code>CustomButton</code> style. <p/> For instance, if the
+ * <code>CustomButton</code> style is "gwt-PushButton" and the face name
+ * is "up", then the CSS class name will be "gwt-PushButton-up".
+ *
+ * @return the face's name
+ */
+ abstract String getName();
+
+ /**
+ * Gets the contents associated with this face.
+ */
+ private Element getFace() {
+ if (face == null) {
+ if (delegateTo == null) {
+ // provide a default face as none was supplied.
+ face = DOM.createDiv();
+ return face;
+ } else {
+ return delegateTo.getFace();
+ }
+ } else {
+ return face;
+ }
+ }
+
+ private void updateButtonFace() {
+ if (curFace != null && curFace.getFace() == this.getFace()) {
+ setCurrentFaceElement(face);
+ }
+ }
+ }
+
+ private static final String STYLENAME_DEFAULT = "gwt-CustomButton";
+
+ /**
+ * Pressed Attribute bit.
+ */
+ private static final int DOWN_ATTRIBUTE = 1;
+
+ /**
+ * Hovering Attribute bit.
+ */
+ private static final int HOVERING_ATTRIBUTE = 2;
+
+ /**
+ * Disabled Attribute bit.
+ */
+ private static final int DISABLED_ATTRIBUTE = 4;
+
+ /**
+ * ID for up face.
+ */
+ private static final int UP = 0;
+
+ /**
+ * ID for down face.
+ */
+ private static final int DOWN = DOWN_ATTRIBUTE;
+
+ /**
+ * ID for upHovering face.
+ */
+ private static final int UP_HOVERING = HOVERING_ATTRIBUTE;
+
+ /**
+ * ID for downHovering face.
+ */
+ private static final int DOWN_HOVERING = DOWN_ATTRIBUTE | HOVERING_ATTRIBUTE;
+
+ /**
+ * ID for upDisabled face.
+ */
+ private static final int UP_DISABLED = DISABLED_ATTRIBUTE;
+
+ /**
+ * ID for downDisabled face.
+ */
+ private static final int DOWN_DISABLED = DOWN | DISABLED_ATTRIBUTE;
+
+ /**
+ * Base style name. By default gwt-CustomButton.
+ */
+ private String baseStyleName;
+
+ /**
+ * The button's current face element.
+ */
+ private Element curFaceElement;
+
+ /**
+ * The button's current face.
+ */
+ private Face curFace;
+
+ /**
+ * Face for up.
+ */
+ private Face up;
+
+ /**
+ * Face for down.
+ */
+ private Face down;
+
+ /**
+ * Face for downHover.
+ */
+ private Face downHovering;
+
+ /**
+ * Face for upHover.
+ */
+ private Face upHovering;
+
+ /**
+ * Face for upDisabled.
+ */
+ private Face upDisabled;
+
+ /**
+ * Face for downDisabled.
+ */
+ private Face downDisabled;
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ *
+ * @param upImage image for the default (up) face of the button
+ */
+ public CustomButton(Image upImage) {
+ this();
+ getUpFace().setImage(upImage);
+ }
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ *
+ * @param upImage image for the default (up) face of the button
+ * @param downImage image for the down face of the button
+ */
+ public CustomButton(Image upImage, Image downImage) {
+ this(upImage);
+ getDownFace().setImage(downImage);
+ }
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ *
+ * @param upImage image for the default (up) face of the button
+ * @param downImage image for the down face of the button
+ * @param listener clickListener
+ */
+ public CustomButton(Image upImage, Image downImage, ClickListener listener) {
+ this(upImage, listener);
+ getDownFace().setImage(downImage);
+ }
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ *
+ * @param upImage image for the default (up) face of the button
+ * @param listener the click listener
+ */
+ public CustomButton(Image upImage, ClickListener listener) {
+ this(upImage);
+ addClickListener(listener);
+ }
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ *
+ * @param upText the text for the default (up) face of the button.
+ */
+ public CustomButton(String upText) {
+ this();
+ getUpFace().setText(upText);
+ }
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ *
+ * @param upText the text for the default (up) face of the button
+ * @param listener the click listener
+ */
+ public CustomButton(String upText, ClickListener listener) {
+ this(upText);
+ addClickListener(listener);
+ }
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ *
+ * @param upText the text for the default (up) face of the button
+ * @param downText the text for the down face of the button
+ */
+ public CustomButton(String upText, String downText) {
+ this(upText);
+ getDownFace().setText(downText);
+ }
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ *
+ * @param upText the text for the default (up) face of the button
+ * @param downText the text for the down face of the button
+ * @param listener the click listener
+ */
+ public CustomButton(String upText, String downText, ClickListener listener) {
+ this(upText, downText);
+ addClickListener(listener);
+ }
+
+ /**
+ * Constructor for <code>CustomButton</code>.
+ */
+ protected CustomButton() {
+ // Use FocusPanel.impl rather than FocusWidget because only FocusPanel.impl
+ // works across browsers to create a focusable element.
+ super(FocusPanel.impl.createFocusable());
+ sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.FOCUSEVENTS);
+ setUpFace(createFace(null, "up", UP));
+ setStyleName(STYLENAME_DEFAULT);
+ }
+
+ /**
+ * Gets the downDisabled face of the button.
+ *
+ * @return the downDisabled face
+ */
+ public final Face getDownDisabledFace() {
+ if (downDisabled == null) {
+ setDownDisabledFace(createFace(getDownFace(), "down-disabled",
+ DOWN_DISABLED));
+ }
+ return downDisabled;
+ }
+
+ /**
+ * Gets the down face of the button.
+ *
+ * @return the down face
+ */
+ public final Face getDownFace() {
+ if (down == null) {
+ setDownFace(createFace(getUpFace(), "down", DOWN));
+ }
+ return down;
+ }
+
+ /**
+ * Gets the downHovering face of the button.
+ *
+ * @return the downHovering face
+ */
+ public final Face getDownHoveringFace() {
+ if (downHovering == null) {
+ setDownHoveringFace(createFace(getDownFace(), "down-hovering",
+ DOWN_HOVERING));
+ }
+ return downHovering;
+ }
+
+ /**
+ * Gets the current face's html.
+ *
+ * @return current face's html
+ */
+ public String getHTML() {
+ return getCurrentFace().getHTML();
+ }
+
+ /**
+ * Gets the style name associated with the object. The actual CSS style name
+ * for the button will be this name + "-" + current face name.
+ *
+ * @return the object's style name
+ * @see #setStyleName(String)
+ */
+ public final String getStyleName() {
+ return baseStyleName;
+ }
+
+ public int getTabIndex() {
+ return FocusPanel.impl.getTabIndex(getElement());
+ }
+
+ /**
+ * Gets the current face's text.
+ *
+ * @return current face's text
+ */
+ public String getText() {
+ return getCurrentFace().getText();
+ }
+
+ /**
+ * Gets the upDisabled face of the button.
+ *
+ * @return the upDisabled face
+ */
+ public final Face getUpDisabledFace() {
+ if (upDisabled == null) {
+ setUpDisabledFace(createFace(getUpFace(), "up-disabled", UP_DISABLED));
+ }
+ return upDisabled;
+ }
+
+ /**
+ * Gets the up face of the button.
+ *
+ * @return the up face
+ */
+ public final Face getUpFace() {
+ return up;
+ }
+
+ /**
+ * Gets the upHovering face of the button.
+ *
+ * @return the upHovering face
+ */
+ public final Face getUpHoveringFace() {
+ if (upHovering == null) {
+ setUpHoveringFace(createFace(getUpFace(), "up-hovering", UP_HOVERING));
+ }
+ return upHovering;
+ }
+
+ public void onBrowserEvent(Event event) {
+ // Should not act on button if disabled.
+ if (isEnabled() == false) {
+ // This can happen when events are bubbled up from non-disabled children
+ return;
+ }
+
+ int type = DOM.eventGetType(event);
+ switch (type) {
+ case Event.ONMOUSEOUT:
+ setHovering(false);
+ break;
+ case Event.ONMOUSEOVER:
+ setHovering(true);
+ break;
+ }
+ super.onBrowserEvent(event);
+ }
+
+ public void setAccessKey(char key) {
+ FocusPanel.impl.setAccessKey(getElement(), key);
+ }
+
+ /**
+ * Sets whether this button is enabled.
+ *
+ * @param enabled <code>true</code> to enable the button, <code>false</code>
+ * to disable it
+ */
+ public final void setEnabled(boolean enabled) {
+ if (isEnabled() != enabled) {
+ toggleDisabled();
+ super.setEnabled(enabled);
+ }
+ }
+
+ public void setFocus(boolean focused) {
+ if (focused) {
+ FocusPanel.impl.focus(getElement());
+ } else {
+ FocusPanel.impl.blur(getElement());
+ }
+ }
+
+ /**
+ * Sets the current face's html.
+ *
+ * @param html html to set
+ */
+ public void setHTML(String html) {
+ getCurrentFace().setHTML(html);
+ }
+
+ /**
+ * Sets the style name associated with the object. The actual CSS style name
+ * for the button will be this name + "-" + current face name.
+ *
+ * @param styleName the object's style name
+ * @see #setStyleName(String)
+ */
+ public final void setStyleName(String styleName) {
+ if (styleName == null) {
+ throw new IllegalStateException("Cannot set the base style name to null");
+ }
+ if (curFace != null) {
+ super.removeStyleName(getCSSStyleName());
+ baseStyleName = styleName;
+ super.addStyleName(getCSSStyleName());
+ } else {
+ baseStyleName = styleName;
+ }
+ }
+
+ public void setTabIndex(int index) {
+ FocusPanel.impl.setTabIndex(getElement(), index);
+ }
+
+ /**
+ * Sets the current face's text.
+ *
+ * @param text text to set
+ */
+ public void setText(String text) {
+ getCurrentFace().setText(text);
+ }
+
+ /**
+ * Is this button down?
+ *
+ * @return <code>true</code> if the button is down
+ */
+ protected boolean isDown() {
+ return (DOWN_ATTRIBUTE & getCurrentFace().getFaceID()) > 0;
+ }
+
+ /**
+ * Overridden on attach to ensure that a button face has been chosen before
+ * the button is displayed.
+ */
+ protected void onAttach() {
+ finishSetup();
+ super.onAttach();
+ }
+
+ /**
+ * Sets whether this button is down.
+ *
+ * @param down <code>true</code> to press the button, <code>false</code>
+ * otherwise
+ */
+ protected void setDown(boolean down) {
+ if (down != isDown()) {
+ toggleDown();
+ }
+ }
+
+ /**
+ * Common setup between constructors.
+ */
+ void finishSetup() {
+ if (curFace == null) {
+ setCurrentFace(getUpFace());
+ }
+ }
+
+ /**
+ * Gets the current face of the button.
+ *
+ * @return the current face
+ */
+
+ Face getCurrentFace() {
+ /*
+ * Implementation note: Package protected so we can use it when testing the
+ * button.
+ */
+
+ finishSetup();
+
+ return curFace;
+ }
+
+ /**
+ * Is the mouse hovering over this button?
+ *
+ * @return <code>true</code> if the mouse is hovering
+ */
+ final boolean isHovering() {
+ return (HOVERING_ATTRIBUTE & getCurrentFace().getFaceID()) > 0;
+ }
+
+ void setCurrentFace(Face newFace) {
+ /*
+ * Implementation note: default access for testing.
+ */
+ if (curFace != newFace) {
+ if (curFace != null) {
+ super.removeStyleName(getCSSStyleName());
+ }
+ curFace = newFace;
+ setCurrentFaceElement(newFace.getFace());
+ super.addStyleName(getCSSStyleName());
+ }
+ }
+
+ /**
+ * Sets whether this button is hovering.
+ *
+ * @param hovering is this button hovering?
+ */
+ final void setHovering(boolean hovering) {
+ if (hovering != isHovering()) {
+ toggleHover();
+ }
+ }
+
+ /**
+ * Toggle the up/down attribute.
+ */
+ void toggleDown() {
+ int newFaceID = getCurrentFace().getFaceID() ^ DOWN_ATTRIBUTE;
+ setCurrentFace(newFaceID);
+ }
+
+ private Face createFace(Face delegateTo, final String name, final int faceID) {
+ return new Face(delegateTo) {
+
+ public String getName() {
+ return name;
+ }
+
+ int getFaceID() {
+ return faceID;
+ }
+ };
+ }
+
+ /**
+ * Gets the modified style name.
+ *
+ * @return the modified style name
+ */
+ private String getCSSStyleName() {
+ return baseStyleName + "-" + curFace.getName();
+ }
+
+ private Face getFaceFromID(int id) {
+ switch (id) {
+ case DOWN:
+ return getDownFace();
+ case UP:
+ return getUpFace();
+ case DOWN_HOVERING:
+ return getDownHoveringFace();
+ case UP_HOVERING:
+ return getUpHoveringFace();
+ case UP_DISABLED:
+ return getUpDisabledFace();
+ case DOWN_DISABLED:
+ return getDownDisabledFace();
+ default:
+ throw new IllegalStateException(id + " is not a known face id.");
+ }
+ }
+
+ /**
+ * Sets the current face based on the faceID.
+ *
+ * @param faceID sets the new face of the button
+ */
+ private void setCurrentFace(int faceID) {
+ Face newFace = getFaceFromID(faceID);
+ setCurrentFace(newFace);
+ }
+
+ private void setCurrentFaceElement(Element newFaceElement) {
+ if (curFaceElement != newFaceElement) {
+ if (curFaceElement != null) {
+ DOM.removeChild(getElement(), curFaceElement);
+ }
+ curFaceElement = newFaceElement;
+ DOM.appendChild(getElement(), curFaceElement);
+ }
+ }
+
+ /**
+ * Sets the downDisabled face of the button.
+ *
+ * @param downDisabled downDisabled face
+ */
+ private void setDownDisabledFace(Face downDisabled) {
+ this.downDisabled = downDisabled;
+ }
+
+ /**
+ * Sets the down face of the button.
+ *
+ * @param down the down face
+ */
+ private void setDownFace(Face down) {
+ this.down = down;
+ }
+
+ /**
+ * Sets the downHovering face of the button.
+ *
+ * @param downHovering hoverDown face
+ */
+ private void setDownHoveringFace(Face downHovering) {
+ this.downHovering = downHovering;
+ }
+
+ /**
+ * Sets the upDisabled face of the button.
+ *
+ * @param upDisabled upDisabled face
+ */
+ private void setUpDisabledFace(Face upDisabled) {
+ this.upDisabled = upDisabled;
+ }
+
+ /**
+ * Sets the up face of the button.
+ *
+ * @param up up face
+ */
+ private void setUpFace(Face up) {
+ this.up = up;
+ }
+
+ /**
+ * Sets the upHovering face of the button.
+ *
+ * @param upHovering upHovering face
+ */
+ private void setUpHoveringFace(Face upHovering) {
+ this.upHovering = upHovering;
+ }
+
+ /**
+ * Toggle the disabled attribute.
+ */
+ private void toggleDisabled() {
+ // Toggle disabled.
+ int newFaceID = getCurrentFace().getFaceID() ^ DISABLED_ATTRIBUTE;
+
+ // Remove hovering.
+ newFaceID &= ~HOVERING_ATTRIBUTE;
+
+ // Sets the current face.
+ setCurrentFace(newFaceID);
+ }
+
+ /**
+ * Toggle the hovering attribute.
+ */
+ private void toggleHover() {
+ // Toggle hovering.
+ int newFaceID = getCurrentFace().getFaceID() ^ HOVERING_ATTRIBUTE;
+
+ // Remove disabled.
+ newFaceID &= ~DISABLED_ATTRIBUTE;
+ setCurrentFace(newFaceID);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/DelegatingChangeListenerCollection.java b/user/src/com/google/gwt/user/client/ui/DelegatingChangeListenerCollection.java
index 72fbea7..e486ef6 100644
--- a/user/src/com/google/gwt/user/client/ui/DelegatingChangeListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/DelegatingChangeListenerCollection.java
@@ -1,62 +1,62 @@
-/*
- * Copyright 2007 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;
-
-/**
- * {@link ChangeListenerCollection} used to correctly hook up listeners which
- * need to listen to events from another source.
- * <p>
- * For example, {@link Composite} widgets often need to listen to events
- * generated on their wrapped widget. Upon the firing of a wrapped widget's
- * event, the composite widget must fire its own listeners with itself as the
- * source of the event. To use a {@link DelegatingChangeListenerCollection},
- * simply use the {@link DelegatingChangeListenerCollection} instead of a
- * {@link ChangeListenerCollection}. For example, in {@link SuggestBox}, the
- * following code is used to listen to change events on the {@link SuggestBox}'s
- * underlying widget.
- * </p>
- *
- * <pre>
- * public void addChangeListener(ChangeListener listener) {
- * if (changeListeners == null) {
- * changeListeners = new DelegatingChangeListenerCollection(this, box);
- * }
- * changeListeners.add(listener);
- * }
- *</pre>
- */
-public class DelegatingChangeListenerCollection extends
- ChangeListenerCollection implements ChangeListener {
-
- private final Widget owner;
-
- /**
- * Constructor for {@link DelegatingChangeListenerCollection}.
- *
- * @param owner owner of listeners
- * @param delegatedTo source of events
- */
- public DelegatingChangeListenerCollection(Widget owner,
- SourcesChangeEvents delegatedTo) {
- this.owner = owner;
- delegatedTo.addChangeListener(this);
- }
-
- public void onChange(Widget sender) {
- super.fireChange(owner);
- }
-}
+/*
+ * Copyright 2007 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;
+
+/**
+ * {@link ChangeListenerCollection} used to correctly hook up listeners which
+ * need to listen to events from another source.
+ * <p>
+ * For example, {@link Composite} widgets often need to listen to events
+ * generated on their wrapped widget. Upon the firing of a wrapped widget's
+ * event, the composite widget must fire its own listeners with itself as the
+ * source of the event. To use a {@link DelegatingChangeListenerCollection},
+ * simply use the {@link DelegatingChangeListenerCollection} instead of a
+ * {@link ChangeListenerCollection}. For example, in {@link SuggestBox}, the
+ * following code is used to listen to change events on the {@link SuggestBox}'s
+ * underlying widget.
+ * </p>
+ *
+ * <pre>
+ * public void addChangeListener(ChangeListener listener) {
+ * if (changeListeners == null) {
+ * changeListeners = new DelegatingChangeListenerCollection(this, box);
+ * }
+ * changeListeners.add(listener);
+ * }
+ *</pre>
+ */
+public class DelegatingChangeListenerCollection extends
+ ChangeListenerCollection implements ChangeListener {
+
+ private final Widget owner;
+
+ /**
+ * Constructor for {@link DelegatingChangeListenerCollection}.
+ *
+ * @param owner owner of listeners
+ * @param delegatedTo source of events
+ */
+ public DelegatingChangeListenerCollection(Widget owner,
+ SourcesChangeEvents delegatedTo) {
+ this.owner = owner;
+ delegatedTo.addChangeListener(this);
+ }
+
+ public void onChange(Widget sender) {
+ super.fireChange(owner);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/DelegatingClickListenerCollection.java b/user/src/com/google/gwt/user/client/ui/DelegatingClickListenerCollection.java
index 04ff9e7..afe3f37 100644
--- a/user/src/com/google/gwt/user/client/ui/DelegatingClickListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/DelegatingClickListenerCollection.java
@@ -1,62 +1,62 @@
-/*
- * Copyright 2006 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;
-
-/**
- * {@link ClickListenerCollection} used to correctly hook up listeners which
- * need to listen to events from another source.
- * <p>
- * For example, {@link Composite} widgets often need to listen to events
- * generated on their wrapped widget. Upon the firing of a wrapped widget's
- * event, the composite widget must fire its own listeners with itself as the
- * source of the event. To use a {@link DelegatingClickListenerCollection},
- * simply use the {@link DelegatingClickListenerCollection} instead of a
- * {@link ClickListenerCollection}. For example, in {@link SuggestBox}, the
- * following code is used to listen to click events on the {@link SuggestBox}'s
- * underlying widget.
- * </p>
- *
- * <pre>
- * public void addClickListener(ClickListener listener) {
- * if (clickListeners == null) {
- * clickListeners = new DelegatingClickListenerCollection(this, box);
- * }
- * clickListeners.add(listener);
- * }
- *</pre>
- */
-public class DelegatingClickListenerCollection extends ClickListenerCollection
- implements ClickListener {
-
- private final Widget owner;
-
- /**
- * Constructor for {@link DelegatingClickListenerCollection}.
- *
- * @param owner owner of listeners
- * @param delegatedTo source of events
- */
- public DelegatingClickListenerCollection(Widget owner,
- SourcesClickEvents delegatedTo) {
- this.owner = owner;
- delegatedTo.addClickListener(this);
- }
-
- public void onClick(Widget sender) {
- super.fireClick(owner);
- }
-}
+/*
+ * Copyright 2006 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;
+
+/**
+ * {@link ClickListenerCollection} used to correctly hook up listeners which
+ * need to listen to events from another source.
+ * <p>
+ * For example, {@link Composite} widgets often need to listen to events
+ * generated on their wrapped widget. Upon the firing of a wrapped widget's
+ * event, the composite widget must fire its own listeners with itself as the
+ * source of the event. To use a {@link DelegatingClickListenerCollection},
+ * simply use the {@link DelegatingClickListenerCollection} instead of a
+ * {@link ClickListenerCollection}. For example, in {@link SuggestBox}, the
+ * following code is used to listen to click events on the {@link SuggestBox}'s
+ * underlying widget.
+ * </p>
+ *
+ * <pre>
+ * public void addClickListener(ClickListener listener) {
+ * if (clickListeners == null) {
+ * clickListeners = new DelegatingClickListenerCollection(this, box);
+ * }
+ * clickListeners.add(listener);
+ * }
+ *</pre>
+ */
+public class DelegatingClickListenerCollection extends ClickListenerCollection
+ implements ClickListener {
+
+ private final Widget owner;
+
+ /**
+ * Constructor for {@link DelegatingClickListenerCollection}.
+ *
+ * @param owner owner of listeners
+ * @param delegatedTo source of events
+ */
+ public DelegatingClickListenerCollection(Widget owner,
+ SourcesClickEvents delegatedTo) {
+ this.owner = owner;
+ delegatedTo.addClickListener(this);
+ }
+
+ public void onClick(Widget sender) {
+ super.fireClick(owner);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/DelegatingFocusListenerCollection.java b/user/src/com/google/gwt/user/client/ui/DelegatingFocusListenerCollection.java
index e10d687..438add4 100644
--- a/user/src/com/google/gwt/user/client/ui/DelegatingFocusListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/DelegatingFocusListenerCollection.java
@@ -1,66 +1,66 @@
-/*
- * Copyright 2006 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;
-
-/**
- * {@link FocusListenerCollection} used to correctly hook up listeners which
- * need to listen to events from another source.
- * <p>
- * For example, {@link Composite} widgets often need to listen to events
- * generated on their wrapped widget. Upon the firing of a wrapped widget's
- * event, the composite widget must fire its own listeners with itself as the
- * source of the event. To use a {@link DelegatingFocusListenerCollection},
- * simply use the {@link DelegatingFocusListenerCollection} instead of a
- * {@link FocusListenerCollection}. For example, in {@link SuggestBox}, the
- * following code is used to listen to focus events on the {@link SuggestBox}'s
- * underlying widget.
- * </p>
- *
- * <pre>
- * public void addFocusListener(FocusListener listener) {
- * if (focusListeners == null) {
- * focusListeners = new DelegatingFocusListenerCollection(this, box);
- * }
- * focusListeners.add(listener);
- * }
- *</pre>
- */
-public class DelegatingFocusListenerCollection extends FocusListenerCollection
- implements FocusListener {
-
- private final Widget owner;
-
- /**
- * Constructor for {@link DelegatingFocusListenerCollection}. *
- *
- * @param owner owner of listeners
- * @param delegatedTo source of events
- */
- public DelegatingFocusListenerCollection(Widget owner,
- SourcesFocusEvents delegatedTo) {
- this.owner = owner;
- delegatedTo.addFocusListener(this);
- }
-
- public void onFocus(Widget sender) {
- super.fireFocus(owner);
- }
-
- public void onLostFocus(Widget sender) {
- super.fireLostFocus(owner);
- }
-}
+/*
+ * Copyright 2006 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;
+
+/**
+ * {@link FocusListenerCollection} used to correctly hook up listeners which
+ * need to listen to events from another source.
+ * <p>
+ * For example, {@link Composite} widgets often need to listen to events
+ * generated on their wrapped widget. Upon the firing of a wrapped widget's
+ * event, the composite widget must fire its own listeners with itself as the
+ * source of the event. To use a {@link DelegatingFocusListenerCollection},
+ * simply use the {@link DelegatingFocusListenerCollection} instead of a
+ * {@link FocusListenerCollection}. For example, in {@link SuggestBox}, the
+ * following code is used to listen to focus events on the {@link SuggestBox}'s
+ * underlying widget.
+ * </p>
+ *
+ * <pre>
+ * public void addFocusListener(FocusListener listener) {
+ * if (focusListeners == null) {
+ * focusListeners = new DelegatingFocusListenerCollection(this, box);
+ * }
+ * focusListeners.add(listener);
+ * }
+ *</pre>
+ */
+public class DelegatingFocusListenerCollection extends FocusListenerCollection
+ implements FocusListener {
+
+ private final Widget owner;
+
+ /**
+ * Constructor for {@link DelegatingFocusListenerCollection}. *
+ *
+ * @param owner owner of listeners
+ * @param delegatedTo source of events
+ */
+ public DelegatingFocusListenerCollection(Widget owner,
+ SourcesFocusEvents delegatedTo) {
+ this.owner = owner;
+ delegatedTo.addFocusListener(this);
+ }
+
+ public void onFocus(Widget sender) {
+ super.fireFocus(owner);
+ }
+
+ public void onLostFocus(Widget sender) {
+ super.fireLostFocus(owner);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/DelegatingKeyboardListenerCollection.java b/user/src/com/google/gwt/user/client/ui/DelegatingKeyboardListenerCollection.java
index bf0c803..5f45de8 100644
--- a/user/src/com/google/gwt/user/client/ui/DelegatingKeyboardListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/DelegatingKeyboardListenerCollection.java
@@ -1,71 +1,71 @@
-/*
- * Copyright 2006 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;
-
-/**
- * {@link KeyboardListenerCollection} used to correctly hook up event listeners
- * to the composite's wrapped widget.
- *
- * <p>
- * For example, {@link Composite} widgets often need to listen to events
- * generated on their wrapped widget. Upon the firing of a wrapped widget's
- * event, the composite widget must fire its own listeners with itself as the
- * source of the event. To use a {@link DelegatingKeyboardListenerCollection},
- * simply use the {@link DelegatingKeyboardListenerCollection} instead of a
- * {@link KeyboardListenerCollection}. For example, in {@link SuggestBox}, the
- * following code is used to listen to keyboard events on the {@link SuggestBox}'s
- * underlying widget.
- * </p>
- *
- * <pre>
- * public void addKeyboardListener(KeyboardListener listener) {
- * if (keyboardListeners == null) {
- * keyboardListeners = new DelegatingKeyboardListenerCollection(this, box);
- * }
- * keyboardListeners.add(listener);
- * }
- *</pre>
- */
-public class DelegatingKeyboardListenerCollection extends
- KeyboardListenerCollection implements KeyboardListener {
-
- private final Widget owner;
-
- /**
- * Constructor for {@link DelegatingKeyboardListenerCollection}.
- *
- * @param owner owner of listeners
- * @param delegatedTo source of events
- */
- public DelegatingKeyboardListenerCollection(Widget owner,
- SourcesKeyboardEvents delegatedTo) {
- this.owner = owner;
- delegatedTo.addKeyboardListener(this);
- }
-
- public void onKeyDown(Widget sender, char keyCode, int modifiers) {
- fireKeyDown(owner, keyCode, modifiers);
- }
-
- public void onKeyPress(Widget sender, char keyCode, int modifiers) {
- fireKeyPress(owner, keyCode, modifiers);
- }
-
- public void onKeyUp(Widget sender, char keyCode, int modifiers) {
- fireKeyPress(owner, keyCode, modifiers);
- }
-}
+/*
+ * Copyright 2006 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;
+
+/**
+ * {@link KeyboardListenerCollection} used to correctly hook up event listeners
+ * to the composite's wrapped widget.
+ *
+ * <p>
+ * For example, {@link Composite} widgets often need to listen to events
+ * generated on their wrapped widget. Upon the firing of a wrapped widget's
+ * event, the composite widget must fire its own listeners with itself as the
+ * source of the event. To use a {@link DelegatingKeyboardListenerCollection},
+ * simply use the {@link DelegatingKeyboardListenerCollection} instead of a
+ * {@link KeyboardListenerCollection}. For example, in {@link SuggestBox}, the
+ * following code is used to listen to keyboard events on the {@link SuggestBox}'s
+ * underlying widget.
+ * </p>
+ *
+ * <pre>
+ * public void addKeyboardListener(KeyboardListener listener) {
+ * if (keyboardListeners == null) {
+ * keyboardListeners = new DelegatingKeyboardListenerCollection(this, box);
+ * }
+ * keyboardListeners.add(listener);
+ * }
+ *</pre>
+ */
+public class DelegatingKeyboardListenerCollection extends
+ KeyboardListenerCollection implements KeyboardListener {
+
+ private final Widget owner;
+
+ /**
+ * Constructor for {@link DelegatingKeyboardListenerCollection}.
+ *
+ * @param owner owner of listeners
+ * @param delegatedTo source of events
+ */
+ public DelegatingKeyboardListenerCollection(Widget owner,
+ SourcesKeyboardEvents delegatedTo) {
+ this.owner = owner;
+ delegatedTo.addKeyboardListener(this);
+ }
+
+ public void onKeyDown(Widget sender, char keyCode, int modifiers) {
+ fireKeyDown(owner, keyCode, modifiers);
+ }
+
+ public void onKeyPress(Widget sender, char keyCode, int modifiers) {
+ fireKeyPress(owner, keyCode, modifiers);
+ }
+
+ public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+ fireKeyPress(owner, keyCode, modifiers);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/MultiWordSuggestOracle.java b/user/src/com/google/gwt/user/client/ui/MultiWordSuggestOracle.java
index 4a065fa..0daac67 100644
--- a/user/src/com/google/gwt/user/client/ui/MultiWordSuggestOracle.java
+++ b/user/src/com/google/gwt/user/client/ui/MultiWordSuggestOracle.java
@@ -1,382 +1,382 @@
-/*
- * Copyright 2007 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 java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * The default {@link com.google.gwt.user.client.ui.SuggestOracle}. The default
- * oracle returns potential suggestions based on breaking the query into
- * separate words and looking for matches. It also modifies the returned text to
- * show which prefix matched the query term. The matching is case insensitive.
- * All suggestions are sorted before being passed into a response.
- * <p>
- * Example Table
- * </p>
- * <p>
- * <table width = "100%" border = "1">
- * <tr>
- * <td><b> All Suggestions </b> </td>
- * <td><b>Query string</b> </td>
- * <td><b>Matching Suggestions</b></td>
- * </tr>
- * <tr>
- * <td> John Smith, Joe Brown, Jane Doe, Jane Smith, Bob Jones</td>
- * <td> Jo</td>
- * <td> John Smith, Joe Brown, Bob Jones</td>
- * </tr>
- * <tr>
- * <td> John Smith, Joe Brown, Jane Doe, Jane Smith, Bob Jones</td>
- * <td> Smith</td>
- * <td> John Smith, Jane Smith</td>
- * </tr>
- * <tr>
- * <td> Georgia, New York, California</td>
- * <td> g</td>
- * <td> Georgia</td>
- * </tr>
- * </table>
- * </p>
- */
-public final class MultiWordSuggestOracle extends SuggestOracle {
-
- /**
- * Suggestion class for {@link MultiWordSuggestOracle}.
- */
- protected static class MultiWordSuggestion implements Suggestion {
- private final String value;
- private final String displayString;
-
- /**
- * Constructor for <code>MultiWordSuggestion</code>.
- *
- * @param value the value
- * @param displayString the display string
- */
- public MultiWordSuggestion(String value, String displayString) {
- this.value = value;
- this.displayString = displayString;
- }
-
- public String getDisplayString() {
- return displayString;
- }
-
- public Object getValue() {
- return value;
- }
- }
-
- private static final char WHITESPACE_CHAR = ' ';
- private static final String WHITESPACE_STRING = " ";
-
- /**
- * Regular expression used to collapse all whitespace in a query string.
- */
- private static final String NORMALIZE_TO_SINGLE_WHITE_SPACE = "\\s+";
-
- private static HTML convertMe = new HTML();
-
- /**
- * Associates substrings with words.
- */
- private final PrefixTree tree = new PrefixTree();
-
- /**
- * Associates individual words with candidates.
- */
- private HashMap toCandidates = new HashMap();
-
- /**
- * Associates candidates with their formatted suggestions.
- */
- private HashMap toRealSuggestions = new HashMap();
-
- /**
- * The whitespace masks used to prevent matching and replacing of the given
- * substrings.
- */
- private char[] whitespaceChars;
-
- /**
- * Constructor for <code>MultiWordSuggestOracle</code>. This uses a space as
- * the whitespace character.
- *
- * @see #MultiWordSuggestOracle(String)
- */
- public MultiWordSuggestOracle() {
- this(" ");
- }
-
- /**
- * Constructor for <code>MultiWordSuggestOracle</code> which takes in a set
- * of whitespace chars that filter its input.
- * <p>
- * Example: If <code>".,"</code> is passed in as whitespace, then the string
- * "foo.bar" would match the queries "foo", "bar", "foo.bar", "foo...bar", and
- * "foo, bar". If the empty string is used, then all characters are used in
- * matching. For example, the query "bar" would match "bar", but not "foo
- * bar".
- * </p>
- *
- * @param whitespaceChars the characters to treat as word separators
- */
- public MultiWordSuggestOracle(String whitespaceChars) {
- this.whitespaceChars = new char[whitespaceChars.length()];
- for (int i = 0; i < whitespaceChars.length(); i++) {
- this.whitespaceChars[i] = whitespaceChars.charAt(i);
- }
- }
-
- /**
- * Adds a suggestion to the oracle. Each suggestion must be plain text.
- *
- * @param suggestion the suggestion
- */
- public void add(String suggestion) {
- String candidate = normalizeSuggestion(suggestion);
- // candidates --> real suggestions.
- toRealSuggestions.put(candidate, suggestion);
-
- // word fragments --> candidates.
- String[] words = candidate.split(WHITESPACE_STRING);
- for (int i = 0; i < words.length; i++) {
- String word = words[i];
- tree.add(word);
- HashSet l = (HashSet) toCandidates.get(word);
- if (l == null) {
- l = new HashSet();
- toCandidates.put(word, l);
- }
- l.add(candidate);
- }
- }
-
- /**
- * Adds all suggestions specified. Each suggestion must be plain text.
- *
- * @param collection the collection
- */
- public void addAll(Collection collection) {
- Iterator suggestions = collection.iterator();
- while (suggestions.hasNext()) {
- add((String) suggestions.next());
- }
- }
-
- public boolean isDisplayStringHTML() {
- return true;
- }
-
- public void requestSuggestions(Request request, Callback callback) {
- final List suggestions = computeItemsFor(request.getQuery(), request
- .getLimit());
- Response response = new Response(suggestions);
- callback.onSuggestionsReady(request, response);
- }
-
- String escapeText(String escapeMe) {
- convertMe.setText(escapeMe);
- String escaped = convertMe.getHTML();
- return escaped;
- }
-
- /**
- * Compute the suggestions that are matches for a given query.
- *
- * @param query search string
- * @param limit limit
- * @return matching suggestions
- */
- private List computeItemsFor(String query, int limit) {
- query = normalizeSearch(query);
-
- // Get candidates from search words.
- List candidates = createCandidatesFromSearch(query, limit);
-
- // Convert candidates to suggestions.
- return convertToFormattedSuggestions(query, candidates);
- }
-
- /**
- * Returns real suggestions with the given query in <code>strong</code> html
- * font.
- *
- * @param query query string
- * @param candidates candidates
- * @return real suggestions
- */
- private List convertToFormattedSuggestions(String query, List candidates) {
- List suggestions = new ArrayList();
-
- for (int i = 0; i < candidates.size(); i++) {
- String candidate = (String) candidates.get(i);
- int index = 0;
- int cursor = 0;
- // Use real suggestion for assembly.
- String formattedSuggestion = (String) toRealSuggestions.get(candidate);
-
- // Create strong search string.
- StringBuffer accum = new StringBuffer();
-
- while (true) {
- index = candidate.indexOf(query, index);
- if (index == -1) {
- break;
- }
- int endIndex = index + query.length();
- if (index == 0 || (WHITESPACE_CHAR == candidate.charAt(index - 1))) {
- String part1 = escapeText(formattedSuggestion
- .substring(cursor, index));
- String part2 = escapeText(formattedSuggestion.substring(index,
- endIndex));
- cursor = endIndex;
- accum.append(part1).append("<strong>").append(part2).append(
- "</strong>");
- }
- index = endIndex;
- }
-
- // Check to make sure the search was found in the string.
- if (cursor == 0) {
- continue;
- }
-
- // Finish creating the formatted string.
- String end = escapeText(formattedSuggestion.substring(cursor));
- accum.append(end);
- MultiWordSuggestion suggestion = new MultiWordSuggestion(
- formattedSuggestion, accum.toString());
- suggestions.add(suggestion);
- }
- return suggestions;
- }
-
- /**
- * Find the sorted list of candidates that are matches for the given query.
- */
- private List createCandidatesFromSearch(String query, int limit) {
- ArrayList candidates = new ArrayList();
-
- if (query.length() == 0) {
- return candidates;
- }
-
- // Find all words to search for.
- String[] searchWords = query.split(WHITESPACE_STRING);
- HashSet candidateSet = null;
- for (int i = 0; i < searchWords.length; i++) {
- String word = searchWords[i];
-
- // Eliminate bogus word choices.
- if (word.length() == 0 || word.matches(WHITESPACE_STRING)) {
- continue;
- }
-
- // Find the set of candidates that are associated with all the
- // searchWords.
- HashSet thisWordChoices = createCandidatesFromWord(word);
- if (candidateSet == null) {
- candidateSet = thisWordChoices;
- } else {
- candidateSet.retainAll(thisWordChoices);
-
- if (candidateSet.size() < 2) {
- // If there is only one candidate, on average it is cheaper to
- // check if that candidate contains our search string than to
- // continue intersecting suggestion sets.
- break;
- }
- }
- }
- if (candidateSet != null) {
- candidates.addAll(candidateSet);
- Collections.sort(candidates);
- // Respect limit for number of choices.
- for (int i = candidates.size() - 1; i > limit; i--) {
- candidates.remove(i);
- }
- }
- return candidates;
- }
-
- /**
- * Creates a set of potential candidates that match the given query.
- *
- * @param limit number of candidates to return
- * @param query query string
- * @return possible candidates
- */
- private HashSet createCandidatesFromWord(String query) {
- HashSet candidateSet = new HashSet();
- List words = tree.getSuggestions(query, Integer.MAX_VALUE);
- if (words != null) {
- // Find all candidates that contain the given word the search is a
- // subset of.
- for (int i = 0; i < words.size(); i++) {
- Collection belongsTo = (Collection) toCandidates.get(words.get(i));
- if (belongsTo != null) {
- candidateSet.addAll(belongsTo);
- }
- }
- }
- return candidateSet;
- }
-
- /**
- * Normalize the search key by making it lower case, removing multiple spaces,
- * apply whitespace masks, and make it lower case.
- */
- private String normalizeSearch(String search) {
- // Use the same whitespace masks and case normalization for the search
- // string as was used with the candidate values.
- search = normalizeSuggestion(search);
-
- // Remove all excess whitespace from the search string.
- search = search.replaceAll(NORMALIZE_TO_SINGLE_WHITE_SPACE,
- WHITESPACE_STRING);
-
- return search.trim();
- }
-
- /**
- * Takes the formatted suggestion, makes it lower case and blanks out any
- * existing whitespace for searching.
- */
- private String normalizeSuggestion(String formattedSuggestion) {
- // Formatted suggestions should already have normalized whitespace. So we
- // can skip that step.
-
- // Lower case suggestion.
- formattedSuggestion = formattedSuggestion.toLowerCase();
-
- // Apply whitespace.
- if (whitespaceChars != null) {
- for (int i = 0; i < whitespaceChars.length; i++) {
- char ignore = whitespaceChars[i];
- formattedSuggestion = formattedSuggestion.replace(ignore,
- WHITESPACE_CHAR);
- }
- }
- return formattedSuggestion;
- }
-}
+/*
+ * Copyright 2007 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * The default {@link com.google.gwt.user.client.ui.SuggestOracle}. The default
+ * oracle returns potential suggestions based on breaking the query into
+ * separate words and looking for matches. It also modifies the returned text to
+ * show which prefix matched the query term. The matching is case insensitive.
+ * All suggestions are sorted before being passed into a response.
+ * <p>
+ * Example Table
+ * </p>
+ * <p>
+ * <table width = "100%" border = "1">
+ * <tr>
+ * <td><b> All Suggestions </b> </td>
+ * <td><b>Query string</b> </td>
+ * <td><b>Matching Suggestions</b></td>
+ * </tr>
+ * <tr>
+ * <td> John Smith, Joe Brown, Jane Doe, Jane Smith, Bob Jones</td>
+ * <td> Jo</td>
+ * <td> John Smith, Joe Brown, Bob Jones</td>
+ * </tr>
+ * <tr>
+ * <td> John Smith, Joe Brown, Jane Doe, Jane Smith, Bob Jones</td>
+ * <td> Smith</td>
+ * <td> John Smith, Jane Smith</td>
+ * </tr>
+ * <tr>
+ * <td> Georgia, New York, California</td>
+ * <td> g</td>
+ * <td> Georgia</td>
+ * </tr>
+ * </table>
+ * </p>
+ */
+public final class MultiWordSuggestOracle extends SuggestOracle {
+
+ /**
+ * Suggestion class for {@link MultiWordSuggestOracle}.
+ */
+ protected static class MultiWordSuggestion implements Suggestion {
+ private final String value;
+ private final String displayString;
+
+ /**
+ * Constructor for <code>MultiWordSuggestion</code>.
+ *
+ * @param value the value
+ * @param displayString the display string
+ */
+ public MultiWordSuggestion(String value, String displayString) {
+ this.value = value;
+ this.displayString = displayString;
+ }
+
+ public String getDisplayString() {
+ return displayString;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+ }
+
+ private static final char WHITESPACE_CHAR = ' ';
+ private static final String WHITESPACE_STRING = " ";
+
+ /**
+ * Regular expression used to collapse all whitespace in a query string.
+ */
+ private static final String NORMALIZE_TO_SINGLE_WHITE_SPACE = "\\s+";
+
+ private static HTML convertMe = new HTML();
+
+ /**
+ * Associates substrings with words.
+ */
+ private final PrefixTree tree = new PrefixTree();
+
+ /**
+ * Associates individual words with candidates.
+ */
+ private HashMap toCandidates = new HashMap();
+
+ /**
+ * Associates candidates with their formatted suggestions.
+ */
+ private HashMap toRealSuggestions = new HashMap();
+
+ /**
+ * The whitespace masks used to prevent matching and replacing of the given
+ * substrings.
+ */
+ private char[] whitespaceChars;
+
+ /**
+ * Constructor for <code>MultiWordSuggestOracle</code>. This uses a space as
+ * the whitespace character.
+ *
+ * @see #MultiWordSuggestOracle(String)
+ */
+ public MultiWordSuggestOracle() {
+ this(" ");
+ }
+
+ /**
+ * Constructor for <code>MultiWordSuggestOracle</code> which takes in a set
+ * of whitespace chars that filter its input.
+ * <p>
+ * Example: If <code>".,"</code> is passed in as whitespace, then the string
+ * "foo.bar" would match the queries "foo", "bar", "foo.bar", "foo...bar", and
+ * "foo, bar". If the empty string is used, then all characters are used in
+ * matching. For example, the query "bar" would match "bar", but not "foo
+ * bar".
+ * </p>
+ *
+ * @param whitespaceChars the characters to treat as word separators
+ */
+ public MultiWordSuggestOracle(String whitespaceChars) {
+ this.whitespaceChars = new char[whitespaceChars.length()];
+ for (int i = 0; i < whitespaceChars.length(); i++) {
+ this.whitespaceChars[i] = whitespaceChars.charAt(i);
+ }
+ }
+
+ /**
+ * Adds a suggestion to the oracle. Each suggestion must be plain text.
+ *
+ * @param suggestion the suggestion
+ */
+ public void add(String suggestion) {
+ String candidate = normalizeSuggestion(suggestion);
+ // candidates --> real suggestions.
+ toRealSuggestions.put(candidate, suggestion);
+
+ // word fragments --> candidates.
+ String[] words = candidate.split(WHITESPACE_STRING);
+ for (int i = 0; i < words.length; i++) {
+ String word = words[i];
+ tree.add(word);
+ HashSet l = (HashSet) toCandidates.get(word);
+ if (l == null) {
+ l = new HashSet();
+ toCandidates.put(word, l);
+ }
+ l.add(candidate);
+ }
+ }
+
+ /**
+ * Adds all suggestions specified. Each suggestion must be plain text.
+ *
+ * @param collection the collection
+ */
+ public void addAll(Collection collection) {
+ Iterator suggestions = collection.iterator();
+ while (suggestions.hasNext()) {
+ add((String) suggestions.next());
+ }
+ }
+
+ public boolean isDisplayStringHTML() {
+ return true;
+ }
+
+ public void requestSuggestions(Request request, Callback callback) {
+ final List suggestions = computeItemsFor(request.getQuery(), request
+ .getLimit());
+ Response response = new Response(suggestions);
+ callback.onSuggestionsReady(request, response);
+ }
+
+ String escapeText(String escapeMe) {
+ convertMe.setText(escapeMe);
+ String escaped = convertMe.getHTML();
+ return escaped;
+ }
+
+ /**
+ * Compute the suggestions that are matches for a given query.
+ *
+ * @param query search string
+ * @param limit limit
+ * @return matching suggestions
+ */
+ private List computeItemsFor(String query, int limit) {
+ query = normalizeSearch(query);
+
+ // Get candidates from search words.
+ List candidates = createCandidatesFromSearch(query, limit);
+
+ // Convert candidates to suggestions.
+ return convertToFormattedSuggestions(query, candidates);
+ }
+
+ /**
+ * Returns real suggestions with the given query in <code>strong</code> html
+ * font.
+ *
+ * @param query query string
+ * @param candidates candidates
+ * @return real suggestions
+ */
+ private List convertToFormattedSuggestions(String query, List candidates) {
+ List suggestions = new ArrayList();
+
+ for (int i = 0; i < candidates.size(); i++) {
+ String candidate = (String) candidates.get(i);
+ int index = 0;
+ int cursor = 0;
+ // Use real suggestion for assembly.
+ String formattedSuggestion = (String) toRealSuggestions.get(candidate);
+
+ // Create strong search string.
+ StringBuffer accum = new StringBuffer();
+
+ while (true) {
+ index = candidate.indexOf(query, index);
+ if (index == -1) {
+ break;
+ }
+ int endIndex = index + query.length();
+ if (index == 0 || (WHITESPACE_CHAR == candidate.charAt(index - 1))) {
+ String part1 = escapeText(formattedSuggestion
+ .substring(cursor, index));
+ String part2 = escapeText(formattedSuggestion.substring(index,
+ endIndex));
+ cursor = endIndex;
+ accum.append(part1).append("<strong>").append(part2).append(
+ "</strong>");
+ }
+ index = endIndex;
+ }
+
+ // Check to make sure the search was found in the string.
+ if (cursor == 0) {
+ continue;
+ }
+
+ // Finish creating the formatted string.
+ String end = escapeText(formattedSuggestion.substring(cursor));
+ accum.append(end);
+ MultiWordSuggestion suggestion = new MultiWordSuggestion(
+ formattedSuggestion, accum.toString());
+ suggestions.add(suggestion);
+ }
+ return suggestions;
+ }
+
+ /**
+ * Find the sorted list of candidates that are matches for the given query.
+ */
+ private List createCandidatesFromSearch(String query, int limit) {
+ ArrayList candidates = new ArrayList();
+
+ if (query.length() == 0) {
+ return candidates;
+ }
+
+ // Find all words to search for.
+ String[] searchWords = query.split(WHITESPACE_STRING);
+ HashSet candidateSet = null;
+ for (int i = 0; i < searchWords.length; i++) {
+ String word = searchWords[i];
+
+ // Eliminate bogus word choices.
+ if (word.length() == 0 || word.matches(WHITESPACE_STRING)) {
+ continue;
+ }
+
+ // Find the set of candidates that are associated with all the
+ // searchWords.
+ HashSet thisWordChoices = createCandidatesFromWord(word);
+ if (candidateSet == null) {
+ candidateSet = thisWordChoices;
+ } else {
+ candidateSet.retainAll(thisWordChoices);
+
+ if (candidateSet.size() < 2) {
+ // If there is only one candidate, on average it is cheaper to
+ // check if that candidate contains our search string than to
+ // continue intersecting suggestion sets.
+ break;
+ }
+ }
+ }
+ if (candidateSet != null) {
+ candidates.addAll(candidateSet);
+ Collections.sort(candidates);
+ // Respect limit for number of choices.
+ for (int i = candidates.size() - 1; i > limit; i--) {
+ candidates.remove(i);
+ }
+ }
+ return candidates;
+ }
+
+ /**
+ * Creates a set of potential candidates that match the given query.
+ *
+ * @param limit number of candidates to return
+ * @param query query string
+ * @return possible candidates
+ */
+ private HashSet createCandidatesFromWord(String query) {
+ HashSet candidateSet = new HashSet();
+ List words = tree.getSuggestions(query, Integer.MAX_VALUE);
+ if (words != null) {
+ // Find all candidates that contain the given word the search is a
+ // subset of.
+ for (int i = 0; i < words.size(); i++) {
+ Collection belongsTo = (Collection) toCandidates.get(words.get(i));
+ if (belongsTo != null) {
+ candidateSet.addAll(belongsTo);
+ }
+ }
+ }
+ return candidateSet;
+ }
+
+ /**
+ * Normalize the search key by making it lower case, removing multiple spaces,
+ * apply whitespace masks, and make it lower case.
+ */
+ private String normalizeSearch(String search) {
+ // Use the same whitespace masks and case normalization for the search
+ // string as was used with the candidate values.
+ search = normalizeSuggestion(search);
+
+ // Remove all excess whitespace from the search string.
+ search = search.replaceAll(NORMALIZE_TO_SINGLE_WHITE_SPACE,
+ WHITESPACE_STRING);
+
+ return search.trim();
+ }
+
+ /**
+ * Takes the formatted suggestion, makes it lower case and blanks out any
+ * existing whitespace for searching.
+ */
+ private String normalizeSuggestion(String formattedSuggestion) {
+ // Formatted suggestions should already have normalized whitespace. So we
+ // can skip that step.
+
+ // Lower case suggestion.
+ formattedSuggestion = formattedSuggestion.toLowerCase();
+
+ // Apply whitespace.
+ if (whitespaceChars != null) {
+ for (int i = 0; i < whitespaceChars.length; i++) {
+ char ignore = whitespaceChars[i];
+ formattedSuggestion = formattedSuggestion.replace(ignore,
+ WHITESPACE_CHAR);
+ }
+ }
+ return formattedSuggestion;
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/PushButton.java b/user/src/com/google/gwt/user/client/ui/PushButton.java
index 91e9b0f..66a8a80 100644
--- a/user/src/com/google/gwt/user/client/ui/PushButton.java
+++ b/user/src/com/google/gwt/user/client/ui/PushButton.java
@@ -1,170 +1,170 @@
-/*
- * Copyright 2006 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.user.client.DOM;
-import com.google.gwt.user.client.Event;
-
-/**
- * A normal push button with custom styling.
- *
- * <p>
- * <img class='gallery' src='PushButton.png'/>
- * </p>
- *
- * <h3>CSS Style Rules</h3>
- * <ul class="css">
- * <li>.gwt-PushButton-up/down/up-hovering/down-hovering/up-disabled/down-disabled {.html-face}</li>
- * </ul>
- *
- * <p>
- * <h3>Example</h3> {@example com.google.gwt.examples.PushButtonExample}
- * </p>
- */
-public class PushButton extends CustomButton {
-
- private static final String STYLENAME_DEFAULT = "gwt-PushButton";
-
- private boolean waitingForMouseUp = false;
-
- {
- setStyleName(STYLENAME_DEFAULT);
- }
-
- /**
- * Constructor for <code>PushButton</code>.
- */
- public PushButton() {
- super();
- }
-
- /**
- * Constructor for <code>PushButton</code>.
- *
- * @param upImage image for the default(up) face of the button
- */
- public PushButton(Image upImage) {
- super(upImage);
- }
-
- /**
- * Constructor for <code>PushButton</code>.
- *
- * @param upImage image for the default(up) face of the button
- * @param downImage image for the down face of the button
- */
- public PushButton(Image upImage, Image downImage) {
- super(upImage, downImage);
- }
-
- /**
- * Constructor for <code>PushButton</code>.
- *
- * @param upImage image for the default(up) face of the button
- * @param downImage image for the down face of the button
- * @param listener clickListener
- */
- public PushButton(Image upImage, Image downImage, ClickListener listener) {
- super(upImage, listener);
- }
-
- /**
- * Constructor for <code>PushButton</code>. The supplied image is used to
- * construct the default face of the button.
- *
- * @param upImage image for the default (up) face of the button
- * @param listener the click listener
- */
- public PushButton(Image upImage, ClickListener listener) {
- super(upImage, listener);
- }
-
- /**
- * Constructor for <code>PushButton</code>. The supplied text is used to
- * construct the default face of the button.
- *
- * @param upText the text for the default (up) face of the button.
- */
- public PushButton(String upText) {
- super(upText);
- }
-
- /**
- * Constructor for <code>PushButton</code>. The supplied text is used to
- * construct the default face of the button.
- *
- * @param upText the text for the default (up) face of the button
- * @param listener the click listener
- */
- public PushButton(String upText, ClickListener listener) {
- super(upText, listener);
- }
-
- /**
- * Constructor for <code>PushButton</code>.
- *
- * @param upText the text for the default (up) face of the button
- * @param downText the text for down face of the button
- */
- public PushButton(String upText, String downText) {
- super(upText, downText);
- }
-
- /**
- * Constructor for <code>PushButton</code>.
- *
- * @param upText the text for the default (up) face of the button
- * @param downText the text for down face of the button
- * @param listener the click listener
- */
- public PushButton(String upText, String downText, ClickListener listener) {
- super(upText, downText, listener);
- }
- public void onBrowserEvent(Event event) {
- // Should not act on button if the button is disabled. This can happen
- // because an event is bubbled up from a non-disabled interior component.
- if (isEnabled() == false) {
- return;
- }
- int type = DOM.eventGetType(event);
- switch (type) {
- case Event.ONMOUSEDOWN:
- waitingForMouseUp = true;
- setDown(true);
- break;
- case Event.ONCLICK:
- // Must synthesize click events because when we have two separate face
- // elements for up/down, no click events are generated.
- return;
- case Event.ONMOUSEUP:
- if (waitingForMouseUp) {
- fireClickListeners();
- }
- waitingForMouseUp = false;
- setDown(false);
- break;
- case Event.ONMOUSEOUT:
- setDown(false);
- break;
- case Event.ONMOUSEOVER:
- if (waitingForMouseUp) {
- setDown(true);
- }
- }
- super.onBrowserEvent(event);
- }
-}
+/*
+ * Copyright 2006 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.user.client.DOM;
+import com.google.gwt.user.client.Event;
+
+/**
+ * A normal push button with custom styling.
+ *
+ * <p>
+ * <img class='gallery' src='PushButton.png'/>
+ * </p>
+ *
+ * <h3>CSS Style Rules</h3>
+ * <ul class="css">
+ * <li>.gwt-PushButton-up/down/up-hovering/down-hovering/up-disabled/down-disabled {.html-face}</li>
+ * </ul>
+ *
+ * <p>
+ * <h3>Example</h3> {@example com.google.gwt.examples.PushButtonExample}
+ * </p>
+ */
+public class PushButton extends CustomButton {
+
+ private static final String STYLENAME_DEFAULT = "gwt-PushButton";
+
+ private boolean waitingForMouseUp = false;
+
+ {
+ setStyleName(STYLENAME_DEFAULT);
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>.
+ */
+ public PushButton() {
+ super();
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>.
+ *
+ * @param upImage image for the default(up) face of the button
+ */
+ public PushButton(Image upImage) {
+ super(upImage);
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>.
+ *
+ * @param upImage image for the default(up) face of the button
+ * @param downImage image for the down face of the button
+ */
+ public PushButton(Image upImage, Image downImage) {
+ super(upImage, downImage);
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>.
+ *
+ * @param upImage image for the default(up) face of the button
+ * @param downImage image for the down face of the button
+ * @param listener clickListener
+ */
+ public PushButton(Image upImage, Image downImage, ClickListener listener) {
+ super(upImage, listener);
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>. The supplied image is used to
+ * construct the default face of the button.
+ *
+ * @param upImage image for the default (up) face of the button
+ * @param listener the click listener
+ */
+ public PushButton(Image upImage, ClickListener listener) {
+ super(upImage, listener);
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>. The supplied text is used to
+ * construct the default face of the button.
+ *
+ * @param upText the text for the default (up) face of the button.
+ */
+ public PushButton(String upText) {
+ super(upText);
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>. The supplied text is used to
+ * construct the default face of the button.
+ *
+ * @param upText the text for the default (up) face of the button
+ * @param listener the click listener
+ */
+ public PushButton(String upText, ClickListener listener) {
+ super(upText, listener);
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>.
+ *
+ * @param upText the text for the default (up) face of the button
+ * @param downText the text for down face of the button
+ */
+ public PushButton(String upText, String downText) {
+ super(upText, downText);
+ }
+
+ /**
+ * Constructor for <code>PushButton</code>.
+ *
+ * @param upText the text for the default (up) face of the button
+ * @param downText the text for down face of the button
+ * @param listener the click listener
+ */
+ public PushButton(String upText, String downText, ClickListener listener) {
+ super(upText, downText, listener);
+ }
+ public void onBrowserEvent(Event event) {
+ // Should not act on button if the button is disabled. This can happen
+ // because an event is bubbled up from a non-disabled interior component.
+ if (isEnabled() == false) {
+ return;
+ }
+ int type = DOM.eventGetType(event);
+ switch (type) {
+ case Event.ONMOUSEDOWN:
+ waitingForMouseUp = true;
+ setDown(true);
+ break;
+ case Event.ONCLICK:
+ // Must synthesize click events because when we have two separate face
+ // elements for up/down, no click events are generated.
+ return;
+ case Event.ONMOUSEUP:
+ if (waitingForMouseUp) {
+ fireClickListeners();
+ }
+ waitingForMouseUp = false;
+ setDown(false);
+ break;
+ case Event.ONMOUSEOUT:
+ setDown(false);
+ break;
+ case Event.ONMOUSEOVER:
+ if (waitingForMouseUp) {
+ setDown(true);
+ }
+ }
+ super.onBrowserEvent(event);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/RichTextArea.java b/user/src/com/google/gwt/user/client/ui/RichTextArea.java
index 3f9a249..c84c600 100644
--- a/user/src/com/google/gwt/user/client/ui/RichTextArea.java
+++ b/user/src/com/google/gwt/user/client/ui/RichTextArea.java
@@ -1,443 +1,443 @@
-/*
- * Copyright 2007 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.core.client.GWT;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.impl.RichTextAreaImpl;
-
-/**
- * A rich text editor that allows complex styling and formatting.
- *
- * Because some browsers do not support rich text editing, and others support
- * only a limited subset of functionality, there are two formatter interfaces,
- * accessed via {@link #getBasicFormatter()} and {@link #getExtendedFormatter()}. A
- * browser that does not support rich text editing at all will return
- * <code>null</code> for both of these, while one that supports only the basic
- * functionality will return <code>null</code> for the latter.
- *
- * <p>
- * <img class='gallery' src='RichTextArea.png'/>
- * </p>
- *
- * <h3>CSS Style Rules</h3>
- * <ul class="css">
- * <li>.gwt-RichTextArea { }</li>
- * </ul>
- */
-public class RichTextArea extends FocusWidget implements HasHTML,
- SourcesMouseEvents, SourcesChangeEvents {
-
- /**
- * This interface is used to access basic formatting options, when available.
- * If the implementation supports basic formatting, then
- * {@link RichTextArea#getBasicFormatter()} will return an instance of this
- * class.
- */
- public interface BasicFormatter {
-
- /**
- * Gets the background color.
- *
- * @return the background color
- */
- String getBackColor();
-
- /**
- * Gets the foreground color.
- *
- * @return the foreground color
- */
- String getForeColor();
-
- /**
- * Is the current region bold?
- *
- * @return true if the current region is bold
- */
- boolean isBold();
-
- /**
- * Is the current region italic?
- *
- * @return true if the current region is italic
- */
- boolean isItalic();
-
- /**
- * Is the current region subscript?
- *
- * @return true if the current region is subscript
- */
- boolean isSubscript();
-
- /**
- * Is the current region superscript?
- *
- * @return true if the current region is superscript
- */
- boolean isSuperscript();
-
- /**
- * Is the current region underlined?
- *
- * @return true if the current region is underlined
- */
- boolean isUnderlined();
-
- /**
- * Selects all the text.
- */
- void selectAll();
-
- /**
- * Sets the background color.
- *
- * @param color the new background color
- */
- void setBackColor(String color);
-
- /**
- * Sets the font name.
- *
- * @param name the new font name
- */
- void setFontName(String name);
-
- /**
- * Sets the font size.
- *
- * @param fontSize the new font size
- */
- void setFontSize(FontSize fontSize);
-
- /**
- * Sets the foreground color.
- *
- * @param color the new foreground color
- */
- void setForeColor(String color);
-
- /**
- * Sets the justification.
- *
- * @param justification the new justification
- */
- void setJustification(Justification justification);
-
- /**
- * Toggles bold.
- */
- void toggleBold();
-
- /**
- * Toggles italic.
- */
- void toggleItalic();
-
- /**
- * Toggles subscript.
- */
- void toggleSubscript();
-
- /**
- * Toggles superscript.
- */
- void toggleSuperscript();
-
- /**
- * Toggles underline.
- */
- void toggleUnderline();
- }
-
- /**
- * This interface is used to access full formatting options, when available.
- * If the implementation supports full formatting, then
- * {@link RichTextArea#getExtendedFormatter()} will return an instance of this
- * class.
- */
- public interface ExtendedFormatter extends BasicFormatter {
-
- /**
- * Creates a link to the supplied URL.
- *
- * @param url the URL to be linked to
- */
- void createLink(String url);
-
- /**
- * Inserts a horizontal rule.
- */
- void insertHorizontalRule();
-
- /**
- * Inserts an image element.
- *
- * @param url the url of the image to be inserted
- */
- void insertImage(String url);
-
- /**
- * Starts an numbered list. Indentation will create nested items.
- */
- void insertOrderedList();
-
- /**
- * Starts an bulleted list. Indentation will create nested items.
- */
- void insertUnorderedList();
-
- /**
- * Is the current region strikethrough?
- *
- * @return true if the current region is strikethrough
- */
- boolean isStrikethrough();
-
- /**
- * Left indent.
- */
- void leftIndent();
-
- /**
- * Removes all formatting on the selected text.
- */
- void removeFormat();
-
- /**
- * Removes any link from the selected text.
- */
- void removeLink();
-
- /**
- * Right indent.
- */
- void rightIndent();
-
- /**
- * Toggles strikethrough.
- */
- void toggleStrikethrough();
- }
-
- /**
- * Font size enumeration. Represents the seven basic HTML font sizes, as
- * defined in CSS.
- */
- public static class FontSize {
-
- /**
- * Represents an XX-Small font.
- */
- public static final FontSize XX_SMALL = new FontSize(1);
-
- /**
- * Represents an X-Small font.
- */
- public static final FontSize X_SMALL = new FontSize(2);
-
- /**
- * Represents a Small font.
- */
- public static final FontSize SMALL = new FontSize(3);
-
- /**
- * Represents a Medium font.
- */
- public static final FontSize MEDIUM = new FontSize(4);
-
- /**
- * Represents a Large font.
- */
- public static final FontSize LARGE = new FontSize(5);
-
- /**
- * Represents an X-Large font.
- */
- public static final FontSize X_LARGE = new FontSize(6);
-
- /**
- * Represents an XX-Large font.
- */
- public static final FontSize XX_LARGE = new FontSize(7);
-
- private int number;
-
- private FontSize(int number) {
- this.number = number;
- }
-
- /**
- * Gets the HTML font number associated with this font size.
- *
- * @return an integer from 1 to 7 inclusive
- */
- public int getNumber() {
- return number;
- }
- }
-
- /**
- * Justification enumeration. The three values are <code>left</code>,
- * <code>right</code>, <code>center</code>.
- */
- public static class Justification {
-
- /**
- * Center justification.
- */
- public static final Justification CENTER = new Justification("Center");
-
- /**
- * Left justification.
- */
- public static final Justification LEFT = new Justification("Left");
-
- /**
- * Right justification.
- */
- public static final Justification RIGHT = new Justification("Right");
-
- private String tag;
-
- private Justification(String tag) {
- this.tag = tag;
- }
-
- public String toString() {
- return "Justify " + tag;
- }
- }
-
- private RichTextAreaImpl impl = (RichTextAreaImpl) GWT.create(RichTextAreaImpl.class);
- private ChangeListenerCollection changeListeners;
- private MouseListenerCollection mouseListeners;
-
- /**
- * Creates a new, blank {@link RichTextArea} object with no stylesheet.
- */
- public RichTextArea() {
- setElement(impl.getElement());
- setStyleName("gwt-RichTextArea");
- }
-
- public void addChangeListener(ChangeListener listener) {
- if (changeListeners == null) {
- changeListeners = new ChangeListenerCollection();
- }
- changeListeners.add(listener);
- }
-
- public void addMouseListener(MouseListener listener) {
- if (mouseListeners == null) {
- mouseListeners = new MouseListenerCollection();
- }
- mouseListeners.add(listener);
- }
-
- /**
- * Gets the basic rich text formatting interface.
- *
- * @return <code>null</code> if basic formatting is not supported
- */
- public BasicFormatter getBasicFormatter() {
- if ((impl instanceof BasicFormatter) && (impl.isBasicEditingSupported())) {
- return (BasicFormatter) impl;
- }
- return null;
- }
-
- /**
- * Gets the full rich text formatting interface.
- *
- * @return <code>null</code> if full formatting is not supported
- */
- public ExtendedFormatter getExtendedFormatter() {
- if ((impl instanceof ExtendedFormatter)
- && (impl.isExtendedEditingSupported())) {
- return (ExtendedFormatter) impl;
- }
- return null;
- }
-
- public String getHTML() {
- return impl.getHTML();
- }
-
- public String getText() {
- return impl.getText();
- }
-
- public void onBrowserEvent(Event event) {
- switch (DOM.eventGetType(event)) {
- case Event.ONMOUSEDOWN:
- case Event.ONMOUSEUP:
- case Event.ONMOUSEMOVE:
- case Event.ONMOUSEOVER:
- case Event.ONMOUSEOUT:
- if (mouseListeners != null) {
- mouseListeners.fireMouseEvent(this, event);
- }
- break;
-
- case Event.ONCHANGE:
- if (changeListeners != null) {
- changeListeners.fireChange(this);
- }
- break;
-
- default:
- super.onBrowserEvent(event);
- }
- }
-
- public void removeChangeListener(ChangeListener listener) {
- if (changeListeners != null) {
- changeListeners.remove(listener);
- }
- }
-
- public void removeMouseListener(MouseListener listener) {
- if (mouseListeners != null) {
- mouseListeners.remove(listener);
- }
- }
-
- public void setFocus(boolean focused) {
- impl.setFocus(focused);
- }
-
- public void setHTML(String html) {
- impl.setHTML(html);
- }
-
- public void setText(String text) {
- impl.setText(text);
- }
-
- protected void onAttach() {
- super.onAttach();
- impl.initElement();
- impl.hookEvents(this);
- }
-
- protected void onDetach() {
- super.onDetach();
- impl.unhookEvents(this);
- }
-}
+/*
+ * Copyright 2007 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.core.client.GWT;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.impl.RichTextAreaImpl;
+
+/**
+ * A rich text editor that allows complex styling and formatting.
+ *
+ * Because some browsers do not support rich text editing, and others support
+ * only a limited subset of functionality, there are two formatter interfaces,
+ * accessed via {@link #getBasicFormatter()} and {@link #getExtendedFormatter()}. A
+ * browser that does not support rich text editing at all will return
+ * <code>null</code> for both of these, while one that supports only the basic
+ * functionality will return <code>null</code> for the latter.
+ *
+ * <p>
+ * <img class='gallery' src='RichTextArea.png'/>
+ * </p>
+ *
+ * <h3>CSS Style Rules</h3>
+ * <ul class="css">
+ * <li>.gwt-RichTextArea { }</li>
+ * </ul>
+ */
+public class RichTextArea extends FocusWidget implements HasHTML,
+ SourcesMouseEvents, SourcesChangeEvents {
+
+ /**
+ * This interface is used to access basic formatting options, when available.
+ * If the implementation supports basic formatting, then
+ * {@link RichTextArea#getBasicFormatter()} will return an instance of this
+ * class.
+ */
+ public interface BasicFormatter {
+
+ /**
+ * Gets the background color.
+ *
+ * @return the background color
+ */
+ String getBackColor();
+
+ /**
+ * Gets the foreground color.
+ *
+ * @return the foreground color
+ */
+ String getForeColor();
+
+ /**
+ * Is the current region bold?
+ *
+ * @return true if the current region is bold
+ */
+ boolean isBold();
+
+ /**
+ * Is the current region italic?
+ *
+ * @return true if the current region is italic
+ */
+ boolean isItalic();
+
+ /**
+ * Is the current region subscript?
+ *
+ * @return true if the current region is subscript
+ */
+ boolean isSubscript();
+
+ /**
+ * Is the current region superscript?
+ *
+ * @return true if the current region is superscript
+ */
+ boolean isSuperscript();
+
+ /**
+ * Is the current region underlined?
+ *
+ * @return true if the current region is underlined
+ */
+ boolean isUnderlined();
+
+ /**
+ * Selects all the text.
+ */
+ void selectAll();
+
+ /**
+ * Sets the background color.
+ *
+ * @param color the new background color
+ */
+ void setBackColor(String color);
+
+ /**
+ * Sets the font name.
+ *
+ * @param name the new font name
+ */
+ void setFontName(String name);
+
+ /**
+ * Sets the font size.
+ *
+ * @param fontSize the new font size
+ */
+ void setFontSize(FontSize fontSize);
+
+ /**
+ * Sets the foreground color.
+ *
+ * @param color the new foreground color
+ */
+ void setForeColor(String color);
+
+ /**
+ * Sets the justification.
+ *
+ * @param justification the new justification
+ */
+ void setJustification(Justification justification);
+
+ /**
+ * Toggles bold.
+ */
+ void toggleBold();
+
+ /**
+ * Toggles italic.
+ */
+ void toggleItalic();
+
+ /**
+ * Toggles subscript.
+ */
+ void toggleSubscript();
+
+ /**
+ * Toggles superscript.
+ */
+ void toggleSuperscript();
+
+ /**
+ * Toggles underline.
+ */
+ void toggleUnderline();
+ }
+
+ /**
+ * This interface is used to access full formatting options, when available.
+ * If the implementation supports full formatting, then
+ * {@link RichTextArea#getExtendedFormatter()} will return an instance of this
+ * class.
+ */
+ public interface ExtendedFormatter extends BasicFormatter {
+
+ /**
+ * Creates a link to the supplied URL.
+ *
+ * @param url the URL to be linked to
+ */
+ void createLink(String url);
+
+ /**
+ * Inserts a horizontal rule.
+ */
+ void insertHorizontalRule();
+
+ /**
+ * Inserts an image element.
+ *
+ * @param url the url of the image to be inserted
+ */
+ void insertImage(String url);
+
+ /**
+ * Starts an numbered list. Indentation will create nested items.
+ */
+ void insertOrderedList();
+
+ /**
+ * Starts an bulleted list. Indentation will create nested items.
+ */
+ void insertUnorderedList();
+
+ /**
+ * Is the current region strikethrough?
+ *
+ * @return true if the current region is strikethrough
+ */
+ boolean isStrikethrough();
+
+ /**
+ * Left indent.
+ */
+ void leftIndent();
+
+ /**
+ * Removes all formatting on the selected text.
+ */
+ void removeFormat();
+
+ /**
+ * Removes any link from the selected text.
+ */
+ void removeLink();
+
+ /**
+ * Right indent.
+ */
+ void rightIndent();
+
+ /**
+ * Toggles strikethrough.
+ */
+ void toggleStrikethrough();
+ }
+
+ /**
+ * Font size enumeration. Represents the seven basic HTML font sizes, as
+ * defined in CSS.
+ */
+ public static class FontSize {
+
+ /**
+ * Represents an XX-Small font.
+ */
+ public static final FontSize XX_SMALL = new FontSize(1);
+
+ /**
+ * Represents an X-Small font.
+ */
+ public static final FontSize X_SMALL = new FontSize(2);
+
+ /**
+ * Represents a Small font.
+ */
+ public static final FontSize SMALL = new FontSize(3);
+
+ /**
+ * Represents a Medium font.
+ */
+ public static final FontSize MEDIUM = new FontSize(4);
+
+ /**
+ * Represents a Large font.
+ */
+ public static final FontSize LARGE = new FontSize(5);
+
+ /**
+ * Represents an X-Large font.
+ */
+ public static final FontSize X_LARGE = new FontSize(6);
+
+ /**
+ * Represents an XX-Large font.
+ */
+ public static final FontSize XX_LARGE = new FontSize(7);
+
+ private int number;
+
+ private FontSize(int number) {
+ this.number = number;
+ }
+
+ /**
+ * Gets the HTML font number associated with this font size.
+ *
+ * @return an integer from 1 to 7 inclusive
+ */
+ public int getNumber() {
+ return number;
+ }
+ }
+
+ /**
+ * Justification enumeration. The three values are <code>left</code>,
+ * <code>right</code>, <code>center</code>.
+ */
+ public static class Justification {
+
+ /**
+ * Center justification.
+ */
+ public static final Justification CENTER = new Justification("Center");
+
+ /**
+ * Left justification.
+ */
+ public static final Justification LEFT = new Justification("Left");
+
+ /**
+ * Right justification.
+ */
+ public static final Justification RIGHT = new Justification("Right");
+
+ private String tag;
+
+ private Justification(String tag) {
+ this.tag = tag;
+ }
+
+ public String toString() {
+ return "Justify " + tag;
+ }
+ }
+
+ private RichTextAreaImpl impl = (RichTextAreaImpl) GWT.create(RichTextAreaImpl.class);
+ private ChangeListenerCollection changeListeners;
+ private MouseListenerCollection mouseListeners;
+
+ /**
+ * Creates a new, blank {@link RichTextArea} object with no stylesheet.
+ */
+ public RichTextArea() {
+ setElement(impl.getElement());
+ setStyleName("gwt-RichTextArea");
+ }
+
+ public void addChangeListener(ChangeListener listener) {
+ if (changeListeners == null) {
+ changeListeners = new ChangeListenerCollection();
+ }
+ changeListeners.add(listener);
+ }
+
+ public void addMouseListener(MouseListener listener) {
+ if (mouseListeners == null) {
+ mouseListeners = new MouseListenerCollection();
+ }
+ mouseListeners.add(listener);
+ }
+
+ /**
+ * Gets the basic rich text formatting interface.
+ *
+ * @return <code>null</code> if basic formatting is not supported
+ */
+ public BasicFormatter getBasicFormatter() {
+ if ((impl instanceof BasicFormatter) && (impl.isBasicEditingSupported())) {
+ return (BasicFormatter) impl;
+ }
+ return null;
+ }
+
+ /**
+ * Gets the full rich text formatting interface.
+ *
+ * @return <code>null</code> if full formatting is not supported
+ */
+ public ExtendedFormatter getExtendedFormatter() {
+ if ((impl instanceof ExtendedFormatter)
+ && (impl.isExtendedEditingSupported())) {
+ return (ExtendedFormatter) impl;
+ }
+ return null;
+ }
+
+ public String getHTML() {
+ return impl.getHTML();
+ }
+
+ public String getText() {
+ return impl.getText();
+ }
+
+ public void onBrowserEvent(Event event) {
+ switch (DOM.eventGetType(event)) {
+ case Event.ONMOUSEDOWN:
+ case Event.ONMOUSEUP:
+ case Event.ONMOUSEMOVE:
+ case Event.ONMOUSEOVER:
+ case Event.ONMOUSEOUT:
+ if (mouseListeners != null) {
+ mouseListeners.fireMouseEvent(this, event);
+ }
+ break;
+
+ case Event.ONCHANGE:
+ if (changeListeners != null) {
+ changeListeners.fireChange(this);
+ }
+ break;
+
+ default:
+ super.onBrowserEvent(event);
+ }
+ }
+
+ public void removeChangeListener(ChangeListener listener) {
+ if (changeListeners != null) {
+ changeListeners.remove(listener);
+ }
+ }
+
+ public void removeMouseListener(MouseListener listener) {
+ if (mouseListeners != null) {
+ mouseListeners.remove(listener);
+ }
+ }
+
+ public void setFocus(boolean focused) {
+ impl.setFocus(focused);
+ }
+
+ public void setHTML(String html) {
+ impl.setHTML(html);
+ }
+
+ public void setText(String text) {
+ impl.setText(text);
+ }
+
+ protected void onAttach() {
+ super.onAttach();
+ impl.initElement();
+ impl.hookEvents(this);
+ }
+
+ protected void onDetach() {
+ super.onDetach();
+ impl.unhookEvents(this);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestBox.java b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
index d0e1fe6..6af0ec7 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestBox.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
@@ -1,411 +1,411 @@
-/*
- * Copyright 2007 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.user.client.ui.SuggestOracle.Callback;
-import com.google.gwt.user.client.ui.SuggestOracle.Request;
-import com.google.gwt.user.client.ui.SuggestOracle.Response;
-import com.google.gwt.user.client.ui.impl.ItemPickerDropDownImpl;
-import com.google.gwt.user.client.ui.impl.SuggestPickerImpl;
-
-import java.util.Collection;
-
-/**
- * A {@link SuggestBox} is a text box or text area which displays a
- * pre-configured set of selections that match the user's input.
- *
- * Each {@link SuggestBox} is associated with a single {@link SuggestOracle}.
- * The {@link SuggestOracle} is used to provide a set of selections given a
- * specific query string.
- *
- * <p>
- * By default, the {@link SuggestBox} uses a {@link MultiWordSuggestOracle} as
- * its oracle. Below we show how a {@link MultiWordSuggestOracle} can be
- * configured:
- * </p>
- *
- * <pre>
- * MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
- * oracle.add("Cat");
- * oracle.add("Dog");
- * oracle.add("Horse");
- * oracle.add("Canary");
- *
- * SuggestBox box = new SuggestBox(oracle);
- * </pre>
- *
- * Using the example above, if the user types "C" into the text widget, the
- * oracle will configure the suggestions with the "Cat" and "Canary"
- * suggestions. Specifically, whenever the user types a key into the text
- * widget, the value is submitted to the <code>MultiWordSuggestOracle</code>.
- *
- * <p>
- * <img class='gallery' src='SuggestBox.png'/>
- * </p>
- *
- * <h3>CSS Style Rules</h3>
- * <ul class='css'>
- * <li>.gwt-SuggestBox { the suggest box itself }</li>
- * <li>.gwt-SuggestBoxPopup { the suggestion popup }</li>
- * <li>.gwt-SuggestBoxPopup .item { an unselected suggestion }</li>
- * <li>.gwt-SuggestBoxPopup .item-selected { a selected suggestion }</li>
- * </ul>
- *
- * @see SuggestOracle, MultiWordSuggestOracle, TextBoxBase
- */
-public final class SuggestBox extends Composite implements HasText, HasFocus,
- SourcesClickEvents, SourcesFocusEvents, SourcesChangeEvents,
- SourcesKeyboardEvents {
-
- private static final String STYLENAME_DEFAULT = "gwt-SuggestBox";
-
- private int limit = 20;
- private int selectStart;
- private int selectEnd;
- private SuggestOracle oracle;
- private char[] separators;
- private String currentValue;
- private final PopupPanel popup;
- private final SuggestPickerImpl picker;
- private final TextBoxBase box;
- private DelegatingClickListenerCollection clickListeners;
- private DelegatingChangeListenerCollection changeListeners;
- private DelegatingFocusListenerCollection focusListeners;
- private DelegatingKeyboardListenerCollection keyboardListeners;
- private String separatorPadding = "";
-
- private final Callback callBack = new Callback() {
- public void onSuggestionsReady(Request request, Response response) {
- showSuggestions(response.getSuggestions());
- }
- };
-
- /**
- * Constructor for {@link SuggestBox}. Creates a
- * {@link MultiWordSuggestOracle} and {@link TextBox} to use with this
- * {@link SuggestBox}.
- */
- public SuggestBox() {
- this(new MultiWordSuggestOracle());
- }
-
- /**
- * Constructor for {@link SuggestBox}. Creates a {@link TextBox} to use with
- * this {@link SuggestBox}.
- *
- * @param oracle the oracle for this <code>SuggestBox</code>
- */
- public SuggestBox(SuggestOracle oracle) {
- this(oracle, new TextBox());
- }
-
- /**
- * Constructor for {@link SuggestBox}. The text box will be removed from it's
- * current location and wrapped by the {@link SuggestBox}.
- *
- * @param oracle supplies suggestions based upon the current contents of the
- * text widget
- * @param box the text widget
- */
- public SuggestBox(SuggestOracle oracle, TextBoxBase box) {
- this.box = box;
- initWidget(box);
- this.picker = new SuggestPickerImpl(oracle.isDisplayStringHTML());
- this.popup = new ItemPickerDropDownImpl(this, picker);
- addPopupChangeListener();
- addKeyboardSupport();
- setOracle(oracle);
- setStyleName(STYLENAME_DEFAULT);
- }
-
- public final void addChangeListener(ChangeListener listener) {
- if (changeListeners == null) {
- changeListeners = new DelegatingChangeListenerCollection(this, box);
- }
- changeListeners.add(listener);
- }
-
- public final void addClickListener(ClickListener listener) {
- if (clickListeners == null) {
- clickListeners = new DelegatingClickListenerCollection(this, box);
- }
- clickListeners.add(listener);
- }
-
- public final void addFocusListener(FocusListener listener) {
- if (focusListeners == null) {
- focusListeners = new DelegatingFocusListenerCollection(this, box);
- }
- focusListeners.add(listener);
- }
-
- public final void addKeyboardListener(KeyboardListener listener) {
- if (keyboardListeners == null) {
- keyboardListeners = new DelegatingKeyboardListenerCollection(this, box);
- }
- keyboardListeners.add(listener);
- }
-
- /**
- * Gets the limit for the number of suggestions that should be displayed for
- * this box. It is up to the current {@link SuggestOracle} to enforce this
- * limit.
- *
- * @return the limit for the number of suggestions
- */
- public final int getLimit() {
- return limit;
- }
-
- /**
- * Gets the suggest box's {@link com.google.gwt.user.client.ui.SuggestOracle}.
- *
- * @return the {@link SuggestOracle}
- */
- public final SuggestOracle getSuggestOracle() {
- return oracle;
- }
-
- public final int getTabIndex() {
- return box.getTabIndex();
- }
-
- public final String getText() {
- return box.getText();
- }
-
- public final void removeChangeListener(ChangeListener listener) {
- if (clickListeners != null) {
- clickListeners.remove(listener);
- }
- }
-
- public final void removeClickListener(ClickListener listener) {
- if (clickListeners != null) {
- clickListeners.remove(listener);
- }
- }
-
- public final void removeFocusListener(FocusListener listener) {
- if (focusListeners != null) {
- focusListeners.remove(listener);
- }
- }
-
- public final void removeKeyboardListener(KeyboardListener listener) {
- if (keyboardListeners != null) {
- keyboardListeners.remove(listener);
- }
- }
-
- public final void setAccessKey(char key) {
- box.setAccessKey(key);
- }
-
- public final void setFocus(boolean focused) {
- box.setFocus(focused);
- }
-
- /**
- * Sets the limit to the number of suggestions the oracle should provide. It
- * is up to the oracle to enforce this limit.
- *
- * @param limit the limit to the number of suggestions provided
- */
- public final void setLimit(int limit) {
- this.limit = limit;
- }
-
- public final void setTabIndex(int index) {
- box.setTabIndex(index);
- }
-
- public final void setText(String text) {
- box.setText(text);
- }
-
- /**
- * Show the given collection of suggestions.
- *
- * @param suggestions suggestions to show
- */
- private void showSuggestions(Collection suggestions) {
- if (suggestions.size() > 0) {
- picker.setItems(suggestions);
- popup.show();
- } else {
- popup.hide();
- }
- }
-
- private void addKeyboardSupport() {
- box.addKeyboardListener(new KeyboardListenerAdapter() {
- private boolean pendingCancel;
-
- public void onKeyDown(Widget sender, char keyCode, int modifiers) {
- pendingCancel = picker.delegateKeyDown(keyCode);
- }
-
- public void onKeyPress(Widget sender, char keyCode, int modifiers) {
- if (pendingCancel) {
- // IE does not allow cancel key on key down, so we have delayed the
- // cancellation of the key until the associated key press.
- box.cancelKey();
- pendingCancel = false;
- } else if (popup.isAttached()) {
- if (separators != null && isSeparator(keyCode)) {
- // onKeyDown/onKeyUps's keyCode for ',' comes back '1/4', so unlike
- // navigation, we use key press events to determine when the user
- // wants to simulate clicking on the popup.
- picker.commitSelection();
-
- // The separator will be added after the popup is activated, so the
- // popup will have already added a new separator. Therefore, the
- // original separator should not be added as well.
- box.cancelKey();
- }
- }
- }
-
- public void onKeyUp(Widget sender, char keyCode, int modifiers) {
- // After every user key input, refresh the popup's suggestions.
- refreshSuggestions();
- }
-
- /**
- * In the presence of separators, returns the active search selection.
- */
- private String getActiveSelection(String text) {
- selectEnd = box.getCursorPos();
-
- // Find the last instance of a separator.
- selectStart = -1;
- for (int i = 0; i < separators.length; i++) {
- selectStart = Math.max(
- text.lastIndexOf(separators[i], selectEnd - 1), selectStart);
- }
- ++selectStart;
-
- return text.substring(selectStart, selectEnd).trim();
- }
-
- private void refreshSuggestions() {
- // Get the raw text.
- String text = box.getText();
- if (text.equals(currentValue)) {
- return;
- } else {
- currentValue = text;
- }
-
- // Find selection to replace.
- String selection;
- if (separators == null) {
- selection = text;
- } else {
- selection = getActiveSelection(text);
- }
- // If we have no text, let's not show the suggestions.
- if (selection.length() == 0) {
- popup.hide();
- } else {
- showSuggestions(selection);
- }
- }
- });
- }
-
- /**
- * Adds a standard popup listener to the suggest box's popup.
- */
- private void addPopupChangeListener() {
- picker.addChangeListener(new ChangeListener() {
- public void onChange(Widget sender) {
- if (separators != null) {
- onChangeWithSeparators();
- } else {
- currentValue = picker.getSelectedValue().toString();
- box.setText(currentValue);
- }
- if (changeListeners != null) {
- changeListeners.fireChange(SuggestBox.this);
- }
- }
-
- private void onChangeWithSeparators() {
- String newValue = (String) picker.getSelectedValue();
-
- StringBuffer accum = new StringBuffer();
- String text = box.getText();
-
- // Add all text up to the selection start.
- accum.append(text.substring(0, selectStart));
-
- // Add one space if not at start.
- if (selectStart > 0) {
- accum.append(separatorPadding);
- }
- // Add the new value.
- accum.append(newValue);
-
- // Find correct cursor position.
- int savedCursorPos = accum.length();
-
- // Add all text after the selection end
- String ender = text.substring(selectEnd).trim();
- if (ender.length() == 0 || !isSeparator(ender.charAt(0))) {
- // Add a separator if the first char of the ender is not already a
- // separator.
- accum.append(separators[0]).append(separatorPadding);
- savedCursorPos = accum.length();
- }
- accum.append(ender);
-
- // Set the text and cursor pos to correct location.
- String replacement = accum.toString();
- currentValue = replacement.trim();
- box.setText(replacement);
- box.setCursorPos(savedCursorPos);
- }
- });
- }
-
- /**
- * Convenience method for identifying if a character is a separator.
- */
- private boolean isSeparator(char candidate) {
- // An int map would be very handy right here...
- for (int i = 0; i < separators.length; i++) {
- if (candidate == separators[i]) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Sets the suggestion oracle used to create suggestions.
- *
- * @param oracle the oracle
- */
- private void setOracle(SuggestOracle oracle) {
- this.oracle = oracle;
- }
-
- private void showSuggestions(String query) {
- oracle.requestSuggestions(new Request(query, limit), callBack);
- }
-}
+/*
+ * Copyright 2007 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.user.client.ui.SuggestOracle.Callback;
+import com.google.gwt.user.client.ui.SuggestOracle.Request;
+import com.google.gwt.user.client.ui.SuggestOracle.Response;
+import com.google.gwt.user.client.ui.impl.ItemPickerDropDownImpl;
+import com.google.gwt.user.client.ui.impl.SuggestPickerImpl;
+
+import java.util.Collection;
+
+/**
+ * A {@link SuggestBox} is a text box or text area which displays a
+ * pre-configured set of selections that match the user's input.
+ *
+ * Each {@link SuggestBox} is associated with a single {@link SuggestOracle}.
+ * The {@link SuggestOracle} is used to provide a set of selections given a
+ * specific query string.
+ *
+ * <p>
+ * By default, the {@link SuggestBox} uses a {@link MultiWordSuggestOracle} as
+ * its oracle. Below we show how a {@link MultiWordSuggestOracle} can be
+ * configured:
+ * </p>
+ *
+ * <pre>
+ * MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
+ * oracle.add("Cat");
+ * oracle.add("Dog");
+ * oracle.add("Horse");
+ * oracle.add("Canary");
+ *
+ * SuggestBox box = new SuggestBox(oracle);
+ * </pre>
+ *
+ * Using the example above, if the user types "C" into the text widget, the
+ * oracle will configure the suggestions with the "Cat" and "Canary"
+ * suggestions. Specifically, whenever the user types a key into the text
+ * widget, the value is submitted to the <code>MultiWordSuggestOracle</code>.
+ *
+ * <p>
+ * <img class='gallery' src='SuggestBox.png'/>
+ * </p>
+ *
+ * <h3>CSS Style Rules</h3>
+ * <ul class='css'>
+ * <li>.gwt-SuggestBox { the suggest box itself }</li>
+ * <li>.gwt-SuggestBoxPopup { the suggestion popup }</li>
+ * <li>.gwt-SuggestBoxPopup .item { an unselected suggestion }</li>
+ * <li>.gwt-SuggestBoxPopup .item-selected { a selected suggestion }</li>
+ * </ul>
+ *
+ * @see SuggestOracle, MultiWordSuggestOracle, TextBoxBase
+ */
+public final class SuggestBox extends Composite implements HasText, HasFocus,
+ SourcesClickEvents, SourcesFocusEvents, SourcesChangeEvents,
+ SourcesKeyboardEvents {
+
+ private static final String STYLENAME_DEFAULT = "gwt-SuggestBox";
+
+ private int limit = 20;
+ private int selectStart;
+ private int selectEnd;
+ private SuggestOracle oracle;
+ private char[] separators;
+ private String currentValue;
+ private final PopupPanel popup;
+ private final SuggestPickerImpl picker;
+ private final TextBoxBase box;
+ private DelegatingClickListenerCollection clickListeners;
+ private DelegatingChangeListenerCollection changeListeners;
+ private DelegatingFocusListenerCollection focusListeners;
+ private DelegatingKeyboardListenerCollection keyboardListeners;
+ private String separatorPadding = "";
+
+ private final Callback callBack = new Callback() {
+ public void onSuggestionsReady(Request request, Response response) {
+ showSuggestions(response.getSuggestions());
+ }
+ };
+
+ /**
+ * Constructor for {@link SuggestBox}. Creates a
+ * {@link MultiWordSuggestOracle} and {@link TextBox} to use with this
+ * {@link SuggestBox}.
+ */
+ public SuggestBox() {
+ this(new MultiWordSuggestOracle());
+ }
+
+ /**
+ * Constructor for {@link SuggestBox}. Creates a {@link TextBox} to use with
+ * this {@link SuggestBox}.
+ *
+ * @param oracle the oracle for this <code>SuggestBox</code>
+ */
+ public SuggestBox(SuggestOracle oracle) {
+ this(oracle, new TextBox());
+ }
+
+ /**
+ * Constructor for {@link SuggestBox}. The text box will be removed from it's
+ * current location and wrapped by the {@link SuggestBox}.
+ *
+ * @param oracle supplies suggestions based upon the current contents of the
+ * text widget
+ * @param box the text widget
+ */
+ public SuggestBox(SuggestOracle oracle, TextBoxBase box) {
+ this.box = box;
+ initWidget(box);
+ this.picker = new SuggestPickerImpl(oracle.isDisplayStringHTML());
+ this.popup = new ItemPickerDropDownImpl(this, picker);
+ addPopupChangeListener();
+ addKeyboardSupport();
+ setOracle(oracle);
+ setStyleName(STYLENAME_DEFAULT);
+ }
+
+ public final void addChangeListener(ChangeListener listener) {
+ if (changeListeners == null) {
+ changeListeners = new DelegatingChangeListenerCollection(this, box);
+ }
+ changeListeners.add(listener);
+ }
+
+ public final void addClickListener(ClickListener listener) {
+ if (clickListeners == null) {
+ clickListeners = new DelegatingClickListenerCollection(this, box);
+ }
+ clickListeners.add(listener);
+ }
+
+ public final void addFocusListener(FocusListener listener) {
+ if (focusListeners == null) {
+ focusListeners = new DelegatingFocusListenerCollection(this, box);
+ }
+ focusListeners.add(listener);
+ }
+
+ public final void addKeyboardListener(KeyboardListener listener) {
+ if (keyboardListeners == null) {
+ keyboardListeners = new DelegatingKeyboardListenerCollection(this, box);
+ }
+ keyboardListeners.add(listener);
+ }
+
+ /**
+ * Gets the limit for the number of suggestions that should be displayed for
+ * this box. It is up to the current {@link SuggestOracle} to enforce this
+ * limit.
+ *
+ * @return the limit for the number of suggestions
+ */
+ public final int getLimit() {
+ return limit;
+ }
+
+ /**
+ * Gets the suggest box's {@link com.google.gwt.user.client.ui.SuggestOracle}.
+ *
+ * @return the {@link SuggestOracle}
+ */
+ public final SuggestOracle getSuggestOracle() {
+ return oracle;
+ }
+
+ public final int getTabIndex() {
+ return box.getTabIndex();
+ }
+
+ public final String getText() {
+ return box.getText();
+ }
+
+ public final void removeChangeListener(ChangeListener listener) {
+ if (clickListeners != null) {
+ clickListeners.remove(listener);
+ }
+ }
+
+ public final void removeClickListener(ClickListener listener) {
+ if (clickListeners != null) {
+ clickListeners.remove(listener);
+ }
+ }
+
+ public final void removeFocusListener(FocusListener listener) {
+ if (focusListeners != null) {
+ focusListeners.remove(listener);
+ }
+ }
+
+ public final void removeKeyboardListener(KeyboardListener listener) {
+ if (keyboardListeners != null) {
+ keyboardListeners.remove(listener);
+ }
+ }
+
+ public final void setAccessKey(char key) {
+ box.setAccessKey(key);
+ }
+
+ public final void setFocus(boolean focused) {
+ box.setFocus(focused);
+ }
+
+ /**
+ * Sets the limit to the number of suggestions the oracle should provide. It
+ * is up to the oracle to enforce this limit.
+ *
+ * @param limit the limit to the number of suggestions provided
+ */
+ public final void setLimit(int limit) {
+ this.limit = limit;
+ }
+
+ public final void setTabIndex(int index) {
+ box.setTabIndex(index);
+ }
+
+ public final void setText(String text) {
+ box.setText(text);
+ }
+
+ /**
+ * Show the given collection of suggestions.
+ *
+ * @param suggestions suggestions to show
+ */
+ private void showSuggestions(Collection suggestions) {
+ if (suggestions.size() > 0) {
+ picker.setItems(suggestions);
+ popup.show();
+ } else {
+ popup.hide();
+ }
+ }
+
+ private void addKeyboardSupport() {
+ box.addKeyboardListener(new KeyboardListenerAdapter() {
+ private boolean pendingCancel;
+
+ public void onKeyDown(Widget sender, char keyCode, int modifiers) {
+ pendingCancel = picker.delegateKeyDown(keyCode);
+ }
+
+ public void onKeyPress(Widget sender, char keyCode, int modifiers) {
+ if (pendingCancel) {
+ // IE does not allow cancel key on key down, so we have delayed the
+ // cancellation of the key until the associated key press.
+ box.cancelKey();
+ pendingCancel = false;
+ } else if (popup.isAttached()) {
+ if (separators != null && isSeparator(keyCode)) {
+ // onKeyDown/onKeyUps's keyCode for ',' comes back '1/4', so unlike
+ // navigation, we use key press events to determine when the user
+ // wants to simulate clicking on the popup.
+ picker.commitSelection();
+
+ // The separator will be added after the popup is activated, so the
+ // popup will have already added a new separator. Therefore, the
+ // original separator should not be added as well.
+ box.cancelKey();
+ }
+ }
+ }
+
+ public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+ // After every user key input, refresh the popup's suggestions.
+ refreshSuggestions();
+ }
+
+ /**
+ * In the presence of separators, returns the active search selection.
+ */
+ private String getActiveSelection(String text) {
+ selectEnd = box.getCursorPos();
+
+ // Find the last instance of a separator.
+ selectStart = -1;
+ for (int i = 0; i < separators.length; i++) {
+ selectStart = Math.max(
+ text.lastIndexOf(separators[i], selectEnd - 1), selectStart);
+ }
+ ++selectStart;
+
+ return text.substring(selectStart, selectEnd).trim();
+ }
+
+ private void refreshSuggestions() {
+ // Get the raw text.
+ String text = box.getText();
+ if (text.equals(currentValue)) {
+ return;
+ } else {
+ currentValue = text;
+ }
+
+ // Find selection to replace.
+ String selection;
+ if (separators == null) {
+ selection = text;
+ } else {
+ selection = getActiveSelection(text);
+ }
+ // If we have no text, let's not show the suggestions.
+ if (selection.length() == 0) {
+ popup.hide();
+ } else {
+ showSuggestions(selection);
+ }
+ }
+ });
+ }
+
+ /**
+ * Adds a standard popup listener to the suggest box's popup.
+ */
+ private void addPopupChangeListener() {
+ picker.addChangeListener(new ChangeListener() {
+ public void onChange(Widget sender) {
+ if (separators != null) {
+ onChangeWithSeparators();
+ } else {
+ currentValue = picker.getSelectedValue().toString();
+ box.setText(currentValue);
+ }
+ if (changeListeners != null) {
+ changeListeners.fireChange(SuggestBox.this);
+ }
+ }
+
+ private void onChangeWithSeparators() {
+ String newValue = (String) picker.getSelectedValue();
+
+ StringBuffer accum = new StringBuffer();
+ String text = box.getText();
+
+ // Add all text up to the selection start.
+ accum.append(text.substring(0, selectStart));
+
+ // Add one space if not at start.
+ if (selectStart > 0) {
+ accum.append(separatorPadding);
+ }
+ // Add the new value.
+ accum.append(newValue);
+
+ // Find correct cursor position.
+ int savedCursorPos = accum.length();
+
+ // Add all text after the selection end
+ String ender = text.substring(selectEnd).trim();
+ if (ender.length() == 0 || !isSeparator(ender.charAt(0))) {
+ // Add a separator if the first char of the ender is not already a
+ // separator.
+ accum.append(separators[0]).append(separatorPadding);
+ savedCursorPos = accum.length();
+ }
+ accum.append(ender);
+
+ // Set the text and cursor pos to correct location.
+ String replacement = accum.toString();
+ currentValue = replacement.trim();
+ box.setText(replacement);
+ box.setCursorPos(savedCursorPos);
+ }
+ });
+ }
+
+ /**
+ * Convenience method for identifying if a character is a separator.
+ */
+ private boolean isSeparator(char candidate) {
+ // An int map would be very handy right here...
+ for (int i = 0; i < separators.length; i++) {
+ if (candidate == separators[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets the suggestion oracle used to create suggestions.
+ *
+ * @param oracle the oracle
+ */
+ private void setOracle(SuggestOracle oracle) {
+ this.oracle = oracle;
+ }
+
+ private void showSuggestions(String query) {
+ oracle.requestSuggestions(new Request(query, limit), callBack);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestOracle.java b/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
index db62d1f..b41b193 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
@@ -1,217 +1,217 @@
-/*
- * Copyright 2007 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.user.client.rpc.IsSerializable;
-
-import java.util.Collection;
-
-/**
- * A {@link com.google.gwt.user.client.ui.SuggestOracle} can be used to create
- * suggestions associated with a specific query string. It is currently used by
- * {@link SuggestBox}.
- *
- * @see SuggestBox
- */
-public abstract class SuggestOracle {
-
- /**
- * Constructor for {@link com.google.gwt.user.client.ui.SuggestOracle}.
- */
- public SuggestOracle() {
- }
-
- /**
- * Should {@link Suggestion} display strings be treated as HTML? If true, this
- * all suggestions' display strings will be interpreted as HTML, otherwise as
- * text.
- *
- * @return by default, returns false
- */
- public boolean isDisplayStringHTML() {
- return false;
- }
-
- /**
- * Generate a {@link Response} based on a specific {@link Request}. After the
- * {@link Response} is created, it is passed into
- * {@link Callback#onSuggestionsReady(com.google.gwt.user.client.ui.SuggestOracle.Request, com.google.gwt.user.client.ui.SuggestOracle.Response)}.
- *
- * @param request the request
- * @param callback the callback to use for the response
- */
- public abstract void requestSuggestions(Request request, Callback callback);
-
- /**
- * Callback for {@link com.google.gwt.user.client.ui.SuggestOracle}. Every
- * {@link Request} should be associated with a callback that should be called
- * after a {@link Response} is generated.
- */
- public interface Callback {
- /**
- * Consume the suggestions created by a
- * {@link com.google.gwt.user.client.ui.SuggestOracle} in response to a
- * {@link Request}.
- *
- * @param request the request
- * @param response the response
- */
- public void onSuggestionsReady(Request request, Response response);
- }
-
- /**
- * A {@link com.google.gwt.user.client.ui.SuggestOracle} request.
- */
- public static class Request implements IsSerializable {
- private int limit = 20;
- private String query;
-
- /**
- * Constructor for {@link Request}.
- */
- public Request() {
- }
-
- /**
- * Constructor for {@link Request}.
- *
- * @param query the query string
- */
- public Request(String query) {
- setQuery(query);
- }
-
- /**
- * Constructor for {@link Request}.
- *
- * @param query the query string
- * @param limit limit on the number of suggestions that should be created
- * for this query
- */
- public Request(String query, int limit) {
- setQuery(query);
- setLimit(limit);
- }
-
- /**
- * Gets the limit on the number of suggestions that should be created.
- *
- * @return the limit
- */
- public int getLimit() {
- return limit;
- }
-
- /**
- * Gets the query string.
- *
- * @return the query string
- */
- public String getQuery() {
- return query;
- }
-
- /**
- * Sets the limit on the number of suggestions that should be created.
- *
- * @param limit the limit
- */
- public void setLimit(int limit) {
- this.limit = limit;
- }
-
- /**
- * Sets the query string used for this request.
- *
- * @param query the query string
- */
- public void setQuery(String query) {
- this.query = query;
- }
- }
-
- /**
- * {@link com.google.gwt.user.client.ui.SuggestOracle} response.
- */
- public static class Response implements IsSerializable {
-
- /**
- * @gwt.typeArgs <com.google.gwt.user.client.ui.SuggestOracle.Suggestion>
- */
- private Collection suggestions;
-
- /**
- * Constructor for {@link Response}.
- */
- public Response() {
- }
-
- /**
- * Constructor for {@link Response}.
- *
- * @param suggestions each element of suggestions must implement the
- * {@link Suggestion} interface
- */
- public Response(Collection suggestions) {
- setSuggestions(suggestions);
- }
-
- /**
- * Gets the collection of suggestions. Each suggestion must implement the
- * {@link Suggestion} interface.
- *
- * @return the collection of suggestions
- */
- public Collection getSuggestions() {
- return this.suggestions;
- }
-
- /**
- * Sets the suggestions for this response. Each suggestion must implement
- * the {@link Suggestion} interface.
- *
- * @param suggestions the suggestions
- */
- public void setSuggestions(Collection suggestions) {
- this.suggestions = suggestions;
- }
- }
-
- /**
- * Suggestion supplied by the
- * {@link com.google.gwt.user.client.ui.SuggestOracle}. Each suggestion has a
- * value and a display string. The interpretation of the display string
- * depends upon the value of its oracle's {@link SuggestOracle#isDisplayStringHTML()}.
- *
- */
- public interface Suggestion {
- /**
- * Gets the display string associated with this suggestion. The
- * interpretation of the display string depends upon the value of
- * its oracle's {@link SuggestOracle#isDisplayStringHTML()}.
- *
- * @return the display string
- */
- String getDisplayString();
-
- /**
- * Get the value associated with this suggestion.
- *
- * @return the value
- */
- Object getValue();
- }
-}
+/*
+ * Copyright 2007 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.user.client.rpc.IsSerializable;
+
+import java.util.Collection;
+
+/**
+ * A {@link com.google.gwt.user.client.ui.SuggestOracle} can be used to create
+ * suggestions associated with a specific query string. It is currently used by
+ * {@link SuggestBox}.
+ *
+ * @see SuggestBox
+ */
+public abstract class SuggestOracle {
+
+ /**
+ * Constructor for {@link com.google.gwt.user.client.ui.SuggestOracle}.
+ */
+ public SuggestOracle() {
+ }
+
+ /**
+ * Should {@link Suggestion} display strings be treated as HTML? If true, this
+ * all suggestions' display strings will be interpreted as HTML, otherwise as
+ * text.
+ *
+ * @return by default, returns false
+ */
+ public boolean isDisplayStringHTML() {
+ return false;
+ }
+
+ /**
+ * Generate a {@link Response} based on a specific {@link Request}. After the
+ * {@link Response} is created, it is passed into
+ * {@link Callback#onSuggestionsReady(com.google.gwt.user.client.ui.SuggestOracle.Request, com.google.gwt.user.client.ui.SuggestOracle.Response)}.
+ *
+ * @param request the request
+ * @param callback the callback to use for the response
+ */
+ public abstract void requestSuggestions(Request request, Callback callback);
+
+ /**
+ * Callback for {@link com.google.gwt.user.client.ui.SuggestOracle}. Every
+ * {@link Request} should be associated with a callback that should be called
+ * after a {@link Response} is generated.
+ */
+ public interface Callback {
+ /**
+ * Consume the suggestions created by a
+ * {@link com.google.gwt.user.client.ui.SuggestOracle} in response to a
+ * {@link Request}.
+ *
+ * @param request the request
+ * @param response the response
+ */
+ public void onSuggestionsReady(Request request, Response response);
+ }
+
+ /**
+ * A {@link com.google.gwt.user.client.ui.SuggestOracle} request.
+ */
+ public static class Request implements IsSerializable {
+ private int limit = 20;
+ private String query;
+
+ /**
+ * Constructor for {@link Request}.
+ */
+ public Request() {
+ }
+
+ /**
+ * Constructor for {@link Request}.
+ *
+ * @param query the query string
+ */
+ public Request(String query) {
+ setQuery(query);
+ }
+
+ /**
+ * Constructor for {@link Request}.
+ *
+ * @param query the query string
+ * @param limit limit on the number of suggestions that should be created
+ * for this query
+ */
+ public Request(String query, int limit) {
+ setQuery(query);
+ setLimit(limit);
+ }
+
+ /**
+ * Gets the limit on the number of suggestions that should be created.
+ *
+ * @return the limit
+ */
+ public int getLimit() {
+ return limit;
+ }
+
+ /**
+ * Gets the query string.
+ *
+ * @return the query string
+ */
+ public String getQuery() {
+ return query;
+ }
+
+ /**
+ * Sets the limit on the number of suggestions that should be created.
+ *
+ * @param limit the limit
+ */
+ public void setLimit(int limit) {
+ this.limit = limit;
+ }
+
+ /**
+ * Sets the query string used for this request.
+ *
+ * @param query the query string
+ */
+ public void setQuery(String query) {
+ this.query = query;
+ }
+ }
+
+ /**
+ * {@link com.google.gwt.user.client.ui.SuggestOracle} response.
+ */
+ public static class Response implements IsSerializable {
+
+ /**
+ * @gwt.typeArgs <com.google.gwt.user.client.ui.SuggestOracle.Suggestion>
+ */
+ private Collection suggestions;
+
+ /**
+ * Constructor for {@link Response}.
+ */
+ public Response() {
+ }
+
+ /**
+ * Constructor for {@link Response}.
+ *
+ * @param suggestions each element of suggestions must implement the
+ * {@link Suggestion} interface
+ */
+ public Response(Collection suggestions) {
+ setSuggestions(suggestions);
+ }
+
+ /**
+ * Gets the collection of suggestions. Each suggestion must implement the
+ * {@link Suggestion} interface.
+ *
+ * @return the collection of suggestions
+ */
+ public Collection getSuggestions() {
+ return this.suggestions;
+ }
+
+ /**
+ * Sets the suggestions for this response. Each suggestion must implement
+ * the {@link Suggestion} interface.
+ *
+ * @param suggestions the suggestions
+ */
+ public void setSuggestions(Collection suggestions) {
+ this.suggestions = suggestions;
+ }
+ }
+
+ /**
+ * Suggestion supplied by the
+ * {@link com.google.gwt.user.client.ui.SuggestOracle}. Each suggestion has a
+ * value and a display string. The interpretation of the display string
+ * depends upon the value of its oracle's {@link SuggestOracle#isDisplayStringHTML()}.
+ *
+ */
+ public interface Suggestion {
+ /**
+ * Gets the display string associated with this suggestion. The
+ * interpretation of the display string depends upon the value of
+ * its oracle's {@link SuggestOracle#isDisplayStringHTML()}.
+ *
+ * @return the display string
+ */
+ String getDisplayString();
+
+ /**
+ * Get the value associated with this suggestion.
+ *
+ * @return the value
+ */
+ Object getValue();
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/ToggleButton.java b/user/src/com/google/gwt/user/client/ui/ToggleButton.java
index 3ebd273..c86a2d2 100644
--- a/user/src/com/google/gwt/user/client/ui/ToggleButton.java
+++ b/user/src/com/google/gwt/user/client/ui/ToggleButton.java
@@ -1,146 +1,146 @@
-/*
- * Copyright 2006 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.user.client.DOM;
-import com.google.gwt.user.client.Event;
-
-/**
- * A <code>ToggleButton</code> is a stylish stateful button which allows the
- * user to toggle between <code>up</code> and <code>down</code> states.
- *
- * <p>
- * <img class='gallery' src='ToggleButton.png'/>
- * </p>
- *
- * <h3>CSS Style Rules</h3>
- * <ul class="css">
- * <li>.gwt-ToggleButton-up/down/up-hovering/down-hovering/up-disabled/down-disabled {.html-face}</li>
- * </ul>
- *
- * <p>
- * <h3>Example</h3> {@example com.google.gwt.examples.ToggleButtonExample}
- * </p>
- */
-public class ToggleButton extends CustomButton {
- private static String STYLENAME_DEFAULT = "gwt-ToggleButton";
-
- {
- setStyleName(STYLENAME_DEFAULT);
- }
-
- /**
- * Constructor for <code>ToggleButton</code>.
- */
- public ToggleButton() {
- super();
- }
-
- /**
- * Constructor for <code>ToggleButton</code>. The supplied image is used to
- * construct the default face.
- *
- * @param upImage image for the default face of the button
- */
- public ToggleButton(Image upImage) {
- super(upImage);
- }
-
- /**
- * Constructor for <code>ToggleButton</code>.
- *
- * @param upImage image for the default(up) face of the button
- * @param downImage image for the down face of the button
- */
- public ToggleButton(Image upImage, Image downImage) {
- super(upImage, downImage);
- }
-
- /**
- * Constructor for <code>ToggleButton</code>.
- *
- * @param upImage image for the default(up) face of the button
- * @param downImage image for the down face of the button
- * @param listener clickListener
- */
- public ToggleButton(Image upImage, Image downImage, ClickListener listener) {
- super(upImage, downImage, listener);
- }
-
- /**
- * Constructor for <code>ToggleButton</code>. The supplied image is used to
- * construct the default face of the button.
- *
- * @param upImage image for the default (up) face of the button
- * @param listener the click listener
- */
- public ToggleButton(Image upImage, ClickListener listener) {
- super(upImage, listener);
- }
-
- /**
- * Constructor for <code>ToggleButton</code>. The supplied text is used to
- * construct the default face of the button.
- *
- * @param upText the text for the default (up) face of the button.
- */
- public ToggleButton(String upText) {
- super(upText);
- }
-
- /**
- * Constructor for <code>ToggleButton</code>. The supplied text is used to
- * construct the default face of the button.
- *
- * @param upText the text for the default (up) face of the button
- * @param listener the click listener
- */
- public ToggleButton(String upText, ClickListener listener) {
- super(upText, listener);
- }
-
- /**
- * Constructor for <code>ToggleButton</code>.
- *
- * @param upText the text for the default (up) face of the button
- * @param downText the text for down face of the button
- */
- public ToggleButton(String upText, String downText) {
- super(upText, downText);
- }
-
- public boolean isDown() {
- return super.isDown();
- }
-
- public void onBrowserEvent(Event event) {
- if (isEnabled() == false) {
- return;
- }
- int type = DOM.eventGetType(event);
- switch (type) {
- case Event.ONCLICK:
- toggleDown();
- break;
- }
- super.onBrowserEvent(event);
- }
-
- public void setDown(boolean isDown) {
- super.setDown(isDown);
- }
-}
+/*
+ * Copyright 2006 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.user.client.DOM;
+import com.google.gwt.user.client.Event;
+
+/**
+ * A <code>ToggleButton</code> is a stylish stateful button which allows the
+ * user to toggle between <code>up</code> and <code>down</code> states.
+ *
+ * <p>
+ * <img class='gallery' src='ToggleButton.png'/>
+ * </p>
+ *
+ * <h3>CSS Style Rules</h3>
+ * <ul class="css">
+ * <li>.gwt-ToggleButton-up/down/up-hovering/down-hovering/up-disabled/down-disabled {.html-face}</li>
+ * </ul>
+ *
+ * <p>
+ * <h3>Example</h3> {@example com.google.gwt.examples.ToggleButtonExample}
+ * </p>
+ */
+public class ToggleButton extends CustomButton {
+ private static String STYLENAME_DEFAULT = "gwt-ToggleButton";
+
+ {
+ setStyleName(STYLENAME_DEFAULT);
+ }
+
+ /**
+ * Constructor for <code>ToggleButton</code>.
+ */
+ public ToggleButton() {
+ super();
+ }
+
+ /**
+ * Constructor for <code>ToggleButton</code>. The supplied image is used to
+ * construct the default face.
+ *
+ * @param upImage image for the default face of the button
+ */
+ public ToggleButton(Image upImage) {
+ super(upImage);
+ }
+
+ /**
+ * Constructor for <code>ToggleButton</code>.
+ *
+ * @param upImage image for the default(up) face of the button
+ * @param downImage image for the down face of the button
+ */
+ public ToggleButton(Image upImage, Image downImage) {
+ super(upImage, downImage);
+ }
+
+ /**
+ * Constructor for <code>ToggleButton</code>.
+ *
+ * @param upImage image for the default(up) face of the button
+ * @param downImage image for the down face of the button
+ * @param listener clickListener
+ */
+ public ToggleButton(Image upImage, Image downImage, ClickListener listener) {
+ super(upImage, downImage, listener);
+ }
+
+ /**
+ * Constructor for <code>ToggleButton</code>. The supplied image is used to
+ * construct the default face of the button.
+ *
+ * @param upImage image for the default (up) face of the button
+ * @param listener the click listener
+ */
+ public ToggleButton(Image upImage, ClickListener listener) {
+ super(upImage, listener);
+ }
+
+ /**
+ * Constructor for <code>ToggleButton</code>. The supplied text is used to
+ * construct the default face of the button.
+ *
+ * @param upText the text for the default (up) face of the button.
+ */
+ public ToggleButton(String upText) {
+ super(upText);
+ }
+
+ /**
+ * Constructor for <code>ToggleButton</code>. The supplied text is used to
+ * construct the default face of the button.
+ *
+ * @param upText the text for the default (up) face of the button
+ * @param listener the click listener
+ */
+ public ToggleButton(String upText, ClickListener listener) {
+ super(upText, listener);
+ }
+
+ /**
+ * Constructor for <code>ToggleButton</code>.
+ *
+ * @param upText the text for the default (up) face of the button
+ * @param downText the text for down face of the button
+ */
+ public ToggleButton(String upText, String downText) {
+ super(upText, downText);
+ }
+
+ public boolean isDown() {
+ return super.isDown();
+ }
+
+ public void onBrowserEvent(Event event) {
+ if (isEnabled() == false) {
+ return;
+ }
+ int type = DOM.eventGetType(event);
+ switch (type) {
+ case Event.ONCLICK:
+ toggleDown();
+ break;
+ }
+ super.onBrowserEvent(event);
+ }
+
+ public void setDown(boolean isDown) {
+ super.setDown(isDown);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/AbstractItemPickerImpl.java b/user/src/com/google/gwt/user/client/ui/impl/AbstractItemPickerImpl.java
index f75ebe5..27fcacf 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/AbstractItemPickerImpl.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/AbstractItemPickerImpl.java
@@ -1,251 +1,251 @@
-/*
- * Copyright 2006 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.impl;
-
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.ChangeListener;
-import com.google.gwt.user.client.ui.ChangeListenerCollection;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * Helpful base implementation of the {@link ItemPicker} interface.
- */
-abstract class AbstractItemPickerImpl extends Widget {
- /**
- * Selectable item.
- */
- class Item extends UIObject {
- private int index;
- private Object value;
-
- /**
- * Constructor for <code>Item</code>.
- *
- * @param index index associated with item
- */
- Item(int index) {
- setElement(DOM.createTD());
- this.index = index;
- this.setStyleName(STYLENAME_ITEM);
- items.add(index, this);
- }
-
- public String toString() {
- return "value: " + this.getValue() + " index: " + this.getIndex();
- }
-
- /**
- * Gets the index of the item.
- *
- * @return the item's index
- */
- int getIndex() {
- return index;
- }
-
- AbstractItemPickerImpl getOwner() {
- return AbstractItemPickerImpl.this;
- }
-
- Object getValue() {
- return value;
- }
-
- void setValue(Object value) {
- this.value = value;
- }
- }
-
- private static final String STYLENAME_SELECTED_ITEM = "item-selected";
- private static final String STYLENAME_ITEM = "item";
-
- final Element body;
- private Element currentTR;
- private final ArrayList items;
- private ChangeListenerCollection changeListeners = new ChangeListenerCollection();
- private Item selectedItem;
-
- public AbstractItemPickerImpl() {
- items = new ArrayList();
- Element table = DOM.createTable();
- body = DOM.createTBody();
- DOM.appendChild(table, body);
- setElement(table);
- sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT);
- DOM.setElementPropertyInt(table, "cellPadding", 0);
- DOM.setElementPropertyInt(table, "cellSpacing", 0);
- }
-
- public final void addChangeListener(ChangeListener listener) {
- if (changeListeners == null) {
- changeListeners = new ChangeListenerCollection();
- }
- changeListeners.add(listener);
- }
-
- public void commitSelection() {
- if (selectedItem == null) {
- throw new IllegalStateException("No element is selected");
- }
- changeListeners.fireChange(this);
- }
-
- public abstract boolean delegateKeyDown(char keyCode);
-
- public int getItemCount() {
- return items.size();
- }
-
- public final int getSelectedIndex() {
- Item item = getSelectedItem();
- if (item == null) {
- return -1;
- }
- return item.getIndex();
- }
-
- public final Object getSelectedValue() {
- Item item = getSelectedItem();
- if (item == null) {
- return null;
- } else {
- return item.getValue();
- }
- }
-
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- Item item = findItem(DOM.eventGetTarget(event));
- switch (DOM.eventGetType(event)) {
- case Event.ONCLICK: {
- commitSelection();
- break;
- }
- case Event.ONMOUSEOVER: {
- if (item != null) {
- setSelection(item);
- }
- break;
- }
- case Event.ONMOUSEOUT: {
- if (item != null) {
- setSelection(null);
- }
- break;
- }
- }
- }
-
- public final void removeChangeListener(ChangeListener listener) {
- this.changeListeners.remove(listener);
- }
-
- public abstract void setItems(Collection items);
-
- public final void setSelectedIndex(int index) {
- Item item = getItem(index);
- setSelection(item);
- }
-
- void addItem(Item item, boolean vertical) {
- if (vertical) {
- currentTR = DOM.createTR();
- DOM.appendChild(body, currentTR);
- }
- DOM.appendChild(currentTR, item.getElement());
- }
-
- void clearItems() {
- items.clear();
- }
-
- /**
- * Gets the ith item.
- *
- * @param index index of item
- * @return the ith item
- */
- Item getItem(int index) {
- return (Item) items.get(index);
- }
-
- /**
- * Gets the currently selected item.
- *
- * @return selected item
- */
- Item getSelectedItem() {
- return selectedItem;
- }
-
- /**
- * Sets the current selection.
- *
- * @param item item to set
- */
- void setSelection(Item item) {
- if (selectedItem == item) {
- return;
- }
-
- // Remove old selected item.
- if (selectedItem != null) {
- selectedItem.removeStyleName(STYLENAME_SELECTED_ITEM);
- selectedItem.addStyleName(STYLENAME_ITEM);
- }
-
- // Add new selected item.
- selectedItem = item;
- if (selectedItem != null) {
- selectedItem.removeStyleName(STYLENAME_ITEM);
- selectedItem.addStyleName(STYLENAME_SELECTED_ITEM);
- }
- }
-
- /**
- * Shifts the current selection by the given amount, unless that would make
- * the selection invalid.
- *
- * @param shift the amount to shift the current selection by
- */
- void shiftSelection(int shift) {
- int newIndex = getSelectedIndex() + shift;
- if (newIndex < 0 || newIndex >= getItemCount()) {
- return;
- } else {
- Item item = getItem(newIndex);
- setSelection(item);
- }
- }
-
- private Item findItem(Element hItem) {
- for (int i = 0; i < items.size(); ++i) {
- Item item = (Item) items.get(i);
- if (DOM.isOrHasChild(item.getElement(), hItem)) {
- return item;
- }
- }
-
- return null;
- }
-}
+/*
+ * Copyright 2006 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.impl;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.ChangeListener;
+import com.google.gwt.user.client.ui.ChangeListenerCollection;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.Widget;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Helpful base implementation of the {@link ItemPicker} interface.
+ */
+abstract class AbstractItemPickerImpl extends Widget {
+ /**
+ * Selectable item.
+ */
+ class Item extends UIObject {
+ private int index;
+ private Object value;
+
+ /**
+ * Constructor for <code>Item</code>.
+ *
+ * @param index index associated with item
+ */
+ Item(int index) {
+ setElement(DOM.createTD());
+ this.index = index;
+ this.setStyleName(STYLENAME_ITEM);
+ items.add(index, this);
+ }
+
+ public String toString() {
+ return "value: " + this.getValue() + " index: " + this.getIndex();
+ }
+
+ /**
+ * Gets the index of the item.
+ *
+ * @return the item's index
+ */
+ int getIndex() {
+ return index;
+ }
+
+ AbstractItemPickerImpl getOwner() {
+ return AbstractItemPickerImpl.this;
+ }
+
+ Object getValue() {
+ return value;
+ }
+
+ void setValue(Object value) {
+ this.value = value;
+ }
+ }
+
+ private static final String STYLENAME_SELECTED_ITEM = "item-selected";
+ private static final String STYLENAME_ITEM = "item";
+
+ final Element body;
+ private Element currentTR;
+ private final ArrayList items;
+ private ChangeListenerCollection changeListeners = new ChangeListenerCollection();
+ private Item selectedItem;
+
+ public AbstractItemPickerImpl() {
+ items = new ArrayList();
+ Element table = DOM.createTable();
+ body = DOM.createTBody();
+ DOM.appendChild(table, body);
+ setElement(table);
+ sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT);
+ DOM.setElementPropertyInt(table, "cellPadding", 0);
+ DOM.setElementPropertyInt(table, "cellSpacing", 0);
+ }
+
+ public final void addChangeListener(ChangeListener listener) {
+ if (changeListeners == null) {
+ changeListeners = new ChangeListenerCollection();
+ }
+ changeListeners.add(listener);
+ }
+
+ public void commitSelection() {
+ if (selectedItem == null) {
+ throw new IllegalStateException("No element is selected");
+ }
+ changeListeners.fireChange(this);
+ }
+
+ public abstract boolean delegateKeyDown(char keyCode);
+
+ public int getItemCount() {
+ return items.size();
+ }
+
+ public final int getSelectedIndex() {
+ Item item = getSelectedItem();
+ if (item == null) {
+ return -1;
+ }
+ return item.getIndex();
+ }
+
+ public final Object getSelectedValue() {
+ Item item = getSelectedItem();
+ if (item == null) {
+ return null;
+ } else {
+ return item.getValue();
+ }
+ }
+
+ public void onBrowserEvent(Event event) {
+ super.onBrowserEvent(event);
+ Item item = findItem(DOM.eventGetTarget(event));
+ switch (DOM.eventGetType(event)) {
+ case Event.ONCLICK: {
+ commitSelection();
+ break;
+ }
+ case Event.ONMOUSEOVER: {
+ if (item != null) {
+ setSelection(item);
+ }
+ break;
+ }
+ case Event.ONMOUSEOUT: {
+ if (item != null) {
+ setSelection(null);
+ }
+ break;
+ }
+ }
+ }
+
+ public final void removeChangeListener(ChangeListener listener) {
+ this.changeListeners.remove(listener);
+ }
+
+ public abstract void setItems(Collection items);
+
+ public final void setSelectedIndex(int index) {
+ Item item = getItem(index);
+ setSelection(item);
+ }
+
+ void addItem(Item item, boolean vertical) {
+ if (vertical) {
+ currentTR = DOM.createTR();
+ DOM.appendChild(body, currentTR);
+ }
+ DOM.appendChild(currentTR, item.getElement());
+ }
+
+ void clearItems() {
+ items.clear();
+ }
+
+ /**
+ * Gets the ith item.
+ *
+ * @param index index of item
+ * @return the ith item
+ */
+ Item getItem(int index) {
+ return (Item) items.get(index);
+ }
+
+ /**
+ * Gets the currently selected item.
+ *
+ * @return selected item
+ */
+ Item getSelectedItem() {
+ return selectedItem;
+ }
+
+ /**
+ * Sets the current selection.
+ *
+ * @param item item to set
+ */
+ void setSelection(Item item) {
+ if (selectedItem == item) {
+ return;
+ }
+
+ // Remove old selected item.
+ if (selectedItem != null) {
+ selectedItem.removeStyleName(STYLENAME_SELECTED_ITEM);
+ selectedItem.addStyleName(STYLENAME_ITEM);
+ }
+
+ // Add new selected item.
+ selectedItem = item;
+ if (selectedItem != null) {
+ selectedItem.removeStyleName(STYLENAME_ITEM);
+ selectedItem.addStyleName(STYLENAME_SELECTED_ITEM);
+ }
+ }
+
+ /**
+ * Shifts the current selection by the given amount, unless that would make
+ * the selection invalid.
+ *
+ * @param shift the amount to shift the current selection by
+ */
+ void shiftSelection(int shift) {
+ int newIndex = getSelectedIndex() + shift;
+ if (newIndex < 0 || newIndex >= getItemCount()) {
+ return;
+ } else {
+ Item item = getItem(newIndex);
+ setSelection(item);
+ }
+ }
+
+ private Item findItem(Element hItem) {
+ for (int i = 0; i < items.size(); ++i) {
+ Item item = (Item) items.get(i);
+ if (DOM.isOrHasChild(item.getElement(), hItem)) {
+ return item;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImpl.java b/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImpl.java
index 6d6f2cb..da8f3da 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImpl.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImpl.java
@@ -1,56 +1,56 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-
-/**
- * Uses a combination of a clear image and a background image to clip all except
- * a desired portion of an underlying image.
- *
- * Do not use this class - it is used for implementation only, and its methods
- * may change in the future.
- */
-public class ClippedImageImpl {
-
- public void adjust(Element img, String url, int left, int top, int width,
- int height) {
- String style = "url(" + url + ") no-repeat " + (-left + "px ")
- + (-top + "px");
- DOM.setStyleAttribute(img, "background", style);
- DOM.setStyleAttribute(img, "width", width + "px");
- DOM.setStyleAttribute(img, "height", height + "px");
- }
-
- public Element createStructure(String url, int left, int top, int width,
- int height) {
- Element tmp = DOM.createSpan();
- DOM.setInnerHTML(tmp, getHTML(url, left, top, width, height));
- return DOM.getFirstChild(tmp);
- }
-
- public String getHTML(String url, int left, int top, int width, int height) {
- String style = "width: " + width + "px; height: " + height
- + "px; background: url(" + url + ") no-repeat " + (-left + "px ")
- + (-top + "px");
-
- String clippedImgHtml = "<img src='clear.cache.gif' style='"
- + style + "' border='0'>";
-
- return clippedImgHtml;
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+
+/**
+ * Uses a combination of a clear image and a background image to clip all except
+ * a desired portion of an underlying image.
+ *
+ * Do not use this class - it is used for implementation only, and its methods
+ * may change in the future.
+ */
+public class ClippedImageImpl {
+
+ public void adjust(Element img, String url, int left, int top, int width,
+ int height) {
+ String style = "url(" + url + ") no-repeat " + (-left + "px ")
+ + (-top + "px");
+ DOM.setStyleAttribute(img, "background", style);
+ DOM.setStyleAttribute(img, "width", width + "px");
+ DOM.setStyleAttribute(img, "height", height + "px");
+ }
+
+ public Element createStructure(String url, int left, int top, int width,
+ int height) {
+ Element tmp = DOM.createSpan();
+ DOM.setInnerHTML(tmp, getHTML(url, left, top, width, height));
+ return DOM.getFirstChild(tmp);
+ }
+
+ public String getHTML(String url, int left, int top, int width, int height) {
+ String style = "width: " + width + "px; height: " + height
+ + "px; background: url(" + url + ") no-repeat " + (-left + "px ")
+ + (-top + "px");
+
+ String clippedImgHtml = "<img src='clear.cache.gif' style='"
+ + style + "' border='0'>";
+
+ return clippedImgHtml;
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImplIE6.java b/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImplIE6.java
index dc6aad8..46ea137 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImplIE6.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImplIE6.java
@@ -1,68 +1,68 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-
-/**
- * Implements the clipped image as a IMG inside a custom tag because we can't
- * use the IE PNG transparency filter on background-image images.
- *
- * Do not use this class - it is used for implementation only, and its methods
- * may change in the future.
- */
-public class ClippedImageImplIE6 extends ClippedImageImpl {
-
- public void adjust(Element clipper, String url, int left, int top, int width,
- int height) {
-
- DOM.setStyleAttribute(clipper, "width", width + "px");
- DOM.setStyleAttribute(clipper, "height", height + "px");
-
- // Update the nested image's url.
- Element img = DOM.getFirstChild(clipper);
- DOM.setStyleAttribute(img, "filter",
- "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + url
- + "',sizingMethod='crop')");
- DOM.setStyleAttribute(img, "marginLeft", -left + "px");
- DOM.setStyleAttribute(img, "marginTop", -top + "px");
-
- // AlphaImageLoader requires that we size the image explicitly.
- // It really only needs to be enough to show the revealed portion.
- int imgWidth = left + width;
- int imgHeight = top + height;
- DOM.setElementPropertyInt(img, "width", imgWidth);
- DOM.setElementPropertyInt(img, "height", imgHeight);
- }
-
- public String getHTML(String url, int left, int top, int width, int height) {
- String clipperStyle = "overflow: hidden; width: " + width + "px; height: "
- + height + "px; padding: 0px";
-
- String imgStyle =
- "filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
- + url + "',sizingMethod='crop'); margin-left: "
- + -left + "px; margin-top: " + -top + "px" + "border: 0px";
-
- String clippedImgHtml = "<gwt:clipper style=\""
- + clipperStyle + "\"><img src='clear.cache.gif' style=\"" + imgStyle
- + "\" width=" + (left + width) + " height=" + (top + height)
- + " border='0'></gwt:clipper>";
-
- return clippedImgHtml;
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+
+/**
+ * Implements the clipped image as a IMG inside a custom tag because we can't
+ * use the IE PNG transparency filter on background-image images.
+ *
+ * Do not use this class - it is used for implementation only, and its methods
+ * may change in the future.
+ */
+public class ClippedImageImplIE6 extends ClippedImageImpl {
+
+ public void adjust(Element clipper, String url, int left, int top, int width,
+ int height) {
+
+ DOM.setStyleAttribute(clipper, "width", width + "px");
+ DOM.setStyleAttribute(clipper, "height", height + "px");
+
+ // Update the nested image's url.
+ Element img = DOM.getFirstChild(clipper);
+ DOM.setStyleAttribute(img, "filter",
+ "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + url
+ + "',sizingMethod='crop')");
+ DOM.setStyleAttribute(img, "marginLeft", -left + "px");
+ DOM.setStyleAttribute(img, "marginTop", -top + "px");
+
+ // AlphaImageLoader requires that we size the image explicitly.
+ // It really only needs to be enough to show the revealed portion.
+ int imgWidth = left + width;
+ int imgHeight = top + height;
+ DOM.setElementPropertyInt(img, "width", imgWidth);
+ DOM.setElementPropertyInt(img, "height", imgHeight);
+ }
+
+ public String getHTML(String url, int left, int top, int width, int height) {
+ String clipperStyle = "overflow: hidden; width: " + width + "px; height: "
+ + height + "px; padding: 0px";
+
+ String imgStyle =
+ "filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
+ + url + "',sizingMethod='crop'); margin-left: "
+ + -left + "px; margin-top: " + -top + "px" + "border: 0px";
+
+ String clippedImgHtml = "<gwt:clipper style=\""
+ + clipperStyle + "\"><img src='clear.cache.gif' style=\"" + imgStyle
+ + "\" width=" + (left + width) + " height=" + (top + height)
+ + " border='0'></gwt:clipper>";
+
+ return clippedImgHtml;
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/ClippedImagePrototype.java b/user/src/com/google/gwt/user/client/ui/impl/ClippedImagePrototype.java
index 159d00c..5bab715 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/ClippedImagePrototype.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/ClippedImagePrototype.java
@@ -1,57 +1,57 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.core.client.GWT;
-
-/**
- * Implementation of {@link AbstractImagePrototype} for a clipped image. This
- * class is used internally by the image bundle generator and is not intended
- * for general use. It is subject to change without warning.
- */
-public class ClippedImagePrototype extends AbstractImagePrototype {
-
- private static final ClippedImageImpl impl = (ClippedImageImpl) GWT.create(ClippedImageImpl.class);
-
- private int left = 0;
- private int top = 0;
- private int width = 0;
- private int height = 0;
- private String url = null;
-
- public ClippedImagePrototype(String url, int left, int top, int width,
- int height) {
- this.url = url;
- this.left = left;
- this.top = top;
- this.width = width;
- this.height = height;
- }
-
- public void applyTo(Image image) {
- image.setUrlAndVisibleRect(url, left, top, width, height);
- }
-
- public Image createImage() {
- return new Image(url, left, top, width, height);
- }
-
- public String getHTML() {
- return impl.getHTML(url, left, top, width, height);
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
+import com.google.gwt.core.client.GWT;
+
+/**
+ * Implementation of {@link AbstractImagePrototype} for a clipped image. This
+ * class is used internally by the image bundle generator and is not intended
+ * for general use. It is subject to change without warning.
+ */
+public class ClippedImagePrototype extends AbstractImagePrototype {
+
+ private static final ClippedImageImpl impl = (ClippedImageImpl) GWT.create(ClippedImageImpl.class);
+
+ private int left = 0;
+ private int top = 0;
+ private int width = 0;
+ private int height = 0;
+ private String url = null;
+
+ public ClippedImagePrototype(String url, int left, int top, int width,
+ int height) {
+ this.url = url;
+ this.left = left;
+ this.top = top;
+ this.width = width;
+ this.height = height;
+ }
+
+ public void applyTo(Image image) {
+ image.setUrlAndVisibleRect(url, left, top, width, height);
+ }
+
+ public Image createImage() {
+ return new Image(url, left, top, width, height);
+ }
+
+ public String getHTML() {
+ return impl.getHTML(url, left, top, width, height);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/ItemPickerDropDownImpl.java b/user/src/com/google/gwt/user/client/ui/impl/ItemPickerDropDownImpl.java
index cccfe29..b04e01d 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/ItemPickerDropDownImpl.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/ItemPickerDropDownImpl.java
@@ -1,96 +1,96 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.ChangeListener;
-import com.google.gwt.user.client.ui.HasFocus;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-
-/**
- * Suggestion picker drop-down, used in the implementation of
- * {@link com.google.gwt.user.client.ui.SuggestBox}.
- */
-public class ItemPickerDropDownImpl extends PopupPanel {
- private final AbstractItemPickerImpl picker;
- private final HasFocus owner;
-
- public ItemPickerDropDownImpl(final HasFocus owner, AbstractItemPickerImpl picker) {
- super(true);
- setWidget(picker);
- this.picker = picker;
- this.owner = owner;
-
- picker.addChangeListener(new ChangeListener() {
- public void onChange(Widget sender) {
- hide();
- }
- });
- }
-
- /**
- * Shows the popup, by default <code>show</code> selects the first item and
- * displays itself under it's owner.
- */
- public void show() {
- showBelow((UIObject) owner);
- }
-
- /**
- * Shows the popup below the given UI object. By default, first item is
- * selected in the item picker.
- * <p>
- * Note, if the popup would not be visible on the browser, than the popup's
- * position may be adjusted.
- * </p>
- *
- * @param showBelow the <code>UIObject</code> beneath which the popup should
- * be shown
- */
- public void showBelow(UIObject showBelow) {
- // A drop down with 0 items should never show itself.
- if (picker.getItemCount() == 0) {
- hide();
- return;
- }
-
- // Initialize the picker to the first element.
- picker.setSelectedIndex(0);
-
- // Show must be called first, as otherwise getOffsetWidth is not correct. As
- // the adjustment is very fast, the user experience is not effected by this
- // call.
- super.show();
-
- // Calculate left.
- int left = showBelow.getAbsoluteLeft();
- int windowRight = Window.getClientWidth() + Window.getScrollLeft();
- int overshootLeft = Math.max(0, (left + getOffsetWidth()) - windowRight);
- left = left - overshootLeft;
-
- // Calculate top.
- int top = showBelow.getAbsoluteTop() + showBelow.getOffsetHeight();
- int windowBottom = Window.getScrollTop() + Window.getClientHeight();
- int overshootTop = Math.max(0, (top + getOffsetHeight()) - windowBottom);
- top = top - overshootTop;
-
- // Set the popup position.
- setPopupPosition(left, top);
- super.show();
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.ChangeListener;
+import com.google.gwt.user.client.ui.HasFocus;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Suggestion picker drop-down, used in the implementation of
+ * {@link com.google.gwt.user.client.ui.SuggestBox}.
+ */
+public class ItemPickerDropDownImpl extends PopupPanel {
+ private final AbstractItemPickerImpl picker;
+ private final HasFocus owner;
+
+ public ItemPickerDropDownImpl(final HasFocus owner, AbstractItemPickerImpl picker) {
+ super(true);
+ setWidget(picker);
+ this.picker = picker;
+ this.owner = owner;
+
+ picker.addChangeListener(new ChangeListener() {
+ public void onChange(Widget sender) {
+ hide();
+ }
+ });
+ }
+
+ /**
+ * Shows the popup, by default <code>show</code> selects the first item and
+ * displays itself under it's owner.
+ */
+ public void show() {
+ showBelow((UIObject) owner);
+ }
+
+ /**
+ * Shows the popup below the given UI object. By default, first item is
+ * selected in the item picker.
+ * <p>
+ * Note, if the popup would not be visible on the browser, than the popup's
+ * position may be adjusted.
+ * </p>
+ *
+ * @param showBelow the <code>UIObject</code> beneath which the popup should
+ * be shown
+ */
+ public void showBelow(UIObject showBelow) {
+ // A drop down with 0 items should never show itself.
+ if (picker.getItemCount() == 0) {
+ hide();
+ return;
+ }
+
+ // Initialize the picker to the first element.
+ picker.setSelectedIndex(0);
+
+ // Show must be called first, as otherwise getOffsetWidth is not correct. As
+ // the adjustment is very fast, the user experience is not effected by this
+ // call.
+ super.show();
+
+ // Calculate left.
+ int left = showBelow.getAbsoluteLeft();
+ int windowRight = Window.getClientWidth() + Window.getScrollLeft();
+ int overshootLeft = Math.max(0, (left + getOffsetWidth()) - windowRight);
+ left = left - overshootLeft;
+
+ // Calculate top.
+ int top = showBelow.getAbsoluteTop() + showBelow.getOffsetHeight();
+ int windowBottom = Window.getScrollTop() + Window.getClientHeight();
+ int overshootTop = Math.max(0, (top + getOffsetHeight()) - windowBottom);
+ top = top - overshootTop;
+
+ // Set the popup position.
+ setPopupPosition(left, top);
+ super.show();
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImpl.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImpl.java
index 4407775..e41f9c3 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImpl.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImpl.java
@@ -1,87 +1,87 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.RichTextArea;
-
-/**
- * Base class for RichText platform implementations. The default version
- * simply creates a text area with no rich text support.
- */
-public class RichTextAreaImpl {
-
- protected Element elem;
-
- public RichTextAreaImpl() {
- elem = createElement();
- }
-
- public Element getElement() {
- return elem;
- }
-
- public String getHTML() {
- return DOM.getElementProperty(elem, "value");
- }
-
- public String getText() {
- return DOM.getElementProperty(elem, "value");
- }
-
- public void hookEvents(RichTextArea owner) {
- DOM.setEventListener(elem, owner);
- }
-
- public void initElement() {
- DOM.sinkEvents(elem, Event.MOUSEEVENTS | Event.KEYEVENTS | Event.ONCHANGE
- | Event.ONCLICK);
- }
-
- public boolean isBasicEditingSupported() {
- return false;
- }
-
- public boolean isExtendedEditingSupported() {
- return false;
- }
-
- public native void setFocus(boolean focused) /*-{
- if (focused) {
- this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.focus();
- } else {
- this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.blur();
- }
- }-*/;
-
- public void setHTML(String html) {
- DOM.setElementProperty(elem, "value", html);
- }
-
- public void setText(String text) {
- DOM.setElementProperty(elem, "value", text);
- }
-
- public void unhookEvents(RichTextArea owner) {
- DOM.setEventListener(elem, null);
- }
-
- protected Element createElement() {
- return DOM.createTextArea();
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.RichTextArea;
+
+/**
+ * Base class for RichText platform implementations. The default version
+ * simply creates a text area with no rich text support.
+ */
+public class RichTextAreaImpl {
+
+ protected Element elem;
+
+ public RichTextAreaImpl() {
+ elem = createElement();
+ }
+
+ public Element getElement() {
+ return elem;
+ }
+
+ public String getHTML() {
+ return DOM.getElementProperty(elem, "value");
+ }
+
+ public String getText() {
+ return DOM.getElementProperty(elem, "value");
+ }
+
+ public void hookEvents(RichTextArea owner) {
+ DOM.setEventListener(elem, owner);
+ }
+
+ public void initElement() {
+ DOM.sinkEvents(elem, Event.MOUSEEVENTS | Event.KEYEVENTS | Event.ONCHANGE
+ | Event.ONCLICK);
+ }
+
+ public boolean isBasicEditingSupported() {
+ return false;
+ }
+
+ public boolean isExtendedEditingSupported() {
+ return false;
+ }
+
+ public native void setFocus(boolean focused) /*-{
+ if (focused) {
+ this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.focus();
+ } else {
+ this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.blur();
+ }
+ }-*/;
+
+ public void setHTML(String html) {
+ DOM.setElementProperty(elem, "value", html);
+ }
+
+ public void setText(String text) {
+ DOM.setElementProperty(elem, "value", text);
+ }
+
+ public void unhookEvents(RichTextArea owner) {
+ DOM.setEventListener(elem, null);
+ }
+
+ protected Element createElement() {
+ return DOM.createTextArea();
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
index 809e82b..ae3ed15 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
@@ -1,69 +1,69 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-
-/**
- * IE6-specific implementation of rich-text editing.
- */
-public class RichTextAreaImplIE6 extends RichTextAreaImplStandard {
-
- public Element createElement() {
- Element elem = super.createElement();
- DOM.setElementProperty(elem, "src", "javascript:''");
- return elem;
- }
-
- public native String getText() /*-{
- return this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.body.innerText;
- }-*/;
-
- public native void initElement() /*-{
- var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
- var _this = this;
- elem.onload = function() {
- _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplIE6::initEvents()();
- };
- elem.src = "RichTextIE.html";
- }-*/;
-
- native void initEvents() /*-{
- var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
- var handler = function(evt) {
- if (elem.__listener) {
- elem.__listener.
- @com.google.gwt.user.client.ui.RichTextArea::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
- }
- };
-
- var body = elem.contentWindow.document.body;
- body.attachEvent('onkeydown', handler);
- body.attachEvent('onkeyup', handler);
- body.attachEvent('onkeypress', handler);
- body.attachEvent('onmousedown', handler);
- body.attachEvent('onmouseup', handler);
- body.attachEvent('onmousemove', handler);
- body.attachEvent('onmouseover', handler);
- body.attachEvent('onmouseout', handler);
- body.attachEvent('onclick', handler);
- }-*/;
-
- boolean isRichEditingActive(Element e) {
- return true;
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+
+/**
+ * IE6-specific implementation of rich-text editing.
+ */
+public class RichTextAreaImplIE6 extends RichTextAreaImplStandard {
+
+ public Element createElement() {
+ Element elem = super.createElement();
+ DOM.setElementProperty(elem, "src", "javascript:''");
+ return elem;
+ }
+
+ public native String getText() /*-{
+ return this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.body.innerText;
+ }-*/;
+
+ public native void initElement() /*-{
+ var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
+ var _this = this;
+ elem.onload = function() {
+ _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplIE6::initEvents()();
+ };
+ elem.src = "RichTextIE.html";
+ }-*/;
+
+ native void initEvents() /*-{
+ var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
+ var handler = function(evt) {
+ if (elem.__listener) {
+ elem.__listener.
+ @com.google.gwt.user.client.ui.RichTextArea::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
+ }
+ };
+
+ var body = elem.contentWindow.document.body;
+ body.attachEvent('onkeydown', handler);
+ body.attachEvent('onkeyup', handler);
+ body.attachEvent('onkeypress', handler);
+ body.attachEvent('onmousedown', handler);
+ body.attachEvent('onmouseup', handler);
+ body.attachEvent('onmousemove', handler);
+ body.attachEvent('onmouseover', handler);
+ body.attachEvent('onmouseout', handler);
+ body.attachEvent('onclick', handler);
+ }-*/;
+
+ boolean isRichEditingActive(Element e) {
+ return true;
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplMozilla.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplMozilla.java
index 1984e62..6f6872f 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplMozilla.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplMozilla.java
@@ -1,28 +1,28 @@
-/*
- * Copyright 2007 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.impl;
-
-/**
- * Mozilla-specific implementation of rich-text editing.
- */
-public class RichTextAreaImplMozilla extends RichTextAreaImplStandard {
-
- public void setBackColor(String color) {
- // Gecko uses 'BackColor' for the *entire area's* background. 'HiliteColor'
- // does what we actually want.
- execCommand("HiliteColor", color);
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+/**
+ * Mozilla-specific implementation of rich-text editing.
+ */
+public class RichTextAreaImplMozilla extends RichTextAreaImplStandard {
+
+ public void setBackColor(String color) {
+ // Gecko uses 'BackColor' for the *entire area's* background. 'HiliteColor'
+ // does what we actually want.
+ execCommand("HiliteColor", color);
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplOpera.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplOpera.java
index 93343b4..cb8d7cd 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplOpera.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplOpera.java
@@ -1,152 +1,152 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.RichTextArea;
-
-/**
- * Opera implementation of rich-text editing.
- */
-public class RichTextAreaImplOpera extends RichTextAreaImplStandard {
-
- private static boolean supportsEditing;
-
- public Element createElement() {
- supportsEditing = detectEditingSupport();
- if (supportsEditing) {
- return super.createElement();
- }
- return DOM.createTextArea();
- }
-
- public String getHTML() {
- if (supportsEditing) {
- return super.getHTML();
- }
-
- // Unsupported fallback.
- return ((RichTextAreaImpl) this).getHTML();
- }
-
- public String getText() {
- if (supportsEditing) {
- return super.getText();
- }
-
- // Unsupported fallback.
- return ((RichTextAreaImpl) this).getText();
- }
-
- public void hookEvents(RichTextArea owner) {
- if (supportsEditing) {
- super.hookEvents(owner);
- return;
- }
-
- // Unsupported fallback.
- ((RichTextAreaImpl) this).hookEvents(owner);
- }
-
- public void initElement() {
- if (supportsEditing) {
- super.initElement();
- return;
- }
-
- // Unsupported fallback.
- ((RichTextAreaImpl) this).initElement();
- }
-
- public boolean isBasicEditingSupported() {
- return supportsEditing;
- }
-
- public boolean isFullEditingSupported() {
- return supportsEditing;
- }
-
- public void setBackColor(String color) {
- // Opera uses 'BackColor' for the *entire area's* background. 'HiliteColor'
- // does what we actually want.
- execCommand("HiliteColor", color);
- }
-
- public native void setFocus(boolean focused) /*-{
- // Opera needs the *iframe* focused, not its window.
- if (focused) {
- this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.focus();
- } else {
- this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.blur();
- }
- }-*/;
-
- public void setHTML(String html) {
- if (supportsEditing) {
- super.setHTML(html);
- }
-
- // Unsupported fallback.
- DOM.setElementProperty(elem, "value", html);
- }
-
- public void setText(String text) {
- if (supportsEditing) {
- super.setText(text);
- }
-
- // Unsupported fallback.
- DOM.setElementProperty(elem, "value", text);
- }
-
- public void unhookEvents(RichTextArea owner) {
- if (supportsEditing) {
- super.unhookEvents(owner);
- return;
- }
-
- // Unsupported fallback.
- ((RichTextAreaImpl) this).unhookEvents(owner);
- }
-
- void execCommand(String cmd, String param) {
- if (isRichEditingActive(elem)) {
- // Opera doesn't need focus for execCommand() to work, but focusing
- // the editor causes it to lose its selection, so we focus *after*
- // execCommand().
- execCommandAssumingFocus(cmd, param);
- setFocus(true);
-
- // TODO: Opera has now lost its selection. Figure out a way to restore it
- // reliably.
- }
- }
-
- boolean queryCommandState(String cmd) {
- // Opera doesn't need focus (and setting it dumps selection).
- return queryCommandStateAssumingFocus(cmd);
- }
-
- String queryCommandValue(String cmd) {
- // Opera doesn't need focus (and setting it dumps selection).
- return queryCommandValueAssumingFocus(cmd);
- }
-
- private native boolean detectEditingSupport() /*-{
- return !!$doc.designMode;
- }-*/;
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.RichTextArea;
+
+/**
+ * Opera implementation of rich-text editing.
+ */
+public class RichTextAreaImplOpera extends RichTextAreaImplStandard {
+
+ private static boolean supportsEditing;
+
+ public Element createElement() {
+ supportsEditing = detectEditingSupport();
+ if (supportsEditing) {
+ return super.createElement();
+ }
+ return DOM.createTextArea();
+ }
+
+ public String getHTML() {
+ if (supportsEditing) {
+ return super.getHTML();
+ }
+
+ // Unsupported fallback.
+ return ((RichTextAreaImpl) this).getHTML();
+ }
+
+ public String getText() {
+ if (supportsEditing) {
+ return super.getText();
+ }
+
+ // Unsupported fallback.
+ return ((RichTextAreaImpl) this).getText();
+ }
+
+ public void hookEvents(RichTextArea owner) {
+ if (supportsEditing) {
+ super.hookEvents(owner);
+ return;
+ }
+
+ // Unsupported fallback.
+ ((RichTextAreaImpl) this).hookEvents(owner);
+ }
+
+ public void initElement() {
+ if (supportsEditing) {
+ super.initElement();
+ return;
+ }
+
+ // Unsupported fallback.
+ ((RichTextAreaImpl) this).initElement();
+ }
+
+ public boolean isBasicEditingSupported() {
+ return supportsEditing;
+ }
+
+ public boolean isFullEditingSupported() {
+ return supportsEditing;
+ }
+
+ public void setBackColor(String color) {
+ // Opera uses 'BackColor' for the *entire area's* background. 'HiliteColor'
+ // does what we actually want.
+ execCommand("HiliteColor", color);
+ }
+
+ public native void setFocus(boolean focused) /*-{
+ // Opera needs the *iframe* focused, not its window.
+ if (focused) {
+ this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.focus();
+ } else {
+ this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.blur();
+ }
+ }-*/;
+
+ public void setHTML(String html) {
+ if (supportsEditing) {
+ super.setHTML(html);
+ }
+
+ // Unsupported fallback.
+ DOM.setElementProperty(elem, "value", html);
+ }
+
+ public void setText(String text) {
+ if (supportsEditing) {
+ super.setText(text);
+ }
+
+ // Unsupported fallback.
+ DOM.setElementProperty(elem, "value", text);
+ }
+
+ public void unhookEvents(RichTextArea owner) {
+ if (supportsEditing) {
+ super.unhookEvents(owner);
+ return;
+ }
+
+ // Unsupported fallback.
+ ((RichTextAreaImpl) this).unhookEvents(owner);
+ }
+
+ void execCommand(String cmd, String param) {
+ if (isRichEditingActive(elem)) {
+ // Opera doesn't need focus for execCommand() to work, but focusing
+ // the editor causes it to lose its selection, so we focus *after*
+ // execCommand().
+ execCommandAssumingFocus(cmd, param);
+ setFocus(true);
+
+ // TODO: Opera has now lost its selection. Figure out a way to restore it
+ // reliably.
+ }
+ }
+
+ boolean queryCommandState(String cmd) {
+ // Opera doesn't need focus (and setting it dumps selection).
+ return queryCommandStateAssumingFocus(cmd);
+ }
+
+ String queryCommandValue(String cmd) {
+ // Opera doesn't need focus (and setting it dumps selection).
+ return queryCommandValueAssumingFocus(cmd);
+ }
+
+ private native boolean detectEditingSupport() /*-{
+ return !!$doc.designMode;
+ }-*/;
+}
diff --git a/user/src/com/google/gwt/user/client/ui/impl/SuggestPickerImpl.java b/user/src/com/google/gwt/user/client/ui/impl/SuggestPickerImpl.java
index ccf936f..6cd92d2 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/SuggestPickerImpl.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/SuggestPickerImpl.java
@@ -1,160 +1,160 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.KeyboardListener;
-import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-
-import java.util.Collection;
-import java.util.Iterator;
-
-/**
- * Suggestion picker, used in the implementation of
- * {@link com.google.gwt.user.client.ui.SuggestBox}.
- */
-public class SuggestPickerImpl extends AbstractItemPickerImpl {
-
- /**
- * Default style for the picker.
- */
- private static final String STYLENAME_DEFAULT = "gwt-SuggestBoxPopup";
- private final boolean asHTML;
- private int startInvisible = Integer.MAX_VALUE;
-
- /**
- * Constructor for <code>SuggestPickerImpl</code>.
- *
- * @param asHTML flag used to indicate how to treat {@link Suggestion} display
- * strings
- */
- public SuggestPickerImpl(boolean asHTML) {
- this.asHTML = asHTML;
- setStyleName(STYLENAME_DEFAULT);
- }
-
- public boolean delegateKeyDown(char keyCode) {
- if (isAttached()) {
- switch (keyCode) {
- case KeyboardListener.KEY_DOWN:
- shiftSelection(1);
- return true;
- case KeyboardListener.KEY_UP:
- shiftSelection(-1);
- return true;
- case KeyboardListener.KEY_ENTER:
- commitSelection();
- return true;
- }
- }
- return false;
- }
-
- public int getItemCount() {
- if (startInvisible == Integer.MAX_VALUE) {
- return 0;
- } else {
- return startInvisible;
- }
- }
-
- /**
- * Sets the suggestions associated with this picker.
- *
- * @param suggestions suggestions for this picker
- */
- public final void setItems(Collection suggestions) {
- setItems(suggestions.iterator());
- }
-
- protected native Element getRow(Element elem, int row)/*-{
- return elem.rows[row];
- }-*/;
-
- void shiftSelection(int shift) {
- int newSelect = getSelectedIndex() + shift;
- if (newSelect >= super.getItemCount() || newSelect < 0
- || newSelect >= startInvisible) {
- return;
- }
- setSelection(getItem(newSelect));
- }
-
- /**
- * Ensures the existence of the given item and returns it.
- *
- * @param itemIndex item index to ensure
- * @return associated item
- */
- private Item ensureItem(int itemIndex) {
- for (int i = super.getItemCount(); i <= itemIndex; i++) {
- Item item = new Item(i);
- addItem(item, true);
- }
- return getItem(itemIndex);
- }
-
- /**
- * Sets the suggestions associated with this picker.
- */
- private final void setItems(Iterator suggestions) {
- int itemCount = 0;
-
- // Ensure all needed items exist and set each item's html to the given
- // suggestion.
- while (suggestions.hasNext()) {
- Item item = ensureItem(itemCount);
- Suggestion suggestion = (Suggestion) suggestions.next();
- String display = suggestion.getDisplayString();
- if (asHTML) {
- DOM.setInnerHTML(item.getElement(), display);
- } else {
- DOM.setInnerText(item.getElement(), display);
- }
- item.setValue(suggestion.getValue());
- ++itemCount;
- }
-
- if (itemCount == 0) {
- throw new IllegalStateException(
- "Must set at least one item in a SuggestPicker");
- }
-
- // Render visible all needed cells.
- int min = Math.min(itemCount, super.getItemCount());
- for (int i = startInvisible; i < min; i++) {
- setVisible(i, true);
- }
-
- // Render invisible all useless cells.
- startInvisible = itemCount;
- for (int i = itemCount; i < super.getItemCount(); i++) {
- setVisible(i, false);
- }
- }
-
- /**
- * Sets whether the given item is visible.
- *
- * @param itemIndex item index
- * @param visible visible boolean
- */
- private void setVisible(int itemIndex, boolean visible) {
- UIObject.setVisible(getRow(body, itemIndex), visible);
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.KeyboardListener;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Suggestion picker, used in the implementation of
+ * {@link com.google.gwt.user.client.ui.SuggestBox}.
+ */
+public class SuggestPickerImpl extends AbstractItemPickerImpl {
+
+ /**
+ * Default style for the picker.
+ */
+ private static final String STYLENAME_DEFAULT = "gwt-SuggestBoxPopup";
+ private final boolean asHTML;
+ private int startInvisible = Integer.MAX_VALUE;
+
+ /**
+ * Constructor for <code>SuggestPickerImpl</code>.
+ *
+ * @param asHTML flag used to indicate how to treat {@link Suggestion} display
+ * strings
+ */
+ public SuggestPickerImpl(boolean asHTML) {
+ this.asHTML = asHTML;
+ setStyleName(STYLENAME_DEFAULT);
+ }
+
+ public boolean delegateKeyDown(char keyCode) {
+ if (isAttached()) {
+ switch (keyCode) {
+ case KeyboardListener.KEY_DOWN:
+ shiftSelection(1);
+ return true;
+ case KeyboardListener.KEY_UP:
+ shiftSelection(-1);
+ return true;
+ case KeyboardListener.KEY_ENTER:
+ commitSelection();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int getItemCount() {
+ if (startInvisible == Integer.MAX_VALUE) {
+ return 0;
+ } else {
+ return startInvisible;
+ }
+ }
+
+ /**
+ * Sets the suggestions associated with this picker.
+ *
+ * @param suggestions suggestions for this picker
+ */
+ public final void setItems(Collection suggestions) {
+ setItems(suggestions.iterator());
+ }
+
+ protected native Element getRow(Element elem, int row)/*-{
+ return elem.rows[row];
+ }-*/;
+
+ void shiftSelection(int shift) {
+ int newSelect = getSelectedIndex() + shift;
+ if (newSelect >= super.getItemCount() || newSelect < 0
+ || newSelect >= startInvisible) {
+ return;
+ }
+ setSelection(getItem(newSelect));
+ }
+
+ /**
+ * Ensures the existence of the given item and returns it.
+ *
+ * @param itemIndex item index to ensure
+ * @return associated item
+ */
+ private Item ensureItem(int itemIndex) {
+ for (int i = super.getItemCount(); i <= itemIndex; i++) {
+ Item item = new Item(i);
+ addItem(item, true);
+ }
+ return getItem(itemIndex);
+ }
+
+ /**
+ * Sets the suggestions associated with this picker.
+ */
+ private final void setItems(Iterator suggestions) {
+ int itemCount = 0;
+
+ // Ensure all needed items exist and set each item's html to the given
+ // suggestion.
+ while (suggestions.hasNext()) {
+ Item item = ensureItem(itemCount);
+ Suggestion suggestion = (Suggestion) suggestions.next();
+ String display = suggestion.getDisplayString();
+ if (asHTML) {
+ DOM.setInnerHTML(item.getElement(), display);
+ } else {
+ DOM.setInnerText(item.getElement(), display);
+ }
+ item.setValue(suggestion.getValue());
+ ++itemCount;
+ }
+
+ if (itemCount == 0) {
+ throw new IllegalStateException(
+ "Must set at least one item in a SuggestPicker");
+ }
+
+ // Render visible all needed cells.
+ int min = Math.min(itemCount, super.getItemCount());
+ for (int i = startInvisible; i < min; i++) {
+ setVisible(i, true);
+ }
+
+ // Render invisible all useless cells.
+ startInvisible = itemCount;
+ for (int i = itemCount; i < super.getItemCount(); i++) {
+ setVisible(i, false);
+ }
+ }
+
+ /**
+ * Sets whether the given item is visible.
+ *
+ * @param itemIndex item index
+ * @param visible visible boolean
+ */
+ private void setVisible(int itemIndex, boolean visible) {
+ UIObject.setVisible(getRow(body, itemIndex), visible);
+ }
+}
diff --git a/user/src/com/google/gwt/user/rebind/ImageBundleBuilder.java b/user/src/com/google/gwt/user/rebind/ImageBundleBuilder.java
index 2343a89..bbc65b3 100644
--- a/user/src/com/google/gwt/user/rebind/ImageBundleBuilder.java
+++ b/user/src/com/google/gwt/user/rebind/ImageBundleBuilder.java
@@ -1,235 +1,235 @@
-/*
- * Copyright 2007 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.rebind;
-
-import com.google.gwt.core.ext.GeneratorContext;
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.dev.util.Util;
-
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.imageio.ImageIO;
-
-/**
- * Accumulates state for the bundled image.
- */
-class ImageBundleBuilder {
-
- /**
- * The rectangle at which the original image is placed into the composite
- * image.
- */
- public static class ImageRect {
-
- public final int height;
- public final BufferedImage image;
- public int left;
- public final int width;
-
- public ImageRect(BufferedImage image) {
- this.image = image;
- this.width = image.getWidth();
- this.height = image.getHeight();
- }
- }
-
- private final Map imageNameToImageRectMap = new HashMap();
- private final MessageDigest md5;
- private final List orderedImageRects = new ArrayList();
-
- public ImageBundleBuilder() {
- try {
- md5 = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("Error initializing MD5", e);
- }
- }
-
- /**
- * Assimilates the image associated with a particular image method into the
- * master composite. If the method names an image that has already been
- * assimilated, the existing image rectangle is reused.
- *
- * @param logger a hierarchical logger which logs to the hosted console
- * @param imageName the name of an image that can be found on the classpath
- * @throws UnableToCompleteException if the image with name
- * <code>imageName</code> cannot be added to the master composite image
- */
- public void assimilate(TreeLogger logger, String imageName)
- throws UnableToCompleteException {
-
- /*
- * Decide whether or not we need to add to the composite image. Either way,
- * we associated it with the rectangle of the specified image as it exists
- * within the composite image. Note that the coordinates of the rectangle
- * aren't computed until the composite is written.
- */
- ImageRect rect = getMapping(imageName);
- if (rect == null) {
- // Assimilate the image into the composite.
- rect = addImage(logger, imageName);
-
- // Map the URL to its image so that even if the same URL is used more than
- // once, we only include the referenced image once in the bundled image.
- putMapping(imageName, rect);
- }
- }
-
- public ImageRect getMapping(String imageName) {
- return (ImageRect) imageNameToImageRectMap.get(imageName);
- }
-
- public String writeBundledImage(TreeLogger logger, GeneratorContext context)
- throws UnableToCompleteException {
-
- // Determine how big the composited image should be by taking the
- // sum of the widths and the max of the heights.
- int nextLeft = 0;
- int maxHeight = 0;
- for (Iterator iter = orderedImageRects.iterator(); iter.hasNext();) {
- ImageRect imageRect = (ImageRect) iter.next();
- imageRect.left = nextLeft;
- nextLeft += imageRect.width;
- if (imageRect.height > maxHeight) {
- maxHeight = imageRect.height;
- }
- }
-
- // Create the bundled image.
- BufferedImage bundledImage = new BufferedImage(nextLeft, maxHeight,
- BufferedImage.TYPE_INT_ARGB_PRE);
- Graphics2D g2d = bundledImage.createGraphics();
-
- for (Iterator iter = orderedImageRects.iterator(); iter.hasNext();) {
- ImageRect imageRect = (ImageRect) iter.next();
- g2d.drawImage(imageRect.image, imageRect.left, 0, null);
- }
- g2d.dispose();
-
- // Compute the strong name as the hex version of the hash.
- byte[] hash = md5.digest();
- char[] strongName = new char[2 * hash.length];
- int j = 0;
- for (int i = 0; i < hash.length; i++) {
- strongName[j++] = Util.HEX_CHARS[(hash[i] & 0xF0) >> 4];
- strongName[j++] = Util.HEX_CHARS[hash[i] & 0x0F];
- }
-
- // Only PNG is supported right now, but still we introduce a variable to
- // anticipate an update when the best output file type is inferred.
- String bundleFileType = "png";
-
- // Compute the file name. The '.cache' part indicates that it can be
- // permanently cached.
- String bundleFileName = new String(strongName) + ".cache." + bundleFileType;
-
- OutputStream outStream = context.tryCreateResource(logger, bundleFileName);
-
- if (outStream != null) {
- try {
- // Write the image bytes to the pending stream.
- if (!ImageIO.write(bundledImage, bundleFileType, outStream)) {
- logger.log(TreeLogger.ERROR, "Unsupported output file type", null);
- throw new UnableToCompleteException();
- }
-
- // Commit the stream.
- context.commitResource(logger, outStream);
-
- } catch (IOException e) {
- logger.log(TreeLogger.ERROR, "Failed while writing", e);
- throw new UnableToCompleteException();
- }
- } else {
- logger.log(
- TreeLogger.TRACE,
- "Generated image bundle file already exists; no need to rewrite it.",
- null);
- }
-
- return bundleFileName;
- }
-
- private ImageRect addImage(TreeLogger logger, String imageName)
- throws UnableToCompleteException {
-
- logger = logger.branch(TreeLogger.TRACE,
- "Adding image '" + imageName + "'", null);
-
- // Fetch the image.
- BufferedImage image = null;
- try {
- // Could turn this lookup logic into an externally-supplied policy for
- // increased generality.
- URL imageUrl = getClass().getClassLoader().getResource(imageName);
- if (imageUrl == null) {
- // This should never happen, because this check is done right after
- // the image name is retrieved from the metadata or the method name.
- // If there is a failure in obtaining the resource, it will happen
- // before this point.
- logger.log(
- TreeLogger.ERROR,
- "Resource not found on classpath (is the name specified as Class.getResource() would expect?)",
- null);
- throw new UnableToCompleteException();
- }
-
- // Assimilate this file's bytes into the MD5.
- InputStream is = imageUrl.openStream();
- BufferedInputStream bis = new BufferedInputStream(is);
- byte imgByte;
- while ((imgByte = (byte) bis.read()) != -1) {
- md5.update(imgByte);
- }
- is.close();
-
- // Load the image from the URL instead of the stream (with the assumption
- // that having the URL provides a tiny bit more context to the parser).
- image = ImageIO.read(imageUrl);
- if (image == null) {
- logger.log(TreeLogger.ERROR, "Unrecognized image file format", null);
- throw new UnableToCompleteException();
- }
-
- } catch (IOException e) {
- logger.log(TreeLogger.ERROR, "Unable to read image resource", null);
- throw new UnableToCompleteException();
- }
-
- ImageRect imageRect = new ImageRect(image);
- orderedImageRects.add(imageRect);
- return imageRect;
- }
-
- private void putMapping(String imageName, ImageRect rect) {
- imageNameToImageRectMap.put(imageName, rect);
- }
-
-}
+/*
+ * Copyright 2007 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.rebind;
+
+import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.util.Util;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.imageio.ImageIO;
+
+/**
+ * Accumulates state for the bundled image.
+ */
+class ImageBundleBuilder {
+
+ /**
+ * The rectangle at which the original image is placed into the composite
+ * image.
+ */
+ public static class ImageRect {
+
+ public final int height;
+ public final BufferedImage image;
+ public int left;
+ public final int width;
+
+ public ImageRect(BufferedImage image) {
+ this.image = image;
+ this.width = image.getWidth();
+ this.height = image.getHeight();
+ }
+ }
+
+ private final Map imageNameToImageRectMap = new HashMap();
+ private final MessageDigest md5;
+ private final List orderedImageRects = new ArrayList();
+
+ public ImageBundleBuilder() {
+ try {
+ md5 = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Error initializing MD5", e);
+ }
+ }
+
+ /**
+ * Assimilates the image associated with a particular image method into the
+ * master composite. If the method names an image that has already been
+ * assimilated, the existing image rectangle is reused.
+ *
+ * @param logger a hierarchical logger which logs to the hosted console
+ * @param imageName the name of an image that can be found on the classpath
+ * @throws UnableToCompleteException if the image with name
+ * <code>imageName</code> cannot be added to the master composite image
+ */
+ public void assimilate(TreeLogger logger, String imageName)
+ throws UnableToCompleteException {
+
+ /*
+ * Decide whether or not we need to add to the composite image. Either way,
+ * we associated it with the rectangle of the specified image as it exists
+ * within the composite image. Note that the coordinates of the rectangle
+ * aren't computed until the composite is written.
+ */
+ ImageRect rect = getMapping(imageName);
+ if (rect == null) {
+ // Assimilate the image into the composite.
+ rect = addImage(logger, imageName);
+
+ // Map the URL to its image so that even if the same URL is used more than
+ // once, we only include the referenced image once in the bundled image.
+ putMapping(imageName, rect);
+ }
+ }
+
+ public ImageRect getMapping(String imageName) {
+ return (ImageRect) imageNameToImageRectMap.get(imageName);
+ }
+
+ public String writeBundledImage(TreeLogger logger, GeneratorContext context)
+ throws UnableToCompleteException {
+
+ // Determine how big the composited image should be by taking the
+ // sum of the widths and the max of the heights.
+ int nextLeft = 0;
+ int maxHeight = 0;
+ for (Iterator iter = orderedImageRects.iterator(); iter.hasNext();) {
+ ImageRect imageRect = (ImageRect) iter.next();
+ imageRect.left = nextLeft;
+ nextLeft += imageRect.width;
+ if (imageRect.height > maxHeight) {
+ maxHeight = imageRect.height;
+ }
+ }
+
+ // Create the bundled image.
+ BufferedImage bundledImage = new BufferedImage(nextLeft, maxHeight,
+ BufferedImage.TYPE_INT_ARGB_PRE);
+ Graphics2D g2d = bundledImage.createGraphics();
+
+ for (Iterator iter = orderedImageRects.iterator(); iter.hasNext();) {
+ ImageRect imageRect = (ImageRect) iter.next();
+ g2d.drawImage(imageRect.image, imageRect.left, 0, null);
+ }
+ g2d.dispose();
+
+ // Compute the strong name as the hex version of the hash.
+ byte[] hash = md5.digest();
+ char[] strongName = new char[2 * hash.length];
+ int j = 0;
+ for (int i = 0; i < hash.length; i++) {
+ strongName[j++] = Util.HEX_CHARS[(hash[i] & 0xF0) >> 4];
+ strongName[j++] = Util.HEX_CHARS[hash[i] & 0x0F];
+ }
+
+ // Only PNG is supported right now, but still we introduce a variable to
+ // anticipate an update when the best output file type is inferred.
+ String bundleFileType = "png";
+
+ // Compute the file name. The '.cache' part indicates that it can be
+ // permanently cached.
+ String bundleFileName = new String(strongName) + ".cache." + bundleFileType;
+
+ OutputStream outStream = context.tryCreateResource(logger, bundleFileName);
+
+ if (outStream != null) {
+ try {
+ // Write the image bytes to the pending stream.
+ if (!ImageIO.write(bundledImage, bundleFileType, outStream)) {
+ logger.log(TreeLogger.ERROR, "Unsupported output file type", null);
+ throw new UnableToCompleteException();
+ }
+
+ // Commit the stream.
+ context.commitResource(logger, outStream);
+
+ } catch (IOException e) {
+ logger.log(TreeLogger.ERROR, "Failed while writing", e);
+ throw new UnableToCompleteException();
+ }
+ } else {
+ logger.log(
+ TreeLogger.TRACE,
+ "Generated image bundle file already exists; no need to rewrite it.",
+ null);
+ }
+
+ return bundleFileName;
+ }
+
+ private ImageRect addImage(TreeLogger logger, String imageName)
+ throws UnableToCompleteException {
+
+ logger = logger.branch(TreeLogger.TRACE,
+ "Adding image '" + imageName + "'", null);
+
+ // Fetch the image.
+ BufferedImage image = null;
+ try {
+ // Could turn this lookup logic into an externally-supplied policy for
+ // increased generality.
+ URL imageUrl = getClass().getClassLoader().getResource(imageName);
+ if (imageUrl == null) {
+ // This should never happen, because this check is done right after
+ // the image name is retrieved from the metadata or the method name.
+ // If there is a failure in obtaining the resource, it will happen
+ // before this point.
+ logger.log(
+ TreeLogger.ERROR,
+ "Resource not found on classpath (is the name specified as Class.getResource() would expect?)",
+ null);
+ throw new UnableToCompleteException();
+ }
+
+ // Assimilate this file's bytes into the MD5.
+ InputStream is = imageUrl.openStream();
+ BufferedInputStream bis = new BufferedInputStream(is);
+ byte imgByte;
+ while ((imgByte = (byte) bis.read()) != -1) {
+ md5.update(imgByte);
+ }
+ is.close();
+
+ // Load the image from the URL instead of the stream (with the assumption
+ // that having the URL provides a tiny bit more context to the parser).
+ image = ImageIO.read(imageUrl);
+ if (image == null) {
+ logger.log(TreeLogger.ERROR, "Unrecognized image file format", null);
+ throw new UnableToCompleteException();
+ }
+
+ } catch (IOException e) {
+ logger.log(TreeLogger.ERROR, "Unable to read image resource", null);
+ throw new UnableToCompleteException();
+ }
+
+ ImageRect imageRect = new ImageRect(image);
+ orderedImageRects.add(imageRect);
+ return imageRect;
+ }
+
+ private void putMapping(String imageName, ImageRect rect) {
+ imageNameToImageRectMap.put(imageName, rect);
+ }
+
+}
diff --git a/user/src/com/google/gwt/user/rebind/ImageBundleGenerator.java b/user/src/com/google/gwt/user/rebind/ImageBundleGenerator.java
index 3b86dc0..4e3f6ea 100644
--- a/user/src/com/google/gwt/user/rebind/ImageBundleGenerator.java
+++ b/user/src/com/google/gwt/user/rebind/ImageBundleGenerator.java
@@ -1,343 +1,343 @@
-/*
- * Copyright 2007 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.rebind;
-
-import com.google.gwt.core.ext.Generator;
-import com.google.gwt.core.ext.GeneratorContext;
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.core.ext.UnableToCompleteException;
-import com.google.gwt.core.ext.typeinfo.JClassType;
-import com.google.gwt.core.ext.typeinfo.JMethod;
-import com.google.gwt.core.ext.typeinfo.NotFoundException;
-import com.google.gwt.core.ext.typeinfo.TypeOracle;
-
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.net.URL;
-
-/**
- * Generates an implementation of a user-defined interface <code>T</code> that
- * extends {@link com.google.gwt.user.client.ImageBundle}.
- *
- * Each method in <code>T</code> must be declared to return
- * {@link com.google.gwt.user.client.ui.AbstractImagePrototype},
- * take no parameters, and optionally specify the metadata tag
- * <code>gwt.resource</code> as the name of an image that can be found in the
- * classpath. In the absence of the metatadata tag, the method name with an
- * extension of <code>.png, .jpg, or .gif</code> defines the name of the image,
- * and the image file must be located in the same package as <code>T</code>.
- */
-public class ImageBundleGenerator extends Generator {
-
- private static final String ABSTRACTIMAGEPROTOTYPE_QNAME =
- "com.google.gwt.user.client.ui.AbstractImagePrototype";
-
- private static final String CLIPPEDIMAGEPROTOTYPE_QNAME =
- "com.google.gwt.user.client.ui.impl.ClippedImagePrototype";
-
- private static final String IMAGEBUNDLE_QNAME = "com.google.gwt.user.client.ImageBundle";
-
- private static final String METADATA_TAG = "gwt.resource";
-
- private static final String [] IMAGE_FILE_EXTENSIONS = {"png", "gif", "jpg"};
-
- public ImageBundleGenerator() {
- }
-
- public String generate(TreeLogger logger, GeneratorContext context,
- String typeName) throws UnableToCompleteException {
-
- TypeOracle typeOracle = context.getTypeOracle();
-
- // Get metadata describing the user's class.
- JClassType userType = getValidUserType(logger, typeName, typeOracle);
-
- // Get the methods that correspond to constituent images.
- JMethod[] imgMethods = getValidImageMethods(logger, userType);
-
- // Write the new class.
- String resultName = generateImpl(logger, context, userType, imgMethods);
-
- // Return the complete name of the generated class.
- return resultName;
- }
-
- private String computeSubclassName(JClassType userType) {
- String baseName = userType.getName().replace('.', '_');
- return baseName + "_generatedBundle";
- }
-
- private void generateImageMethod(TreeLogger logger,
- ImageBundleBuilder compositeImage,
- SourceWriter sw, JMethod method)
- throws UnableToCompleteException {
-
- String imageName = getImageUrlFromMetaDataOrMethodName(logger, method);
- String decl = method.getReadableDeclaration(false, true, true, true, true);
-
- {
- sw.indent();
-
- // Create a singleton that this method can return. There is no need to
- // create a new instance every time this method is called, since
- // ClippedImagePrototype is immutable
-
- ImageBundleBuilder.ImageRect imageRect = compositeImage.getMapping(imageName);
- String singletonName = method.getName() + "_SINGLETON";
-
- sw.print("private static final ClippedImagePrototype ");
- sw.print(singletonName);
- sw.print(" = new ClippedImagePrototype(IMAGE_BUNDLE_URL, ");
- sw.print(Integer.toString(imageRect.left));
- sw.print(", 0, ");
- sw.print(Integer.toString(imageRect.width));
- sw.print(", ");
- sw.print(Integer.toString(imageRect.height));
- sw.println(");");
-
- sw.print(decl);
- sw.println(" {");
-
- {
- sw.indent();
- sw.print("return ");
- sw.print(singletonName);
- sw.println(";");
- sw.outdent();
- }
-
- sw.println("}");
- sw.outdent();
- }
- }
-
- private String generateImpl(TreeLogger logger, GeneratorContext context,
- JClassType userType, JMethod[] imageMethods)
- throws UnableToCompleteException {
- // Compute the package and class names of the generated class.
- String pkgName = userType.getPackage().getName();
- String subName = computeSubclassName(userType);
-
- // Begin writing the generated source.
- ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
- pkgName, subName);
- f.addImport(ABSTRACTIMAGEPROTOTYPE_QNAME);
- f.addImport(CLIPPEDIMAGEPROTOTYPE_QNAME);
- f.addImplementedInterface(userType.getQualifiedSourceName());
-
- PrintWriter pw = context.tryCreate(logger, pkgName, subName);
- if (pw != null) {
- SourceWriter sw = f.createSourceWriter(context, pw);
-
- // Build a compound image from each individual image.
- ImageBundleBuilder bulder = new ImageBundleBuilder();
-
- for (int i = 0; i < imageMethods.length; i++) {
- JMethod method = imageMethods[i];
- String imageUrl = getImageUrlFromMetaDataOrMethodName(logger, method);
- assert (imageUrl != null);
- bulder.assimilate(logger, imageUrl);
- }
-
- // Write the compound image into the output directory.
- String bundledImageUrl = bulder.writeBundledImage(logger, context);
-
- // Emit a constant for the composite url.
- sw.print("private static final String IMAGE_BUNDLE_URL = \"");
- sw.print(escape(bundledImageUrl));
- sw.println("\";");
-
- // Generate an implementation of each method.
- for (int i = 0; i < imageMethods.length; i++) {
- JMethod method = imageMethods[i];
- generateImageMethod(logger, bulder, sw, method);
- }
-
- // Finish.
- sw.commit(logger);
- }
-
- return f.getCreatedClassName();
- }
-
- // Assume this is only called for valid methods.
- private String getImageUrlFromMetaDataOrMethodName(TreeLogger logger,
- JMethod method)
- throws UnableToCompleteException {
-
- String[][] md = method.getMetaData(METADATA_TAG);
-
- if (md.length == 1) {
- // Metadata is available, so get the image url from the metadata
- int lastTagIndex = md.length - 1;
- int lastValueIndex = md[lastTagIndex].length - 1;
- String imageNameFromMetaData = md[lastTagIndex][lastValueIndex];
-
- // Make sure the name is either absolute or package-relative.
- if (imageNameFromMetaData.indexOf("/") == -1) {
- String pkgName = method.getEnclosingType().getPackage().getName();
- // This construction handles the default package correctly, too.
- imageNameFromMetaData = pkgName.replace('.', '/') + "/" + imageNameFromMetaData;
- }
-
- // Make sure that the resource exists on the classpath. In the future,
- // this code will have to be changed if images are loaded from the
- // source path or public path.
- URL imageResourceURL = getClass().getClassLoader().getResource(imageNameFromMetaData);
- if (imageResourceURL == null) {
- logger.log(
- TreeLogger.ERROR,
- "Resource " + imageNameFromMetaData +
- " not found on classpath (is the name specified as Class.getResource() would expect?)",
- null);
- throw new UnableToCompleteException();
- }
-
- return imageNameFromMetaData;
- }
-
- String imageNameFromMethod = null;
- String packageAndMethodName =
- method.getEnclosingType().getPackage().getName().replace('.', '/') +
- '/' + method.getName();
- // There is no metadata available, so the image url will be generated from
- // the method name with an image file extension.
- for (int i = 0; i < IMAGE_FILE_EXTENSIONS.length; i++) {
- String possibleImageName = packageAndMethodName + '.' + IMAGE_FILE_EXTENSIONS[i];
- // Check to see if the resource exists on the classpath for each possible
- // image file extension. This code will have to be changed if images are
- // loaded from the source path or the public path.
- URL imageResourceURL = getClass().getClassLoader().getResource(possibleImageName);
- if (imageResourceURL != null) {
- imageNameFromMethod = possibleImageName;
- break;
- }
- }
-
- if (imageNameFromMethod == null) {
-
- StringBuffer errorStringBuf = new StringBuffer();
- for (int i = 0; i < IMAGE_FILE_EXTENSIONS.length; i++) {
-
- errorStringBuf.append(IMAGE_FILE_EXTENSIONS[i]);
-
- if (i != IMAGE_FILE_EXTENSIONS.length - 1) {
- errorStringBuf.append(", ");
- }
- }
-
- logger.log(
- TreeLogger.ERROR,
- "Resource " + packageAndMethodName + ".(" + errorStringBuf.toString() +
- ") not found on classpath (is the name specified as Class.getResource() would expect?)",
- null);
- throw new UnableToCompleteException();
- }
-
- return imageNameFromMethod;
- }
-
- private JMethod[] getValidImageMethods(TreeLogger logger, JClassType userType)
- throws UnableToCompleteException {
-
- logger = logger.branch(TreeLogger.TRACE, "Analyzing methods on "
- + userType.getQualifiedSourceName(), null);
-
- final JClassType imageClass;
- try {
- imageClass = userType.getOracle().getType(ABSTRACTIMAGEPROTOTYPE_QNAME);
- } catch (NotFoundException e) {
- logger.log(TreeLogger.ERROR, "GWT " + ABSTRACTIMAGEPROTOTYPE_QNAME
- + "class is not available", e);
- throw new UnableToCompleteException();
- }
-
- Map rejectedMethodsAndWhy = new HashMap();
- JMethod[] leafMethods = userType.getOverridableMethods();
- for (int i = 0; i < leafMethods.length; i++) {
- JMethod method = leafMethods[i];
-
- if (method.getReturnType() != imageClass) {
- rejectedMethodsAndWhy.put(method, "Return type must be "
- + ABSTRACTIMAGEPROTOTYPE_QNAME);
- continue;
- }
-
- if (method.getParameters().length > 0) {
- rejectedMethodsAndWhy.put(method, "Method cannot take parameters");
- continue;
- }
-
- String[][] md = method.getMetaData(METADATA_TAG);
- if ( (md.length > 1) || (md.length == 1 && md[0].length != 1)) {
- rejectedMethodsAndWhy.put(method,
- "Expecting either no metadata tags, or one metadata tag of the form '@gwt.resource <resource-name>'");
- }
- }
-
- // Make sure there aren't any invalid methods.
- if (!rejectedMethodsAndWhy.isEmpty()) {
- logger = logger.branch(TreeLogger.ERROR,
- "The following methods are invalid on an image bundle:", null);
- for (Iterator iter = rejectedMethodsAndWhy.entrySet().iterator(); iter.hasNext();) {
- Map.Entry entry = (Map.Entry) iter.next();
- JMethod badMethod = (JMethod) entry.getKey();
- String reason = (String) entry.getValue();
- TreeLogger branch = logger.branch(TreeLogger.ERROR,
- badMethod.getReadableDeclaration(), null);
- branch.log(TreeLogger.ERROR, reason, null);
- }
- throw new UnableToCompleteException();
- }
-
- return leafMethods;
- }
-
- private JClassType getValidUserType(TreeLogger logger, String typeName,
- TypeOracle typeOracle) throws UnableToCompleteException {
- try {
- // Get the type that the user is introducing.
- JClassType userType = typeOracle.getType(typeName);
-
- // Get the type this generator is designed to support.
- JClassType magicType = typeOracle.findType(IMAGEBUNDLE_QNAME);
-
- // Ensure it's an interface.
- if (userType.isInterface() == null) {
- logger.log(TreeLogger.ERROR, userType.getQualifiedSourceName()
- + " must be an interface", null);
- throw new UnableToCompleteException();
- }
-
- // Ensure proper derivation.
- if (!userType.isAssignableTo(magicType)) {
- logger.log(TreeLogger.ERROR, userType.getQualifiedSourceName()
- + " must be assignable to " + magicType.getQualifiedSourceName(),
- null);
- throw new UnableToCompleteException();
- }
-
- return userType;
-
- } catch (NotFoundException e) {
- logger.log(TreeLogger.ERROR, "Unable to find required type(s)", e);
- throw new UnableToCompleteException();
- }
- }
-
-}
+/*
+ * Copyright 2007 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.rebind;
+
+import com.google.gwt.core.ext.Generator;
+import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JMethod;
+import com.google.gwt.core.ext.typeinfo.NotFoundException;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.net.URL;
+
+/**
+ * Generates an implementation of a user-defined interface <code>T</code> that
+ * extends {@link com.google.gwt.user.client.ImageBundle}.
+ *
+ * Each method in <code>T</code> must be declared to return
+ * {@link com.google.gwt.user.client.ui.AbstractImagePrototype},
+ * take no parameters, and optionally specify the metadata tag
+ * <code>gwt.resource</code> as the name of an image that can be found in the
+ * classpath. In the absence of the metatadata tag, the method name with an
+ * extension of <code>.png, .jpg, or .gif</code> defines the name of the image,
+ * and the image file must be located in the same package as <code>T</code>.
+ */
+public class ImageBundleGenerator extends Generator {
+
+ private static final String ABSTRACTIMAGEPROTOTYPE_QNAME =
+ "com.google.gwt.user.client.ui.AbstractImagePrototype";
+
+ private static final String CLIPPEDIMAGEPROTOTYPE_QNAME =
+ "com.google.gwt.user.client.ui.impl.ClippedImagePrototype";
+
+ private static final String IMAGEBUNDLE_QNAME = "com.google.gwt.user.client.ImageBundle";
+
+ private static final String METADATA_TAG = "gwt.resource";
+
+ private static final String [] IMAGE_FILE_EXTENSIONS = {"png", "gif", "jpg"};
+
+ public ImageBundleGenerator() {
+ }
+
+ public String generate(TreeLogger logger, GeneratorContext context,
+ String typeName) throws UnableToCompleteException {
+
+ TypeOracle typeOracle = context.getTypeOracle();
+
+ // Get metadata describing the user's class.
+ JClassType userType = getValidUserType(logger, typeName, typeOracle);
+
+ // Get the methods that correspond to constituent images.
+ JMethod[] imgMethods = getValidImageMethods(logger, userType);
+
+ // Write the new class.
+ String resultName = generateImpl(logger, context, userType, imgMethods);
+
+ // Return the complete name of the generated class.
+ return resultName;
+ }
+
+ private String computeSubclassName(JClassType userType) {
+ String baseName = userType.getName().replace('.', '_');
+ return baseName + "_generatedBundle";
+ }
+
+ private void generateImageMethod(TreeLogger logger,
+ ImageBundleBuilder compositeImage,
+ SourceWriter sw, JMethod method)
+ throws UnableToCompleteException {
+
+ String imageName = getImageUrlFromMetaDataOrMethodName(logger, method);
+ String decl = method.getReadableDeclaration(false, true, true, true, true);
+
+ {
+ sw.indent();
+
+ // Create a singleton that this method can return. There is no need to
+ // create a new instance every time this method is called, since
+ // ClippedImagePrototype is immutable
+
+ ImageBundleBuilder.ImageRect imageRect = compositeImage.getMapping(imageName);
+ String singletonName = method.getName() + "_SINGLETON";
+
+ sw.print("private static final ClippedImagePrototype ");
+ sw.print(singletonName);
+ sw.print(" = new ClippedImagePrototype(IMAGE_BUNDLE_URL, ");
+ sw.print(Integer.toString(imageRect.left));
+ sw.print(", 0, ");
+ sw.print(Integer.toString(imageRect.width));
+ sw.print(", ");
+ sw.print(Integer.toString(imageRect.height));
+ sw.println(");");
+
+ sw.print(decl);
+ sw.println(" {");
+
+ {
+ sw.indent();
+ sw.print("return ");
+ sw.print(singletonName);
+ sw.println(";");
+ sw.outdent();
+ }
+
+ sw.println("}");
+ sw.outdent();
+ }
+ }
+
+ private String generateImpl(TreeLogger logger, GeneratorContext context,
+ JClassType userType, JMethod[] imageMethods)
+ throws UnableToCompleteException {
+ // Compute the package and class names of the generated class.
+ String pkgName = userType.getPackage().getName();
+ String subName = computeSubclassName(userType);
+
+ // Begin writing the generated source.
+ ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
+ pkgName, subName);
+ f.addImport(ABSTRACTIMAGEPROTOTYPE_QNAME);
+ f.addImport(CLIPPEDIMAGEPROTOTYPE_QNAME);
+ f.addImplementedInterface(userType.getQualifiedSourceName());
+
+ PrintWriter pw = context.tryCreate(logger, pkgName, subName);
+ if (pw != null) {
+ SourceWriter sw = f.createSourceWriter(context, pw);
+
+ // Build a compound image from each individual image.
+ ImageBundleBuilder bulder = new ImageBundleBuilder();
+
+ for (int i = 0; i < imageMethods.length; i++) {
+ JMethod method = imageMethods[i];
+ String imageUrl = getImageUrlFromMetaDataOrMethodName(logger, method);
+ assert (imageUrl != null);
+ bulder.assimilate(logger, imageUrl);
+ }
+
+ // Write the compound image into the output directory.
+ String bundledImageUrl = bulder.writeBundledImage(logger, context);
+
+ // Emit a constant for the composite url.
+ sw.print("private static final String IMAGE_BUNDLE_URL = \"");
+ sw.print(escape(bundledImageUrl));
+ sw.println("\";");
+
+ // Generate an implementation of each method.
+ for (int i = 0; i < imageMethods.length; i++) {
+ JMethod method = imageMethods[i];
+ generateImageMethod(logger, bulder, sw, method);
+ }
+
+ // Finish.
+ sw.commit(logger);
+ }
+
+ return f.getCreatedClassName();
+ }
+
+ // Assume this is only called for valid methods.
+ private String getImageUrlFromMetaDataOrMethodName(TreeLogger logger,
+ JMethod method)
+ throws UnableToCompleteException {
+
+ String[][] md = method.getMetaData(METADATA_TAG);
+
+ if (md.length == 1) {
+ // Metadata is available, so get the image url from the metadata
+ int lastTagIndex = md.length - 1;
+ int lastValueIndex = md[lastTagIndex].length - 1;
+ String imageNameFromMetaData = md[lastTagIndex][lastValueIndex];
+
+ // Make sure the name is either absolute or package-relative.
+ if (imageNameFromMetaData.indexOf("/") == -1) {
+ String pkgName = method.getEnclosingType().getPackage().getName();
+ // This construction handles the default package correctly, too.
+ imageNameFromMetaData = pkgName.replace('.', '/') + "/" + imageNameFromMetaData;
+ }
+
+ // Make sure that the resource exists on the classpath. In the future,
+ // this code will have to be changed if images are loaded from the
+ // source path or public path.
+ URL imageResourceURL = getClass().getClassLoader().getResource(imageNameFromMetaData);
+ if (imageResourceURL == null) {
+ logger.log(
+ TreeLogger.ERROR,
+ "Resource " + imageNameFromMetaData +
+ " not found on classpath (is the name specified as Class.getResource() would expect?)",
+ null);
+ throw new UnableToCompleteException();
+ }
+
+ return imageNameFromMetaData;
+ }
+
+ String imageNameFromMethod = null;
+ String packageAndMethodName =
+ method.getEnclosingType().getPackage().getName().replace('.', '/') +
+ '/' + method.getName();
+ // There is no metadata available, so the image url will be generated from
+ // the method name with an image file extension.
+ for (int i = 0; i < IMAGE_FILE_EXTENSIONS.length; i++) {
+ String possibleImageName = packageAndMethodName + '.' + IMAGE_FILE_EXTENSIONS[i];
+ // Check to see if the resource exists on the classpath for each possible
+ // image file extension. This code will have to be changed if images are
+ // loaded from the source path or the public path.
+ URL imageResourceURL = getClass().getClassLoader().getResource(possibleImageName);
+ if (imageResourceURL != null) {
+ imageNameFromMethod = possibleImageName;
+ break;
+ }
+ }
+
+ if (imageNameFromMethod == null) {
+
+ StringBuffer errorStringBuf = new StringBuffer();
+ for (int i = 0; i < IMAGE_FILE_EXTENSIONS.length; i++) {
+
+ errorStringBuf.append(IMAGE_FILE_EXTENSIONS[i]);
+
+ if (i != IMAGE_FILE_EXTENSIONS.length - 1) {
+ errorStringBuf.append(", ");
+ }
+ }
+
+ logger.log(
+ TreeLogger.ERROR,
+ "Resource " + packageAndMethodName + ".(" + errorStringBuf.toString() +
+ ") not found on classpath (is the name specified as Class.getResource() would expect?)",
+ null);
+ throw new UnableToCompleteException();
+ }
+
+ return imageNameFromMethod;
+ }
+
+ private JMethod[] getValidImageMethods(TreeLogger logger, JClassType userType)
+ throws UnableToCompleteException {
+
+ logger = logger.branch(TreeLogger.TRACE, "Analyzing methods on "
+ + userType.getQualifiedSourceName(), null);
+
+ final JClassType imageClass;
+ try {
+ imageClass = userType.getOracle().getType(ABSTRACTIMAGEPROTOTYPE_QNAME);
+ } catch (NotFoundException e) {
+ logger.log(TreeLogger.ERROR, "GWT " + ABSTRACTIMAGEPROTOTYPE_QNAME
+ + "class is not available", e);
+ throw new UnableToCompleteException();
+ }
+
+ Map rejectedMethodsAndWhy = new HashMap();
+ JMethod[] leafMethods = userType.getOverridableMethods();
+ for (int i = 0; i < leafMethods.length; i++) {
+ JMethod method = leafMethods[i];
+
+ if (method.getReturnType() != imageClass) {
+ rejectedMethodsAndWhy.put(method, "Return type must be "
+ + ABSTRACTIMAGEPROTOTYPE_QNAME);
+ continue;
+ }
+
+ if (method.getParameters().length > 0) {
+ rejectedMethodsAndWhy.put(method, "Method cannot take parameters");
+ continue;
+ }
+
+ String[][] md = method.getMetaData(METADATA_TAG);
+ if ( (md.length > 1) || (md.length == 1 && md[0].length != 1)) {
+ rejectedMethodsAndWhy.put(method,
+ "Expecting either no metadata tags, or one metadata tag of the form '@gwt.resource <resource-name>'");
+ }
+ }
+
+ // Make sure there aren't any invalid methods.
+ if (!rejectedMethodsAndWhy.isEmpty()) {
+ logger = logger.branch(TreeLogger.ERROR,
+ "The following methods are invalid on an image bundle:", null);
+ for (Iterator iter = rejectedMethodsAndWhy.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ JMethod badMethod = (JMethod) entry.getKey();
+ String reason = (String) entry.getValue();
+ TreeLogger branch = logger.branch(TreeLogger.ERROR,
+ badMethod.getReadableDeclaration(), null);
+ branch.log(TreeLogger.ERROR, reason, null);
+ }
+ throw new UnableToCompleteException();
+ }
+
+ return leafMethods;
+ }
+
+ private JClassType getValidUserType(TreeLogger logger, String typeName,
+ TypeOracle typeOracle) throws UnableToCompleteException {
+ try {
+ // Get the type that the user is introducing.
+ JClassType userType = typeOracle.getType(typeName);
+
+ // Get the type this generator is designed to support.
+ JClassType magicType = typeOracle.findType(IMAGEBUNDLE_QNAME);
+
+ // Ensure it's an interface.
+ if (userType.isInterface() == null) {
+ logger.log(TreeLogger.ERROR, userType.getQualifiedSourceName()
+ + " must be an interface", null);
+ throw new UnableToCompleteException();
+ }
+
+ // Ensure proper derivation.
+ if (!userType.isAssignableTo(magicType)) {
+ logger.log(TreeLogger.ERROR, userType.getQualifiedSourceName()
+ + " must be assignable to " + magicType.getQualifiedSourceName(),
+ null);
+ throw new UnableToCompleteException();
+ }
+
+ return userType;
+
+ } catch (NotFoundException e) {
+ logger.log(TreeLogger.ERROR, "Unable to find required type(s)", e);
+ throw new UnableToCompleteException();
+ }
+ }
+
+}
diff --git a/user/super/com/google/gwt/emul/java/util/ConcurrentModificationException.java b/user/super/com/google/gwt/emul/java/util/ConcurrentModificationException.java
index 694c2ba..784be65 100644
--- a/user/super/com/google/gwt/emul/java/util/ConcurrentModificationException.java
+++ b/user/super/com/google/gwt/emul/java/util/ConcurrentModificationException.java
@@ -1,31 +1,31 @@
-/*
- * Copyright 2007 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 java.util;
-
-/**
- * See <a
- * href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ConcurrentModificationException.html">the
- * official Java API doc</a> for details.
- */
-public class ConcurrentModificationException extends RuntimeException {
-
- public ConcurrentModificationException() {
- }
-
- public ConcurrentModificationException(String message) {
- super(message);
- }
-}
+/*
+ * Copyright 2007 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 java.util;
+
+/**
+ * See <a
+ * href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ConcurrentModificationException.html">the
+ * official Java API doc</a> for details.
+ */
+public class ConcurrentModificationException extends RuntimeException {
+
+ public ConcurrentModificationException() {
+ }
+
+ public ConcurrentModificationException(String message) {
+ super(message);
+ }
+}
diff --git a/user/test/com/google/gwt/i18n/client/DateTimeFormat_de_Test.java b/user/test/com/google/gwt/i18n/client/DateTimeFormat_de_Test.java
index 1a6a83f..f0abd02 100644
--- a/user/test/com/google/gwt/i18n/client/DateTimeFormat_de_Test.java
+++ b/user/test/com/google/gwt/i18n/client/DateTimeFormat_de_Test.java
@@ -1,264 +1,264 @@
-/*
- * Copyright 2007 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.i18n.client;
-
-import com.google.gwt.junit.client.GWTTestCase;
-
-import java.util.Date;
-
-/**
- * Tests formatting functionality in {@link DateTimeFormat} for the German
- * language.
- */
-public class DateTimeFormat_de_Test extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.i18n.I18NTest_de";
- }
-
- public void test_EEEEMMMddyy() {
- Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- assertEquals("Donnerstag,Juli 27, 2006", format("EEEE,MMMM dd, yyyy", date));
- }
-
- public void test_EEEMMMddyy() {
- Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- assertEquals("Do, Jul 27, 06", format("EEE, MMM d, yy", date));
- }
-
- public void test_HHmmss() {
- Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- assertEquals("13:10:10", format("HH:mm:ss", date));
- }
-
- public void test_hhmmssa() {
- Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- assertEquals("1:10:10 nachm.", format("h:mm:ss a", date));
- }
-
- public void test_MMddyyyyHHmmssZ() {
- Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- String tz = getTimezoneString(date, false);
- String actual = format("MM/dd/yyyy HH:mm:ss Z", date);
- assertEquals("07/27/2006 13:10:10 " + tz, actual);
- }
-
- public void test_MMddyyyyHHmmsszzz() {
- Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- String tz = getTimezoneString(date);
- String actual = format("MM/dd/yyyy HH:mm:ss zzz", date);
- assertEquals("07/27/2006 13:10:10 GMT" + tz, actual);
- }
-
- public void test_predefinedFormat() {
- Date date = getUTCDate(2006 - 1900, 7, 4, 13, 49, 24);
- String tz = getTimezoneString(date);
-
- String fullDateFormat = DateTimeFormat.getFullDateFormat().format(date);
- assertEquals("Freitag, 4. August 2006", fullDateFormat);
-
- String longDateFormat = DateTimeFormat.getLongDateFormat().format(date);
- assertEquals("4. August 2006", longDateFormat);
-
- String medDateFormat = DateTimeFormat.getMediumDateFormat().format(date);
- assertEquals("04.08.2006", medDateFormat);
-
- String shortDateFormat = DateTimeFormat.getShortDateFormat().format(date);
- assertEquals("04.08.06", shortDateFormat);
-
- String fullTimeFormat = DateTimeFormat.getFullTimeFormat().format(date);
- assertEquals("13:49 Uhr GMT" + tz, fullTimeFormat);
-
- String longTimeFormat = DateTimeFormat.getLongTimeFormat().format(date);
- assertEquals("13:49:24 GMT" + tz, longTimeFormat);
-
- String medTimeFormat = DateTimeFormat.getMediumTimeFormat().format(date);
- assertEquals("13:49:24", medTimeFormat);
-
- String shortTimeFormat = DateTimeFormat.getShortTimeFormat().format(date);
- assertEquals("13:49", shortTimeFormat);
-
- String fullFormat = DateTimeFormat.getFullDateTimeFormat().format(date);
- assertEquals("Freitag, 4. August 2006 13:49 Uhr GMT" + tz, fullFormat);
-
- String longFormat = DateTimeFormat.getLongDateTimeFormat().format(date);
- assertEquals("4. August 2006 13:49:24 GMT" + tz, longFormat);
-
- String medFormat = DateTimeFormat.getMediumDateTimeFormat().format(date);
- assertEquals("04.08.2006 13:49:24", medFormat);
-
- String shortFormat = DateTimeFormat.getShortDateTimeFormat().format(date);
- assertEquals("04.08.06 13:49", shortFormat);
- }
-
- public void test_QQQQyy() {
- Date date;
-
- date = getUTCDate(2006 - 1900, 0, 27, 13, 10, 10);
- assertEquals("1. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 1, 27, 13, 10, 10);
- assertEquals("1. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 2, 27, 13, 10, 10);
- assertEquals("1. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 3, 27, 13, 10, 10);
- assertEquals("2. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 4, 27, 13, 10, 10);
- assertEquals("2. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 5, 27, 13, 10, 10);
- assertEquals("2. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- assertEquals("3. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 7, 27, 13, 10, 10);
- assertEquals("3. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 8, 27, 13, 10, 10);
- assertEquals("3. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 9, 27, 13, 10, 10);
- assertEquals("4. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 10, 27, 13, 10, 10);
- assertEquals("4. Quartal 06", format("QQQQ yy", date));
-
- date = getUTCDate(2006 - 1900, 11, 27, 13, 10, 10);
- assertEquals("4. Quartal 06", format("QQQQ yy", date));
- }
-
- public void test_QQyyyy() {
- Date date = new Date(2006 - 1900, 0, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q1 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 1, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q1 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 2, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q1 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 3, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q2 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 4, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q2 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 5, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q2 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 6, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q3 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 7, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q3 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 8, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q3 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 9, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q4 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 10, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q4 2006", format("QQ yyyy", date));
- date = new Date(2006 - 1900, 11, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("Q4 2006", format("QQ yyyy", date));
- }
-
- public void test_quote() {
- Date date = new Date(2006 - 1900, 6, 27);
- date.setHours(13);
- date.setMinutes(10);
- date.setSeconds(10);
- assertEquals("13 o'clock", format("HH 'o''clock'", date));
- assertEquals("13 oclock", format("HH 'oclock'", date));
- assertEquals("13 '", format("HH ''", date));
- }
-
- public void test_yyyyMMddG() {
- Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- String tz = getTimezoneString(date);
-
- String expected = "2006.07.27 n. Chr. at 13:10:10 GMT" + tz;
- String actual = format("yyyy.MM.dd G 'at' HH:mm:ss vvvv", date);
- assertEquals(expected, actual);
- }
-
- public void test_yyyyyMMMMM() {
- Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
- assertEquals("2006.J.27 n. Chr. 01:10 nachm.", format(
- "yyyyy.MMMMM.dd GGG hh:mm aaa", date));
- }
-
- private String format(String pattern, Date toFormat) {
- DateTimeFormat fmt = DateTimeFormat.getFormat(pattern);
- return fmt.format(toFormat);
- }
-
- private String getTimezoneString(Date date) {
- return getTimezoneString(date, true);
- }
-
- private String getTimezoneString(Date date, boolean useColon) {
- int tzOffset = date.getTimezoneOffset();
- int tzAbsOffset = Math.abs(tzOffset);
- int tzAbsOffsetHrs = tzAbsOffset / 60;
- int tzAbsOffsetMins = tzAbsOffset % 60;
- String tzOffsetStr = (tzOffset < 0 ? "+" : "-")
- + (tzAbsOffsetHrs < 10 ? "0" : "") + Integer.toString(tzAbsOffsetHrs)
- + (useColon ? ":" : "") + (tzAbsOffsetMins < 10 ? "0" : "")
- + Integer.toString(tzAbsOffsetMins);
- return tzOffsetStr;
- }
-
- private Date getUTCDate(int year, int month, int day, int hrs, int mins,
- int secs) {
- long localTzOffset = new Date().getTimezoneOffset();
- long utc = Date.UTC(year, month, day, hrs, mins, secs);
- long localTzOffsetMillis = localTzOffset * 60 * 1000;
- utc += localTzOffsetMillis;
- return new Date(utc);
- }
-}
+/*
+ * Copyright 2007 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.i18n.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+import java.util.Date;
+
+/**
+ * Tests formatting functionality in {@link DateTimeFormat} for the German
+ * language.
+ */
+public class DateTimeFormat_de_Test extends GWTTestCase {
+
+ public String getModuleName() {
+ return "com.google.gwt.i18n.I18NTest_de";
+ }
+
+ public void test_EEEEMMMddyy() {
+ Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ assertEquals("Donnerstag,Juli 27, 2006", format("EEEE,MMMM dd, yyyy", date));
+ }
+
+ public void test_EEEMMMddyy() {
+ Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ assertEquals("Do, Jul 27, 06", format("EEE, MMM d, yy", date));
+ }
+
+ public void test_HHmmss() {
+ Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ assertEquals("13:10:10", format("HH:mm:ss", date));
+ }
+
+ public void test_hhmmssa() {
+ Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ assertEquals("1:10:10 nachm.", format("h:mm:ss a", date));
+ }
+
+ public void test_MMddyyyyHHmmssZ() {
+ Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ String tz = getTimezoneString(date, false);
+ String actual = format("MM/dd/yyyy HH:mm:ss Z", date);
+ assertEquals("07/27/2006 13:10:10 " + tz, actual);
+ }
+
+ public void test_MMddyyyyHHmmsszzz() {
+ Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ String tz = getTimezoneString(date);
+ String actual = format("MM/dd/yyyy HH:mm:ss zzz", date);
+ assertEquals("07/27/2006 13:10:10 GMT" + tz, actual);
+ }
+
+ public void test_predefinedFormat() {
+ Date date = getUTCDate(2006 - 1900, 7, 4, 13, 49, 24);
+ String tz = getTimezoneString(date);
+
+ String fullDateFormat = DateTimeFormat.getFullDateFormat().format(date);
+ assertEquals("Freitag, 4. August 2006", fullDateFormat);
+
+ String longDateFormat = DateTimeFormat.getLongDateFormat().format(date);
+ assertEquals("4. August 2006", longDateFormat);
+
+ String medDateFormat = DateTimeFormat.getMediumDateFormat().format(date);
+ assertEquals("04.08.2006", medDateFormat);
+
+ String shortDateFormat = DateTimeFormat.getShortDateFormat().format(date);
+ assertEquals("04.08.06", shortDateFormat);
+
+ String fullTimeFormat = DateTimeFormat.getFullTimeFormat().format(date);
+ assertEquals("13:49 Uhr GMT" + tz, fullTimeFormat);
+
+ String longTimeFormat = DateTimeFormat.getLongTimeFormat().format(date);
+ assertEquals("13:49:24 GMT" + tz, longTimeFormat);
+
+ String medTimeFormat = DateTimeFormat.getMediumTimeFormat().format(date);
+ assertEquals("13:49:24", medTimeFormat);
+
+ String shortTimeFormat = DateTimeFormat.getShortTimeFormat().format(date);
+ assertEquals("13:49", shortTimeFormat);
+
+ String fullFormat = DateTimeFormat.getFullDateTimeFormat().format(date);
+ assertEquals("Freitag, 4. August 2006 13:49 Uhr GMT" + tz, fullFormat);
+
+ String longFormat = DateTimeFormat.getLongDateTimeFormat().format(date);
+ assertEquals("4. August 2006 13:49:24 GMT" + tz, longFormat);
+
+ String medFormat = DateTimeFormat.getMediumDateTimeFormat().format(date);
+ assertEquals("04.08.2006 13:49:24", medFormat);
+
+ String shortFormat = DateTimeFormat.getShortDateTimeFormat().format(date);
+ assertEquals("04.08.06 13:49", shortFormat);
+ }
+
+ public void test_QQQQyy() {
+ Date date;
+
+ date = getUTCDate(2006 - 1900, 0, 27, 13, 10, 10);
+ assertEquals("1. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 1, 27, 13, 10, 10);
+ assertEquals("1. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 2, 27, 13, 10, 10);
+ assertEquals("1. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 3, 27, 13, 10, 10);
+ assertEquals("2. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 4, 27, 13, 10, 10);
+ assertEquals("2. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 5, 27, 13, 10, 10);
+ assertEquals("2. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ assertEquals("3. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 7, 27, 13, 10, 10);
+ assertEquals("3. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 8, 27, 13, 10, 10);
+ assertEquals("3. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 9, 27, 13, 10, 10);
+ assertEquals("4. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 10, 27, 13, 10, 10);
+ assertEquals("4. Quartal 06", format("QQQQ yy", date));
+
+ date = getUTCDate(2006 - 1900, 11, 27, 13, 10, 10);
+ assertEquals("4. Quartal 06", format("QQQQ yy", date));
+ }
+
+ public void test_QQyyyy() {
+ Date date = new Date(2006 - 1900, 0, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q1 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 1, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q1 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 2, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q1 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 3, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q2 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 4, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q2 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 5, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q2 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 6, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q3 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 7, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q3 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 8, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q3 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 9, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q4 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 10, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q4 2006", format("QQ yyyy", date));
+ date = new Date(2006 - 1900, 11, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("Q4 2006", format("QQ yyyy", date));
+ }
+
+ public void test_quote() {
+ Date date = new Date(2006 - 1900, 6, 27);
+ date.setHours(13);
+ date.setMinutes(10);
+ date.setSeconds(10);
+ assertEquals("13 o'clock", format("HH 'o''clock'", date));
+ assertEquals("13 oclock", format("HH 'oclock'", date));
+ assertEquals("13 '", format("HH ''", date));
+ }
+
+ public void test_yyyyMMddG() {
+ Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ String tz = getTimezoneString(date);
+
+ String expected = "2006.07.27 n. Chr. at 13:10:10 GMT" + tz;
+ String actual = format("yyyy.MM.dd G 'at' HH:mm:ss vvvv", date);
+ assertEquals(expected, actual);
+ }
+
+ public void test_yyyyyMMMMM() {
+ Date date = getUTCDate(2006 - 1900, 6, 27, 13, 10, 10);
+ assertEquals("2006.J.27 n. Chr. 01:10 nachm.", format(
+ "yyyyy.MMMMM.dd GGG hh:mm aaa", date));
+ }
+
+ private String format(String pattern, Date toFormat) {
+ DateTimeFormat fmt = DateTimeFormat.getFormat(pattern);
+ return fmt.format(toFormat);
+ }
+
+ private String getTimezoneString(Date date) {
+ return getTimezoneString(date, true);
+ }
+
+ private String getTimezoneString(Date date, boolean useColon) {
+ int tzOffset = date.getTimezoneOffset();
+ int tzAbsOffset = Math.abs(tzOffset);
+ int tzAbsOffsetHrs = tzAbsOffset / 60;
+ int tzAbsOffsetMins = tzAbsOffset % 60;
+ String tzOffsetStr = (tzOffset < 0 ? "+" : "-")
+ + (tzAbsOffsetHrs < 10 ? "0" : "") + Integer.toString(tzAbsOffsetHrs)
+ + (useColon ? ":" : "") + (tzAbsOffsetMins < 10 ? "0" : "")
+ + Integer.toString(tzAbsOffsetMins);
+ return tzOffsetStr;
+ }
+
+ private Date getUTCDate(int year, int month, int day, int hrs, int mins,
+ int secs) {
+ long localTzOffset = new Date().getTimezoneOffset();
+ long utc = Date.UTC(year, month, day, hrs, mins, secs);
+ long localTzOffsetMillis = localTzOffset * 60 * 1000;
+ utc += localTzOffsetMillis;
+ return new Date(utc);
+ }
+}
diff --git a/user/test/com/google/gwt/i18n/client/DateTimeParse_en_Test.java b/user/test/com/google/gwt/i18n/client/DateTimeParse_en_Test.java
index 767c0a0..5d8ce47 100644
--- a/user/test/com/google/gwt/i18n/client/DateTimeParse_en_Test.java
+++ b/user/test/com/google/gwt/i18n/client/DateTimeParse_en_Test.java
@@ -1,543 +1,543 @@
-/*
- * Copyright 2007 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.i18n.client;
-
-import com.google.gwt.junit.client.GWTTestCase;
-
-import java.util.Date;
-
-/**
- * Tests parsing functionality in {@link DateTimeFormat} for the English
- * language.
- */
-public class DateTimeParse_en_Test extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.i18n.I18NTest_en";
- }
-
- private int parse(String pattern, String toParse, int startIndex, Date output) {
- DateTimeFormat fmt = DateTimeFormat.getFormat(pattern);
- return fmt.parse(toParse, startIndex, output);
- }
-
- private String format(String pattern, Date toFormat) {
- DateTimeFormat fmt = DateTimeFormat.getFormat(pattern);
- return fmt.format(toFormat);
- }
-
- public void testParseConsumesAllCharacters() {
- String toParse = "July 11, 1938";
- DateTimeFormat longDateFormat = DateTimeFormat.getLongDateFormat();
-
- try {
- Date actualDate = longDateFormat.parse(toParse);
- String actualFormat = longDateFormat.format(actualDate);
- assertEquals(toParse, actualFormat);
- } catch (IllegalArgumentException e) {
- fail("Should not have thrown an exception");
- }
-
- try {
- String toParseMangled = toParse + " asdfasdfasdf";
- longDateFormat.parse(toParseMangled);
- fail("Should have thrown an exception on failure to parse");
- } catch (IllegalArgumentException e) {
- // Success.
- }
- }
-
- public void testAbutField() {
- Date date = new Date();
-
- assertTrue(parse("hhmm", "1122", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmm", "122", 0, date) > 0);
- assertTrue(date.getHours() == 1);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmmss", "112233", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
- assertTrue(date.getSeconds() == 33);
-
- assertTrue(parse("hhmmss", "12233", 0, date) > 0);
- assertTrue(date.getHours() == 1);
- assertTrue(date.getMinutes() == 22);
- assertTrue(date.getSeconds() == 33);
-
- assertTrue(parse("yyyyMMdd", "19991202", 0, date) > 0);
- assertTrue(date.getYear() == (1999 - 1900));
- assertTrue(date.getMonth() == 12 - 1);
- assertTrue(date.getDate() == 02);
-
- assertTrue(parse("yyyyMMdd", "9991202", 0, date) > 0);
- assertTrue(date.getYear() == (999 - 1900));
- assertTrue(date.getMonth() == 12 - 1);
- assertTrue(date.getDate() == 02);
-
- assertTrue(parse("yyyyMMdd", "991202", 0, date) > 0);
- assertTrue(date.getYear() == (99 - 1900));
- assertTrue(date.getMonth() == 12 - 1);
- assertTrue(date.getDate() == 02);
-
- assertTrue(parse("yyyyMMdd", "91202", 0, date) > 0);
- assertTrue(date.getYear() == (9 - 1900));
- assertTrue(date.getMonth() == 12 - 1);
- assertTrue(date.getDate() == 02);
- }
-
- public void testAmbiguousYear() {
- Date date = new Date();
- if (date.getMonth() == 0 && date.getDate() == 1 || date.getMonth() == 11
- && date.getDate() >= 31) {
- // we are using current time to resolve ambiguous year.
- // This test case is not designed to work on new year's eve and new year.
- return;
- }
-
- Date orgDate = new Date();
- orgDate.setYear(orgDate.getYear() + 20);
-
- orgDate.setMonth(0);
- orgDate.setDate(1);
- String str = format("MM/dd/yy", orgDate);
- assertTrue(parse("MM/dd/yy", str, 0, date) > 0);
- assertTrue(date.getYear() == orgDate.getYear());
-
- orgDate.setMonth(11);
- orgDate.setDate(31);
- str = format("MM/dd/yy", orgDate);
- assertTrue(parse("MM/dd/yy", str, 0, date) > 0);
- assertTrue(date.getYear() + 100 == orgDate.getYear());
-
- assertTrue(parse("yy,MM,dd", "2097,07,21", 0, date) > 0);
- assertTrue(date.getYear() == 2097 - 1900);
- }
-
- public void testEnglishDate() {
- Date date = new Date();
-
- assertTrue(parse("yyyy MMM dd hh:mm", "2006 Jul 10 15:44", 0, date) > 0);
- assertTrue(date.getYear() == 2006 - 1900);
- assertTrue(date.getMonth() == 7 - 1);
- assertTrue(date.getDate() == 10);
- assertTrue(date.getHours() == 15);
- assertTrue(date.getMinutes() == 44);
- }
-
- /**
- * Add as many tests as you like.
- */
- public void testFractionalSeconds() {
- Date date = new Date();
-
- assertTrue(parse("hh:mm:ss.SSS", "11:12:13.956", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 12);
- assertTrue(date.getSeconds() == 13);
- assertTrue((date.getTime() % 1000) == 956);
-
- assertTrue(parse("hh:mm:ss.SSS", "11:12:13.95", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 12);
- assertTrue(date.getSeconds() == 13);
- assertTrue((date.getTime() % 1000) == 950);
-
- assertTrue(parse("hh:mm:ss.SSS", "11:12:13.9", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 12);
- assertTrue(date.getSeconds() == 13);
- assertTrue((date.getTime() % 1000) == 900);
- }
-
- public void testHourParsingFHH() {
- Date date = new Date();
- assertTrue(parse("HHmm", "0022", 0, date) > 0);
- assertTrue(date.getHours() == 00);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmm", "1122", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmm", "1222", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmm", "2322", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmm", "2422", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "0022am", 0, date) > 0);
- assertTrue(date.getHours() == 00);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "1122am", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "1222am", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "2322am", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "2422am", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "0022pm", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "1122pm", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "1222pm", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "2322pm", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("HHmma", "2422pm", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
- }
-
- public void testHourParsingFhh() {
- Date date = new Date();
-
- assertTrue(parse("hhmm", "0022", 0, date) > 0);
- assertTrue(date.getHours() == 00);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmm", "1122", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmm", "1222", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmm", "2322", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmm", "2422", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "0022am", 0, date) > 0);
- assertTrue(date.getHours() == 00);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "1122am", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "1222am", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "2322am", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "2422am", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "0022pm", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "1122pm", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "1222pm", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "2322pm", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("hhmma", "2422pm", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
- }
-
- public void testHourParsingFKK() {
- Date date = new Date();
- assertTrue(parse("KKmm", "0022", 0, date) > 0);
- assertTrue(date.getHours() == 00);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmm", "1122", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmm", "1222", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmm", "2322", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmm", "2422", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "0022am", 0, date) > 0);
- assertTrue(date.getHours() == 00);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "1122am", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "1222am", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "2322am", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "2422am", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "0022pm", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "1122pm", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "1222pm", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "2322pm", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("KKmma", "2422pm", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
- }
-
- public void testHourParsingFkk() {
- Date date = new Date();
- assertTrue(parse("kkmm", "0022", 0, date) > 0);
- assertTrue(date.getHours() == 00);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmm", "1122", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmm", "1222", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmm", "2322", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmm", "2422", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "0022am", 0, date) > 0);
- assertTrue(date.getHours() == 00);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "1122am", 0, date) > 0);
- assertTrue(date.getHours() == 11);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "1222am", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "2322am", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "2422am", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "0022pm", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "1122pm", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "1222pm", 0, date) > 0);
- assertTrue(date.getHours() == 12);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "2322pm", 0, date) > 0);
- assertTrue(date.getHours() == 23);
- assertTrue(date.getMinutes() == 22);
-
- assertTrue(parse("kkmma", "2422pm", 0, date) > 0);
- assertTrue(date.getHours() == 0);
- assertTrue(date.getMinutes() == 22);
- }
-
- public void testLeapYear() {
- Date date = new Date();
-
- assertTrue(parse("MMdd, yyyy", "0229, 2001", 0, date) > 0);
- assertTrue(date.getMonth() == 3 - 1);
- assertTrue(date.getDate() == 1);
-
- assertTrue(parse("MMdd, yyyy", "0229, 2000", 0, date) > 0);
- assertTrue(date.getMonth() == 2 - 1);
- assertTrue(date.getDate() == 29);
- }
-
- public void testRFC3339() {
- Date date = new Date();
-
- {
- // Parse a string formatted according to RFC3389.
- String rfc3339str = "1985-04-12T23:20:50.52-08:00";
- assertTrue(parse("yyyy-MM-dd'T'HH:mm:ss.SSZ", rfc3339str, 0, date) > 0);
-
- // Create the expected time as UTC. The "+8" is due to the tz offset.
- long expectedTimeUTC = Date.UTC(1985 - 1900, 3, 12, 23 + 8, 20, 50);
- Date expectedDate = new Date(expectedTimeUTC);
- assertEquals(expectedDate.getYear(), date.getYear());
- assertEquals(expectedDate.getMonth(), date.getMonth());
- assertEquals(expectedDate.getDate(), date.getDate());
- assertEquals(expectedDate.getHours(), date.getHours());
- assertEquals(expectedDate.getMinutes(), date.getMinutes());
- assertEquals(expectedDate.getSeconds(), date.getSeconds());
- // Make sure our parse captured the extra 520 milliseconds.
- assertEquals(520, date.getTime() % 1000);
- }
-
- {
- // Parse a string formatted according to RFC3389.
- String rfc3339str = "1985-04-12T23:20:50.52Z";
- if (rfc3339str.endsWith("Z")) {
- StringBuffer strbuf = new StringBuffer(rfc3339str);
- strbuf.deleteCharAt(rfc3339str.length() - 1);
- strbuf.append("+00:00");
- rfc3339str = strbuf.toString();
- }
- assertTrue(parse("yyyy-MM-dd'T'HH:mm:ss.SSZ", rfc3339str, 0, date) > 0);
-
- // Create the expected time as UTC. The "+0" is because it's already GMT.
- long expectedTimeUTC = Date.UTC(85, 3, 12, 23 + 0, 20, 50);
- Date expectedDate = new Date(expectedTimeUTC);
- assertEquals(expectedDate.getYear(), date.getYear());
- assertEquals(expectedDate.getMonth(), date.getMonth());
- assertEquals(expectedDate.getDate(), date.getDate());
- assertEquals(expectedDate.getHours(), date.getHours());
- assertEquals(expectedDate.getMinutes(), date.getMinutes());
- assertEquals(expectedDate.getSeconds(), date.getSeconds());
- // Make sure our parse captured the extra 520 milliseconds.
- assertEquals(520, date.getTime() % 1000);
- }
- }
-
- public void testTimeZone() {
- Date date = new Date();
-
- assertTrue(parse("MM/dd/yyyy, hh:mm:ss zzz",
- "07/21/2003, 11:22:33 GMT-0700", 0, date) > 0);
- int gmtNegative07 = date.getHours();
-
- assertTrue(parse("MM/dd/yyyy, hh:mm:ss zzz",
- "07/21/2003, 11:22:33 GMT-0600", 0, date) > 0);
- int gmtNegative06 = date.getHours();
- assertTrue((gmtNegative07 + 24 - gmtNegative06) % 24 == 1);
-
- assertTrue(parse("MM/dd/yyyy, hh:mm:ss zzz",
- "07/21/2003, 11:22:33 GMT-0800", 0, date) > 0);
- int gmtNegative08 = date.getHours();
- assertTrue((gmtNegative08 + 24 - gmtNegative07) % 24 == 1);
-
- assertTrue(parse("MM/dd/yyyy, HH:mm:ss zzz",
- "07/21/2003, 11:22:33 GMT+0800", 0, date) > 0);
- int gmtPositive08 = date.getHours();
- assertTrue((gmtNegative08 + 24 - gmtPositive08) % 24 == 16);
- }
-
- public void testWeekDay() {
- Date date = new Date();
-
- assertTrue(parse("EEEE, MM/dd/yyyy", "Wednesday, 08/16/2006", 0, date) > 0);
- assertTrue(date.getYear() == 2006 - 1900);
- assertTrue(date.getMonth() == 8 - 1);
- assertTrue(date.getDate() == 16);
- assertTrue(parse("EEEE, MM/dd/yyyy", "Tuesday, 08/16/2006", 0, date) == 0);
- assertTrue(parse("EEEE, MM/dd/yyyy", "Thursday, 08/16/2006", 0, date) == 0);
- assertTrue(parse("EEEE, MM/dd/yyyy", "Wed, 08/16/2006", 0, date) > 0);
- assertTrue(parse("EEEE, MM/dd/yyyy", "Wasdfed, 08/16/2006", 0, date) == 0);
-
- date.setDate(25);
- assertTrue(parse("EEEE, MM/yyyy", "Wed, 09/2006", 0, date) > 0);
- assertTrue(date.getDate() == 27);
-
- date.setDate(30);
- assertTrue(parse("EEEE, MM/yyyy", "Wed, 09/2006", 0, date) > 0);
- assertTrue(date.getDate() == 27);
-
- date.setDate(30);
- assertTrue(parse("EEEE, MM/yyyy", "Mon, 09/2006", 0, date) > 0);
- assertTrue(date.getDate() == 25);
- }
-
- public void testYearParsing() {
- Date date = new Date();
-
- assertTrue(parse("yyMMdd", "991202", 0, date) > 0);
- assertTrue(date.getYear() == (1999 - 1900));
- assertTrue(date.getMonth() == 12 - 1);
- assertTrue(date.getDate() == 02);
-
- assertTrue(parse("yyyyMMdd", "20051202", 0, date) > 0);
- assertTrue(date.getYear() == (2005 - 1900));
- assertTrue(date.getMonth() == 12 - 1);
- assertTrue(date.getDate() == 02);
- }
-
-}
+/*
+ * Copyright 2007 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.i18n.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+import java.util.Date;
+
+/**
+ * Tests parsing functionality in {@link DateTimeFormat} for the English
+ * language.
+ */
+public class DateTimeParse_en_Test extends GWTTestCase {
+
+ public String getModuleName() {
+ return "com.google.gwt.i18n.I18NTest_en";
+ }
+
+ private int parse(String pattern, String toParse, int startIndex, Date output) {
+ DateTimeFormat fmt = DateTimeFormat.getFormat(pattern);
+ return fmt.parse(toParse, startIndex, output);
+ }
+
+ private String format(String pattern, Date toFormat) {
+ DateTimeFormat fmt = DateTimeFormat.getFormat(pattern);
+ return fmt.format(toFormat);
+ }
+
+ public void testParseConsumesAllCharacters() {
+ String toParse = "July 11, 1938";
+ DateTimeFormat longDateFormat = DateTimeFormat.getLongDateFormat();
+
+ try {
+ Date actualDate = longDateFormat.parse(toParse);
+ String actualFormat = longDateFormat.format(actualDate);
+ assertEquals(toParse, actualFormat);
+ } catch (IllegalArgumentException e) {
+ fail("Should not have thrown an exception");
+ }
+
+ try {
+ String toParseMangled = toParse + " asdfasdfasdf";
+ longDateFormat.parse(toParseMangled);
+ fail("Should have thrown an exception on failure to parse");
+ } catch (IllegalArgumentException e) {
+ // Success.
+ }
+ }
+
+ public void testAbutField() {
+ Date date = new Date();
+
+ assertTrue(parse("hhmm", "1122", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmm", "122", 0, date) > 0);
+ assertTrue(date.getHours() == 1);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmmss", "112233", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+ assertTrue(date.getSeconds() == 33);
+
+ assertTrue(parse("hhmmss", "12233", 0, date) > 0);
+ assertTrue(date.getHours() == 1);
+ assertTrue(date.getMinutes() == 22);
+ assertTrue(date.getSeconds() == 33);
+
+ assertTrue(parse("yyyyMMdd", "19991202", 0, date) > 0);
+ assertTrue(date.getYear() == (1999 - 1900));
+ assertTrue(date.getMonth() == 12 - 1);
+ assertTrue(date.getDate() == 02);
+
+ assertTrue(parse("yyyyMMdd", "9991202", 0, date) > 0);
+ assertTrue(date.getYear() == (999 - 1900));
+ assertTrue(date.getMonth() == 12 - 1);
+ assertTrue(date.getDate() == 02);
+
+ assertTrue(parse("yyyyMMdd", "991202", 0, date) > 0);
+ assertTrue(date.getYear() == (99 - 1900));
+ assertTrue(date.getMonth() == 12 - 1);
+ assertTrue(date.getDate() == 02);
+
+ assertTrue(parse("yyyyMMdd", "91202", 0, date) > 0);
+ assertTrue(date.getYear() == (9 - 1900));
+ assertTrue(date.getMonth() == 12 - 1);
+ assertTrue(date.getDate() == 02);
+ }
+
+ public void testAmbiguousYear() {
+ Date date = new Date();
+ if (date.getMonth() == 0 && date.getDate() == 1 || date.getMonth() == 11
+ && date.getDate() >= 31) {
+ // we are using current time to resolve ambiguous year.
+ // This test case is not designed to work on new year's eve and new year.
+ return;
+ }
+
+ Date orgDate = new Date();
+ orgDate.setYear(orgDate.getYear() + 20);
+
+ orgDate.setMonth(0);
+ orgDate.setDate(1);
+ String str = format("MM/dd/yy", orgDate);
+ assertTrue(parse("MM/dd/yy", str, 0, date) > 0);
+ assertTrue(date.getYear() == orgDate.getYear());
+
+ orgDate.setMonth(11);
+ orgDate.setDate(31);
+ str = format("MM/dd/yy", orgDate);
+ assertTrue(parse("MM/dd/yy", str, 0, date) > 0);
+ assertTrue(date.getYear() + 100 == orgDate.getYear());
+
+ assertTrue(parse("yy,MM,dd", "2097,07,21", 0, date) > 0);
+ assertTrue(date.getYear() == 2097 - 1900);
+ }
+
+ public void testEnglishDate() {
+ Date date = new Date();
+
+ assertTrue(parse("yyyy MMM dd hh:mm", "2006 Jul 10 15:44", 0, date) > 0);
+ assertTrue(date.getYear() == 2006 - 1900);
+ assertTrue(date.getMonth() == 7 - 1);
+ assertTrue(date.getDate() == 10);
+ assertTrue(date.getHours() == 15);
+ assertTrue(date.getMinutes() == 44);
+ }
+
+ /**
+ * Add as many tests as you like.
+ */
+ public void testFractionalSeconds() {
+ Date date = new Date();
+
+ assertTrue(parse("hh:mm:ss.SSS", "11:12:13.956", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 12);
+ assertTrue(date.getSeconds() == 13);
+ assertTrue((date.getTime() % 1000) == 956);
+
+ assertTrue(parse("hh:mm:ss.SSS", "11:12:13.95", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 12);
+ assertTrue(date.getSeconds() == 13);
+ assertTrue((date.getTime() % 1000) == 950);
+
+ assertTrue(parse("hh:mm:ss.SSS", "11:12:13.9", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 12);
+ assertTrue(date.getSeconds() == 13);
+ assertTrue((date.getTime() % 1000) == 900);
+ }
+
+ public void testHourParsingFHH() {
+ Date date = new Date();
+ assertTrue(parse("HHmm", "0022", 0, date) > 0);
+ assertTrue(date.getHours() == 00);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmm", "1122", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmm", "1222", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmm", "2322", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmm", "2422", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "0022am", 0, date) > 0);
+ assertTrue(date.getHours() == 00);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "1122am", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "1222am", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "2322am", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "2422am", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "0022pm", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "1122pm", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "1222pm", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "2322pm", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("HHmma", "2422pm", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+ }
+
+ public void testHourParsingFhh() {
+ Date date = new Date();
+
+ assertTrue(parse("hhmm", "0022", 0, date) > 0);
+ assertTrue(date.getHours() == 00);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmm", "1122", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmm", "1222", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmm", "2322", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmm", "2422", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "0022am", 0, date) > 0);
+ assertTrue(date.getHours() == 00);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "1122am", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "1222am", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "2322am", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "2422am", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "0022pm", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "1122pm", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "1222pm", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "2322pm", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("hhmma", "2422pm", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+ }
+
+ public void testHourParsingFKK() {
+ Date date = new Date();
+ assertTrue(parse("KKmm", "0022", 0, date) > 0);
+ assertTrue(date.getHours() == 00);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmm", "1122", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmm", "1222", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmm", "2322", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmm", "2422", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "0022am", 0, date) > 0);
+ assertTrue(date.getHours() == 00);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "1122am", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "1222am", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "2322am", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "2422am", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "0022pm", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "1122pm", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "1222pm", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "2322pm", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("KKmma", "2422pm", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+ }
+
+ public void testHourParsingFkk() {
+ Date date = new Date();
+ assertTrue(parse("kkmm", "0022", 0, date) > 0);
+ assertTrue(date.getHours() == 00);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmm", "1122", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmm", "1222", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmm", "2322", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmm", "2422", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "0022am", 0, date) > 0);
+ assertTrue(date.getHours() == 00);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "1122am", 0, date) > 0);
+ assertTrue(date.getHours() == 11);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "1222am", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "2322am", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "2422am", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "0022pm", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "1122pm", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "1222pm", 0, date) > 0);
+ assertTrue(date.getHours() == 12);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "2322pm", 0, date) > 0);
+ assertTrue(date.getHours() == 23);
+ assertTrue(date.getMinutes() == 22);
+
+ assertTrue(parse("kkmma", "2422pm", 0, date) > 0);
+ assertTrue(date.getHours() == 0);
+ assertTrue(date.getMinutes() == 22);
+ }
+
+ public void testLeapYear() {
+ Date date = new Date();
+
+ assertTrue(parse("MMdd, yyyy", "0229, 2001", 0, date) > 0);
+ assertTrue(date.getMonth() == 3 - 1);
+ assertTrue(date.getDate() == 1);
+
+ assertTrue(parse("MMdd, yyyy", "0229, 2000", 0, date) > 0);
+ assertTrue(date.getMonth() == 2 - 1);
+ assertTrue(date.getDate() == 29);
+ }
+
+ public void testRFC3339() {
+ Date date = new Date();
+
+ {
+ // Parse a string formatted according to RFC3389.
+ String rfc3339str = "1985-04-12T23:20:50.52-08:00";
+ assertTrue(parse("yyyy-MM-dd'T'HH:mm:ss.SSZ", rfc3339str, 0, date) > 0);
+
+ // Create the expected time as UTC. The "+8" is due to the tz offset.
+ long expectedTimeUTC = Date.UTC(1985 - 1900, 3, 12, 23 + 8, 20, 50);
+ Date expectedDate = new Date(expectedTimeUTC);
+ assertEquals(expectedDate.getYear(), date.getYear());
+ assertEquals(expectedDate.getMonth(), date.getMonth());
+ assertEquals(expectedDate.getDate(), date.getDate());
+ assertEquals(expectedDate.getHours(), date.getHours());
+ assertEquals(expectedDate.getMinutes(), date.getMinutes());
+ assertEquals(expectedDate.getSeconds(), date.getSeconds());
+ // Make sure our parse captured the extra 520 milliseconds.
+ assertEquals(520, date.getTime() % 1000);
+ }
+
+ {
+ // Parse a string formatted according to RFC3389.
+ String rfc3339str = "1985-04-12T23:20:50.52Z";
+ if (rfc3339str.endsWith("Z")) {
+ StringBuffer strbuf = new StringBuffer(rfc3339str);
+ strbuf.deleteCharAt(rfc3339str.length() - 1);
+ strbuf.append("+00:00");
+ rfc3339str = strbuf.toString();
+ }
+ assertTrue(parse("yyyy-MM-dd'T'HH:mm:ss.SSZ", rfc3339str, 0, date) > 0);
+
+ // Create the expected time as UTC. The "+0" is because it's already GMT.
+ long expectedTimeUTC = Date.UTC(85, 3, 12, 23 + 0, 20, 50);
+ Date expectedDate = new Date(expectedTimeUTC);
+ assertEquals(expectedDate.getYear(), date.getYear());
+ assertEquals(expectedDate.getMonth(), date.getMonth());
+ assertEquals(expectedDate.getDate(), date.getDate());
+ assertEquals(expectedDate.getHours(), date.getHours());
+ assertEquals(expectedDate.getMinutes(), date.getMinutes());
+ assertEquals(expectedDate.getSeconds(), date.getSeconds());
+ // Make sure our parse captured the extra 520 milliseconds.
+ assertEquals(520, date.getTime() % 1000);
+ }
+ }
+
+ public void testTimeZone() {
+ Date date = new Date();
+
+ assertTrue(parse("MM/dd/yyyy, hh:mm:ss zzz",
+ "07/21/2003, 11:22:33 GMT-0700", 0, date) > 0);
+ int gmtNegative07 = date.getHours();
+
+ assertTrue(parse("MM/dd/yyyy, hh:mm:ss zzz",
+ "07/21/2003, 11:22:33 GMT-0600", 0, date) > 0);
+ int gmtNegative06 = date.getHours();
+ assertTrue((gmtNegative07 + 24 - gmtNegative06) % 24 == 1);
+
+ assertTrue(parse("MM/dd/yyyy, hh:mm:ss zzz",
+ "07/21/2003, 11:22:33 GMT-0800", 0, date) > 0);
+ int gmtNegative08 = date.getHours();
+ assertTrue((gmtNegative08 + 24 - gmtNegative07) % 24 == 1);
+
+ assertTrue(parse("MM/dd/yyyy, HH:mm:ss zzz",
+ "07/21/2003, 11:22:33 GMT+0800", 0, date) > 0);
+ int gmtPositive08 = date.getHours();
+ assertTrue((gmtNegative08 + 24 - gmtPositive08) % 24 == 16);
+ }
+
+ public void testWeekDay() {
+ Date date = new Date();
+
+ assertTrue(parse("EEEE, MM/dd/yyyy", "Wednesday, 08/16/2006", 0, date) > 0);
+ assertTrue(date.getYear() == 2006 - 1900);
+ assertTrue(date.getMonth() == 8 - 1);
+ assertTrue(date.getDate() == 16);
+ assertTrue(parse("EEEE, MM/dd/yyyy", "Tuesday, 08/16/2006", 0, date) == 0);
+ assertTrue(parse("EEEE, MM/dd/yyyy", "Thursday, 08/16/2006", 0, date) == 0);
+ assertTrue(parse("EEEE, MM/dd/yyyy", "Wed, 08/16/2006", 0, date) > 0);
+ assertTrue(parse("EEEE, MM/dd/yyyy", "Wasdfed, 08/16/2006", 0, date) == 0);
+
+ date.setDate(25);
+ assertTrue(parse("EEEE, MM/yyyy", "Wed, 09/2006", 0, date) > 0);
+ assertTrue(date.getDate() == 27);
+
+ date.setDate(30);
+ assertTrue(parse("EEEE, MM/yyyy", "Wed, 09/2006", 0, date) > 0);
+ assertTrue(date.getDate() == 27);
+
+ date.setDate(30);
+ assertTrue(parse("EEEE, MM/yyyy", "Mon, 09/2006", 0, date) > 0);
+ assertTrue(date.getDate() == 25);
+ }
+
+ public void testYearParsing() {
+ Date date = new Date();
+
+ assertTrue(parse("yyMMdd", "991202", 0, date) > 0);
+ assertTrue(date.getYear() == (1999 - 1900));
+ assertTrue(date.getMonth() == 12 - 1);
+ assertTrue(date.getDate() == 02);
+
+ assertTrue(parse("yyyyMMdd", "20051202", 0, date) > 0);
+ assertTrue(date.getYear() == (2005 - 1900));
+ assertTrue(date.getMonth() == 12 - 1);
+ assertTrue(date.getDate() == 02);
+ }
+
+}
diff --git a/user/test/com/google/gwt/i18n/client/DateTimeParse_zh_CN_Test.java b/user/test/com/google/gwt/i18n/client/DateTimeParse_zh_CN_Test.java
index 523730c..da44ab7 100644
--- a/user/test/com/google/gwt/i18n/client/DateTimeParse_zh_CN_Test.java
+++ b/user/test/com/google/gwt/i18n/client/DateTimeParse_zh_CN_Test.java
@@ -1,95 +1,95 @@
-/*
- * Copyright 2006 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.i18n.client;
-
-import com.google.gwt.junit.client.GWTTestCase;
-
-import java.util.Date;
-
-/**
- * Tests formatting functionality in {@link DateTimeFormat} for the Chinese
- * language.
- */
-public class DateTimeParse_zh_CN_Test extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.i18n.I18NTest_zh_CN";
- }
-
- public void testChineseDateParse() {
- Date date = new Date();
-
- {
- String time_15_26_28 = "\u4e0b\u534803\u65f626\u520628\u79d2 GMT-07:00";
- DateTimeFormat.getFullTimeFormat().parse(time_15_26_28, 0, date);
-
- /*
- * Create the expected time as UTC. The "+7" is due to the tz offset.
- * NOTE: we use the same date explicitly because Java and JavaScript
- * disagree about whether or not daylight savings time is in effect on day
- * 0 of the epoch.
- */
- long expectedTimeUTC = Date.UTC(date.getYear(), date.getMonth(),
- date.getDate(), 15 + 7, 26, 28);
- Date expectedDate = new Date(expectedTimeUTC);
- assertEquals(expectedDate.getHours(), date.getHours());
- assertEquals(expectedDate.getMinutes(), date.getMinutes());
- assertEquals(expectedDate.getSeconds(), date.getSeconds());
- }
-
- {
- String date_2006_07_24 = "2006\u5E747\u670824\u65e5\u661f\u671f\u4e00";
- assertTrue(DateTimeFormat.getFullDateFormat().parse(date_2006_07_24, 0,
- date) > 0);
-
- // Create the expected date object, adjusting for the local timezone.
- long localTzOffset = new Date().getTimezoneOffset();
- long expectedTimeUTC = Date.UTC(2006 - 1900, 7 - 1, 24, 0, 0, 0);
- long localTzOffsetMillis = localTzOffset * 60 * 1000;
- expectedTimeUTC += localTzOffsetMillis;
- Date expectedDate = new Date(expectedTimeUTC);
-
- // Compare the actual and expected results.
- addCheckpoint("2a");
- assertEquals(expectedDate.getYear(), date.getYear());
- addCheckpoint("2b");
- assertEquals(expectedDate.getMonth(), date.getMonth());
- addCheckpoint("2c");
- assertEquals(expectedDate.getDate(), date.getDate());
- }
-
- {
- String date_2006_07_24 = "2006\u5E747\u670824\u65e5";
- DateTimeFormat.getLongDateFormat().parse(date_2006_07_24, 0, date);
-
- // Create the expected date object, adjusting for the local timezone.
- long localTzOffset = new Date().getTimezoneOffset();
- long expectedTimeUTC = Date.UTC(2006 - 1900, 7 - 1, 24, 0, 0, 0);
- long localTzOffsetMillis = localTzOffset * 60 * 1000;
- expectedTimeUTC += localTzOffsetMillis;
- Date expectedDate = new Date(expectedTimeUTC);
-
- // Compare the actual and expected results.
- addCheckpoint("3a");
- assertEquals(expectedDate.getYear(), date.getYear());
- addCheckpoint("3b");
- assertEquals(expectedDate.getMonth(), date.getMonth());
- addCheckpoint("3c");
- assertEquals(expectedDate.getDate(), date.getDate());
- }
- }
-}
+/*
+ * Copyright 2006 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.i18n.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+import java.util.Date;
+
+/**
+ * Tests formatting functionality in {@link DateTimeFormat} for the Chinese
+ * language.
+ */
+public class DateTimeParse_zh_CN_Test extends GWTTestCase {
+
+ public String getModuleName() {
+ return "com.google.gwt.i18n.I18NTest_zh_CN";
+ }
+
+ public void testChineseDateParse() {
+ Date date = new Date();
+
+ {
+ String time_15_26_28 = "\u4e0b\u534803\u65f626\u520628\u79d2 GMT-07:00";
+ DateTimeFormat.getFullTimeFormat().parse(time_15_26_28, 0, date);
+
+ /*
+ * Create the expected time as UTC. The "+7" is due to the tz offset.
+ * NOTE: we use the same date explicitly because Java and JavaScript
+ * disagree about whether or not daylight savings time is in effect on day
+ * 0 of the epoch.
+ */
+ long expectedTimeUTC = Date.UTC(date.getYear(), date.getMonth(),
+ date.getDate(), 15 + 7, 26, 28);
+ Date expectedDate = new Date(expectedTimeUTC);
+ assertEquals(expectedDate.getHours(), date.getHours());
+ assertEquals(expectedDate.getMinutes(), date.getMinutes());
+ assertEquals(expectedDate.getSeconds(), date.getSeconds());
+ }
+
+ {
+ String date_2006_07_24 = "2006\u5E747\u670824\u65e5\u661f\u671f\u4e00";
+ assertTrue(DateTimeFormat.getFullDateFormat().parse(date_2006_07_24, 0,
+ date) > 0);
+
+ // Create the expected date object, adjusting for the local timezone.
+ long localTzOffset = new Date().getTimezoneOffset();
+ long expectedTimeUTC = Date.UTC(2006 - 1900, 7 - 1, 24, 0, 0, 0);
+ long localTzOffsetMillis = localTzOffset * 60 * 1000;
+ expectedTimeUTC += localTzOffsetMillis;
+ Date expectedDate = new Date(expectedTimeUTC);
+
+ // Compare the actual and expected results.
+ addCheckpoint("2a");
+ assertEquals(expectedDate.getYear(), date.getYear());
+ addCheckpoint("2b");
+ assertEquals(expectedDate.getMonth(), date.getMonth());
+ addCheckpoint("2c");
+ assertEquals(expectedDate.getDate(), date.getDate());
+ }
+
+ {
+ String date_2006_07_24 = "2006\u5E747\u670824\u65e5";
+ DateTimeFormat.getLongDateFormat().parse(date_2006_07_24, 0, date);
+
+ // Create the expected date object, adjusting for the local timezone.
+ long localTzOffset = new Date().getTimezoneOffset();
+ long expectedTimeUTC = Date.UTC(2006 - 1900, 7 - 1, 24, 0, 0, 0);
+ long localTzOffsetMillis = localTzOffset * 60 * 1000;
+ expectedTimeUTC += localTzOffsetMillis;
+ Date expectedDate = new Date(expectedTimeUTC);
+
+ // Compare the actual and expected results.
+ addCheckpoint("3a");
+ assertEquals(expectedDate.getYear(), date.getYear());
+ addCheckpoint("3b");
+ assertEquals(expectedDate.getMonth(), date.getMonth());
+ addCheckpoint("3c");
+ assertEquals(expectedDate.getDate(), date.getDate());
+ }
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/ui/CustomButtonTest.java b/user/test/com/google/gwt/user/client/ui/CustomButtonTest.java
index 4133fa7..3b155dd 100644
--- a/user/test/com/google/gwt/user/client/ui/CustomButtonTest.java
+++ b/user/test/com/google/gwt/user/client/ui/CustomButtonTest.java
@@ -1,157 +1,157 @@
-/*
- * Copyright 2007 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.client.DOM;
-import com.google.gwt.user.client.ui.CustomButton.Face;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Test for <code>PushButton</code> as most of this widget's functionality is
- * UI based, the primary test will be in the new UI testing framework once it is
- * released.
- *
- */
-public class CustomButtonTest extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.user.User";
- }
-
- public void testCSS() {
- ToggleButton b = new ToggleButton("up", "down");
- b.setStyleName("random");
- b.setDown(true);
- assertEquals(b.getStyleName(), "random");
-
- Map faces = new HashMap();
- faces.put("downDisabled", b.getDownDisabledFace());
- faces.put("upDisabled", b.getUpDisabledFace());
- faces.put("down", b.getDownFace());
- faces.put("up", b.getUpFace());
- faces.put("upHovering", b.getUpHoveringFace());
- faces.put("downHovering", b.getDownHoveringFace());
- Iterator entries = faces.entrySet().iterator();
- // Set all faces as text.
- while (entries.hasNext()) {
- Map.Entry entry = (Entry) entries.next();
- Face f = (Face) entry.getValue();
- b.setCurrentFace(f);
- assertEquals("random-" + f.getName(), DOM.getElementProperty(
- b.getElement(), "className").trim());
- }
-
- entries = faces.entrySet().iterator();
- b.addStyleName("fobar");
- // Set all faces as text.
- while (entries.hasNext()) {
- Map.Entry entry = (Entry) entries.next();
- Face f = (Face) entry.getValue();
- b.setCurrentFace(f);
- String computedStyleName = DOM.getElementProperty(b.getElement(),
- "className");
- assertTrue(computedStyleName.indexOf("random-" + f.getName()) >= 0);
- assertTrue(computedStyleName.indexOf("fobar") >= 0);
- }
- }
-
- public void testSettingFaces() {
- PushButton b = new PushButton();
- Map faces = new HashMap();
- faces.put("downDisabled", b.getDownDisabledFace());
- faces.put("upDisabled", b.getUpDisabledFace());
- faces.put("down", b.getDownFace());
- faces.put("up", b.getUpFace());
- faces.put("upHovering", b.getUpHoveringFace());
- faces.put("downHovering", b.getDownHoveringFace());
- Iterator entries = faces.entrySet().iterator();
-
- // Set all faces as text.
- while (entries.hasNext()) {
- Map.Entry entry = (Entry) entries.next();
- Face f = (Face) entry.getValue();
- String faceName = (String) entry.getKey();
- f.setText(faceName);
- }
- entries = faces.entrySet().iterator();
- while (entries.hasNext()) {
- Map.Entry entry = (Entry) entries.next();
- Face f = (Face) entry.getValue();
- String faceName = (String) entry.getKey();
- assertEquals(f.getText(), faceName);
- }
- // Set all faces as HTML
- entries = faces.entrySet().iterator();
- while (entries.hasNext()) {
- Map.Entry entry = (Entry) entries.next();
- Face f = (Face) entry.getValue();
- String faceName = (String) entry.getKey();
- f.setHTML("<b>" + faceName + "</b>");
- }
-
- entries = faces.entrySet().iterator();
- while (entries.hasNext()) {
- Map.Entry entry = (Entry) entries.next();
- Face f = (Face) entry.getValue();
- String faceName = (String) entry.getKey();
- assertEquals(f.getText(), faceName);
- assertEquals(f.getHTML().toLowerCase(), "<b>" + faceName.toLowerCase()
- + "</b>");
- }
- }
-
- public void testTransitions() {
- ToggleButton b = new ToggleButton("transitions");
-
- b.setDown(true);
- assertTrue(b.isDown());
- assertFalse(b.isHovering());
- assertTrue(b.isEnabled());
-
- b.setHovering(true);
- assertTrue(b.isDown());
- assertTrue(b.isHovering());
- assertTrue(b.isEnabled());
-
- b.setEnabled(false);
- assertTrue(b.isDown());
- assertFalse(b.isHovering());
- assertFalse(b.isEnabled());
-
- b.setDown(false);
- assertFalse(b.isHovering());
- assertFalse(b.isEnabled());
- assertFalse(b.isDown());
-
- b.setEnabled(false);
- assertFalse(b.isHovering());
- assertFalse(b.isEnabled());
- assertFalse(b.isDown());
-
- b.setEnabled(false);
- b.setHovering(true);
- assertTrue(b.isHovering());
- assertFalse(b.isDown());
- assertFalse(b.isEnabled());
- }
-
-}
+/*
+ * Copyright 2007 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.client.DOM;
+import com.google.gwt.user.client.ui.CustomButton.Face;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Test for <code>PushButton</code> as most of this widget's functionality is
+ * UI based, the primary test will be in the new UI testing framework once it is
+ * released.
+ *
+ */
+public class CustomButtonTest extends GWTTestCase {
+
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ public void testCSS() {
+ ToggleButton b = new ToggleButton("up", "down");
+ b.setStyleName("random");
+ b.setDown(true);
+ assertEquals(b.getStyleName(), "random");
+
+ Map faces = new HashMap();
+ faces.put("downDisabled", b.getDownDisabledFace());
+ faces.put("upDisabled", b.getUpDisabledFace());
+ faces.put("down", b.getDownFace());
+ faces.put("up", b.getUpFace());
+ faces.put("upHovering", b.getUpHoveringFace());
+ faces.put("downHovering", b.getDownHoveringFace());
+ Iterator entries = faces.entrySet().iterator();
+ // Set all faces as text.
+ while (entries.hasNext()) {
+ Map.Entry entry = (Entry) entries.next();
+ Face f = (Face) entry.getValue();
+ b.setCurrentFace(f);
+ assertEquals("random-" + f.getName(), DOM.getElementProperty(
+ b.getElement(), "className").trim());
+ }
+
+ entries = faces.entrySet().iterator();
+ b.addStyleName("fobar");
+ // Set all faces as text.
+ while (entries.hasNext()) {
+ Map.Entry entry = (Entry) entries.next();
+ Face f = (Face) entry.getValue();
+ b.setCurrentFace(f);
+ String computedStyleName = DOM.getElementProperty(b.getElement(),
+ "className");
+ assertTrue(computedStyleName.indexOf("random-" + f.getName()) >= 0);
+ assertTrue(computedStyleName.indexOf("fobar") >= 0);
+ }
+ }
+
+ public void testSettingFaces() {
+ PushButton b = new PushButton();
+ Map faces = new HashMap();
+ faces.put("downDisabled", b.getDownDisabledFace());
+ faces.put("upDisabled", b.getUpDisabledFace());
+ faces.put("down", b.getDownFace());
+ faces.put("up", b.getUpFace());
+ faces.put("upHovering", b.getUpHoveringFace());
+ faces.put("downHovering", b.getDownHoveringFace());
+ Iterator entries = faces.entrySet().iterator();
+
+ // Set all faces as text.
+ while (entries.hasNext()) {
+ Map.Entry entry = (Entry) entries.next();
+ Face f = (Face) entry.getValue();
+ String faceName = (String) entry.getKey();
+ f.setText(faceName);
+ }
+ entries = faces.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Entry) entries.next();
+ Face f = (Face) entry.getValue();
+ String faceName = (String) entry.getKey();
+ assertEquals(f.getText(), faceName);
+ }
+ // Set all faces as HTML
+ entries = faces.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Entry) entries.next();
+ Face f = (Face) entry.getValue();
+ String faceName = (String) entry.getKey();
+ f.setHTML("<b>" + faceName + "</b>");
+ }
+
+ entries = faces.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Entry) entries.next();
+ Face f = (Face) entry.getValue();
+ String faceName = (String) entry.getKey();
+ assertEquals(f.getText(), faceName);
+ assertEquals(f.getHTML().toLowerCase(), "<b>" + faceName.toLowerCase()
+ + "</b>");
+ }
+ }
+
+ public void testTransitions() {
+ ToggleButton b = new ToggleButton("transitions");
+
+ b.setDown(true);
+ assertTrue(b.isDown());
+ assertFalse(b.isHovering());
+ assertTrue(b.isEnabled());
+
+ b.setHovering(true);
+ assertTrue(b.isDown());
+ assertTrue(b.isHovering());
+ assertTrue(b.isEnabled());
+
+ b.setEnabled(false);
+ assertTrue(b.isDown());
+ assertFalse(b.isHovering());
+ assertFalse(b.isEnabled());
+
+ b.setDown(false);
+ assertFalse(b.isHovering());
+ assertFalse(b.isEnabled());
+ assertFalse(b.isDown());
+
+ b.setEnabled(false);
+ assertFalse(b.isHovering());
+ assertFalse(b.isEnabled());
+ assertFalse(b.isDown());
+
+ b.setEnabled(false);
+ b.setHovering(true);
+ assertTrue(b.isHovering());
+ assertFalse(b.isDown());
+ assertFalse(b.isEnabled());
+ }
+
+}
diff --git a/user/test/com/google/gwt/user/client/ui/HorizontalPanelTest.java b/user/test/com/google/gwt/user/client/ui/HorizontalPanelTest.java
index 154d4f0..588ee25 100644
--- a/user/test/com/google/gwt/user/client/ui/HorizontalPanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/HorizontalPanelTest.java
@@ -1,69 +1,69 @@
-/*
- * Copyright 2007 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 java.util.Iterator;
-
-/**
- * A test for {@link HorizontalPanel}.
- */
-public class HorizontalPanelTest extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.user.User";
- }
-
- public void testInsertMultipleTimes() {
- HorizontalPanel p = new HorizontalPanel();
-
- TextBox tb = new TextBox();
- p.add(tb);
- p.add(tb);
- p.add(tb);
-
- assertEquals(1, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(tb));
- Iterator i = p.iterator();
- assertTrue(i.hasNext());
- assertTrue(tb.equals(i.next()));
- assertFalse(i.hasNext());
-
- Label l = new Label();
- p.add(l);
- p.add(l);
- p.add(l);
- assertEquals(2, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(tb));
- assertEquals(1, p.getWidgetIndex(l));
-
- p.insert(l, 0);
- assertEquals(2, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(l));
- assertEquals(1, p.getWidgetIndex(tb));
-
- p.insert(l, 1);
- assertEquals(2, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(l));
- assertEquals(1, p.getWidgetIndex(tb));
-
- p.insert(l, 2);
- assertEquals(2, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(tb));
- assertEquals(1, p.getWidgetIndex(l));
- }
-}
+/*
+ * Copyright 2007 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 java.util.Iterator;
+
+/**
+ * A test for {@link HorizontalPanel}.
+ */
+public class HorizontalPanelTest extends GWTTestCase {
+
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ public void testInsertMultipleTimes() {
+ HorizontalPanel p = new HorizontalPanel();
+
+ TextBox tb = new TextBox();
+ p.add(tb);
+ p.add(tb);
+ p.add(tb);
+
+ assertEquals(1, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(tb));
+ Iterator i = p.iterator();
+ assertTrue(i.hasNext());
+ assertTrue(tb.equals(i.next()));
+ assertFalse(i.hasNext());
+
+ Label l = new Label();
+ p.add(l);
+ p.add(l);
+ p.add(l);
+ assertEquals(2, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(tb));
+ assertEquals(1, p.getWidgetIndex(l));
+
+ p.insert(l, 0);
+ assertEquals(2, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(l));
+ assertEquals(1, p.getWidgetIndex(tb));
+
+ p.insert(l, 1);
+ assertEquals(2, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(l));
+ assertEquals(1, p.getWidgetIndex(tb));
+
+ p.insert(l, 2);
+ assertEquals(2, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(tb));
+ assertEquals(1, p.getWidgetIndex(l));
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/ui/ImageTest.java b/user/test/com/google/gwt/user/client/ui/ImageTest.java
index 9c408d2..e27b139 100644
--- a/user/test/com/google/gwt/user/client/ui/ImageTest.java
+++ b/user/test/com/google/gwt/user/client/ui/ImageTest.java
@@ -1,369 +1,369 @@
-/*
- * Copyright 2007 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.client.Timer;
-
-import java.util.ArrayList;
-
-/**
- * Tests for the Image widget. Images in both clipped mode and unclipped mode
- * are tested, along with the transitions between the two modes.
- */
-public class ImageTest extends GWTTestCase {
-
- /**
- * Helper method that allows us to 'peek' at the private <code>state</code>
- * field in the Image object, and call the <code>state.getStateName()</code>
- * method.
- *
- * @param image The image instance
- * @return "unclipped" if image is in the unclipped state, or
- * "clipped" if the image is in the clipped state
- */
- public static native String getCurrentImageStateName(Image image) /*-{
- var imgState = image.@com.google.gwt.user.client.ui.Image::state;
- return imgState.@com.google.gwt.user.client.ui.Image.State::getStateName() ();
- }-*/;
-
- public String getModuleName() {
- return "com.google.gwt.user.User";
- }
-
- /**
- * Tests the transition from the unclipped state to the clipped state
- */
- /* This test is commented out because of issue #863
- public void testChangeImageToClipped() {
- final ArrayList onloadEventFireCounter = new ArrayList();
- final Image image = new Image("counting-forwards.png");
- assertEquals("unclipped", getCurrentImageStateName(image));
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
- onloadEventFireCounter.add(new Object());
-
- if (getCurrentImageStateName(image).equals("unclipped")) {
- image.setVisibleRect(12, 13, 8, 8);
- }
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(12, image.getOriginLeft());
- assertEquals(13, image.getOriginTop());
- assertEquals(8, image.getWidth());
- assertEquals(8, image.getHeight());
- assertEquals("clipped", getCurrentImageStateName(image));
- assertEquals(2, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
- */
-
- /**
- * Tests the transition from the clipped state to the unclipped state.
- */
- public void testChangeClippedImageToUnclipped() {
- final ArrayList onloadEventFireCounter = new ArrayList();
- final Image image = new Image("counting-forwards.png",
- 12, 13, 8, 8);
- assertEquals("clipped", getCurrentImageStateName(image));
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
- onloadEventFireCounter.add(new Object());
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- image.setUrl("counting-forwards.png");
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(0, image.getOriginLeft());
- assertEquals(0, image.getOriginTop());
- assertEquals(32, image.getWidth());
- assertEquals(32, image.getHeight());
- assertEquals("unclipped", getCurrentImageStateName(image));
- assertEquals(2, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
-
- /**
- * Tests the creation of an image in unclipped mode
- */
- /* This test is commented out because of issue #864 and issue #863
- public void testCreateImage() {
- final ArrayList onloadEventFireCounter = new ArrayList();
- final Image image = new Image("counting-forwards.png");
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
- onloadEventFireCounter.add(new Object());
- assertEquals(32, image.getWidth());
- assertEquals(32, image.getHeight());
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- assertEquals(0, image.getOriginLeft());
- assertEquals(0, image.getOriginTop());
- assertEquals("unclipped", getCurrentImageStateName(image));
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(1, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
- */
-
- /**
- * Tests the creation of an image in clipped mode.
- */
- public void testCreateClippedImage() {
- final ArrayList onloadEventFireCounter = new ArrayList();
- final Image image = new Image("counting-forwards.png",
- 16, 16, 16, 16);
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
- onloadEventFireCounter.add(new Object());
- assertEquals(16, image.getWidth());
- assertEquals(16, image.getHeight());
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- assertEquals(16, image.getOriginLeft());
- assertEquals(16, image.getOriginTop());
- assertEquals("clipped", getCurrentImageStateName(image));
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(1, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
-
- /**
- * Tests the firing of onload events when
- * {@link com.google.gwt.user.client.ui.Image#setUrl(String)}
- * is called on an unclipped image.
- */
- /* This test has been commented out because of issue #863
- public void testSetUrlAndLoadEventsOnUnclippedImage() {
-
- final ArrayList onloadEventFireCounter = new ArrayList();
- final Image image = new Image("counting-backwards.png");
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
-
- onloadEventFireCounter.add(new Object());
-
- if (onloadEventFireCounter.size() < 4) {
- image.setUrl("counting-forwards.png");
- }
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(4, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
- */
-
- /**
- * Tests the behavior of
- * {@link com.google.gwt.user.client.ui.Image#setUrlAndVisibleRect(String,int,int,int,int)}
- * on a clipped image.
- */
- public void testSetUrlAndVisibleRectOnClippedImage() {
- final ArrayList onloadEventFireCounter = new ArrayList();
- final Image image = new Image("counting-backwards.png",
- 12, 12, 12, 12);
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
- onloadEventFireCounter.add(new Object());
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- assertEquals("clipped", getCurrentImageStateName(image));
-
- image.setUrlAndVisibleRect("counting-forwards.png",
- 0, 16, 16, 16);
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(0, image.getOriginLeft());
- assertEquals(16, image.getOriginTop());
- assertEquals(16, image.getWidth());
- assertEquals(16, image.getHeight());
- assertEquals("clipped", getCurrentImageStateName(image));
- assertEquals(2, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
-
- /**
- * Tests the behavior of
- * <code>setUrlAndVisibleRect(String, int, int, int, int)</code> method on
- * an unclipped image, which causes a state transition to the clipped state.
- */
- /* This test has been commented out because of issue #863
- public void testSetUrlAndVisibleRectOnUnclippedImage() {
- final ArrayList onloadEventFireCounter = new ArrayList();
- final Image image =
- new Image("counting-backwards.png");
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
- onloadEventFireCounter.add(new Object());
- if (getCurrentImageStateName(image).equals("unclipped")) {
- image.setUrlAndVisibleRect("counting-forwards.png",
- 0, 16, 16, 16);
- }
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- assertEquals("unclipped", getCurrentImageStateName(image));
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(0, image.getOriginLeft());
- assertEquals(16, image.getOriginTop());
- assertEquals(16, image.getWidth());
- assertEquals(16, image.getHeight());
- assertEquals("clipped", getCurrentImageStateName(image));
- assertEquals(2, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
- */
-
- /**
- * Tests the firing of onload events when calling
- * {@link com.google.gwt.user.client.ui.Image#setVisibleRect(int,int,int,int)}
- * on a clipped image.
- */
- public void testSetVisibleRectAndLoadEventsOnClippedImage() {
- final ArrayList onloadEventFireCounter = new ArrayList();
- final Image image = new Image("counting-backwards.png",
- 16, 16, 16, 16);
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
- onloadEventFireCounter.add(new Object());
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- image.setVisibleRect(0, 0, 16, 16);
- image.setVisibleRect(0, 0, 16, 16);
- image.setVisibleRect(16, 0, 16, 16);
- image.setVisibleRect(16, 8, 8, 8);
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(4, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
-}
+/*
+ * Copyright 2007 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.client.Timer;
+
+import java.util.ArrayList;
+
+/**
+ * Tests for the Image widget. Images in both clipped mode and unclipped mode
+ * are tested, along with the transitions between the two modes.
+ */
+public class ImageTest extends GWTTestCase {
+
+ /**
+ * Helper method that allows us to 'peek' at the private <code>state</code>
+ * field in the Image object, and call the <code>state.getStateName()</code>
+ * method.
+ *
+ * @param image The image instance
+ * @return "unclipped" if image is in the unclipped state, or
+ * "clipped" if the image is in the clipped state
+ */
+ public static native String getCurrentImageStateName(Image image) /*-{
+ var imgState = image.@com.google.gwt.user.client.ui.Image::state;
+ return imgState.@com.google.gwt.user.client.ui.Image.State::getStateName() ();
+ }-*/;
+
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ /**
+ * Tests the transition from the unclipped state to the clipped state
+ */
+ /* This test is commented out because of issue #863
+ public void testChangeImageToClipped() {
+ final ArrayList onloadEventFireCounter = new ArrayList();
+ final Image image = new Image("counting-forwards.png");
+ assertEquals("unclipped", getCurrentImageStateName(image));
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+ onloadEventFireCounter.add(new Object());
+
+ if (getCurrentImageStateName(image).equals("unclipped")) {
+ image.setVisibleRect(12, 13, 8, 8);
+ }
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(12, image.getOriginLeft());
+ assertEquals(13, image.getOriginTop());
+ assertEquals(8, image.getWidth());
+ assertEquals(8, image.getHeight());
+ assertEquals("clipped", getCurrentImageStateName(image));
+ assertEquals(2, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+ */
+
+ /**
+ * Tests the transition from the clipped state to the unclipped state.
+ */
+ public void testChangeClippedImageToUnclipped() {
+ final ArrayList onloadEventFireCounter = new ArrayList();
+ final Image image = new Image("counting-forwards.png",
+ 12, 13, 8, 8);
+ assertEquals("clipped", getCurrentImageStateName(image));
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+ onloadEventFireCounter.add(new Object());
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ image.setUrl("counting-forwards.png");
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(0, image.getOriginLeft());
+ assertEquals(0, image.getOriginTop());
+ assertEquals(32, image.getWidth());
+ assertEquals(32, image.getHeight());
+ assertEquals("unclipped", getCurrentImageStateName(image));
+ assertEquals(2, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+
+ /**
+ * Tests the creation of an image in unclipped mode
+ */
+ /* This test is commented out because of issue #864 and issue #863
+ public void testCreateImage() {
+ final ArrayList onloadEventFireCounter = new ArrayList();
+ final Image image = new Image("counting-forwards.png");
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+ onloadEventFireCounter.add(new Object());
+ assertEquals(32, image.getWidth());
+ assertEquals(32, image.getHeight());
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ assertEquals(0, image.getOriginLeft());
+ assertEquals(0, image.getOriginTop());
+ assertEquals("unclipped", getCurrentImageStateName(image));
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(1, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+ */
+
+ /**
+ * Tests the creation of an image in clipped mode.
+ */
+ public void testCreateClippedImage() {
+ final ArrayList onloadEventFireCounter = new ArrayList();
+ final Image image = new Image("counting-forwards.png",
+ 16, 16, 16, 16);
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+ onloadEventFireCounter.add(new Object());
+ assertEquals(16, image.getWidth());
+ assertEquals(16, image.getHeight());
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ assertEquals(16, image.getOriginLeft());
+ assertEquals(16, image.getOriginTop());
+ assertEquals("clipped", getCurrentImageStateName(image));
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(1, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+
+ /**
+ * Tests the firing of onload events when
+ * {@link com.google.gwt.user.client.ui.Image#setUrl(String)}
+ * is called on an unclipped image.
+ */
+ /* This test has been commented out because of issue #863
+ public void testSetUrlAndLoadEventsOnUnclippedImage() {
+
+ final ArrayList onloadEventFireCounter = new ArrayList();
+ final Image image = new Image("counting-backwards.png");
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+
+ onloadEventFireCounter.add(new Object());
+
+ if (onloadEventFireCounter.size() < 4) {
+ image.setUrl("counting-forwards.png");
+ }
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(4, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+ */
+
+ /**
+ * Tests the behavior of
+ * {@link com.google.gwt.user.client.ui.Image#setUrlAndVisibleRect(String,int,int,int,int)}
+ * on a clipped image.
+ */
+ public void testSetUrlAndVisibleRectOnClippedImage() {
+ final ArrayList onloadEventFireCounter = new ArrayList();
+ final Image image = new Image("counting-backwards.png",
+ 12, 12, 12, 12);
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+ onloadEventFireCounter.add(new Object());
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ assertEquals("clipped", getCurrentImageStateName(image));
+
+ image.setUrlAndVisibleRect("counting-forwards.png",
+ 0, 16, 16, 16);
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(0, image.getOriginLeft());
+ assertEquals(16, image.getOriginTop());
+ assertEquals(16, image.getWidth());
+ assertEquals(16, image.getHeight());
+ assertEquals("clipped", getCurrentImageStateName(image));
+ assertEquals(2, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+
+ /**
+ * Tests the behavior of
+ * <code>setUrlAndVisibleRect(String, int, int, int, int)</code> method on
+ * an unclipped image, which causes a state transition to the clipped state.
+ */
+ /* This test has been commented out because of issue #863
+ public void testSetUrlAndVisibleRectOnUnclippedImage() {
+ final ArrayList onloadEventFireCounter = new ArrayList();
+ final Image image =
+ new Image("counting-backwards.png");
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+ onloadEventFireCounter.add(new Object());
+ if (getCurrentImageStateName(image).equals("unclipped")) {
+ image.setUrlAndVisibleRect("counting-forwards.png",
+ 0, 16, 16, 16);
+ }
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ assertEquals("unclipped", getCurrentImageStateName(image));
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(0, image.getOriginLeft());
+ assertEquals(16, image.getOriginTop());
+ assertEquals(16, image.getWidth());
+ assertEquals(16, image.getHeight());
+ assertEquals("clipped", getCurrentImageStateName(image));
+ assertEquals(2, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+ */
+
+ /**
+ * Tests the firing of onload events when calling
+ * {@link com.google.gwt.user.client.ui.Image#setVisibleRect(int,int,int,int)}
+ * on a clipped image.
+ */
+ public void testSetVisibleRectAndLoadEventsOnClippedImage() {
+ final ArrayList onloadEventFireCounter = new ArrayList();
+ final Image image = new Image("counting-backwards.png",
+ 16, 16, 16, 16);
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+ onloadEventFireCounter.add(new Object());
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ image.setVisibleRect(0, 0, 16, 16);
+ image.setVisibleRect(0, 0, 16, 16);
+ image.setVisibleRect(16, 0, 16, 16);
+ image.setVisibleRect(16, 8, 8, 8);
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(4, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/ui/NamedFrameTest.java b/user/test/com/google/gwt/user/client/ui/NamedFrameTest.java
index b897fd6..d25665c 100644
--- a/user/test/com/google/gwt/user/client/ui/NamedFrameTest.java
+++ b/user/test/com/google/gwt/user/client/ui/NamedFrameTest.java
@@ -1,79 +1,79 @@
-/*
- * Copyright 2007 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;
-
-/**
- * Tests the {@link NamedFrame} widget.
- */
-public class NamedFrameTest extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.user.User";
- }
-
- public void testNormalName() {
- String name = "testFrame";
- NamedFrame frame = new NamedFrame(name);
- assertEquals(name, frame.getName());
- }
-
- public void testEmptyName() {
- try {
- new NamedFrame("");
- fail("Empty frame name not allowed");
- } catch (IllegalArgumentException e) {
- // Success
- }
- }
-
- public void testWhitespaceName() {
- try {
- new NamedFrame(" ");
- fail("Whitespace-only frame name not allowed");
- } catch (IllegalArgumentException e) {
- // Success
- }
- }
-
- public void testHTMLName() {
- try {
- new NamedFrame("<b>yuck</b>");
- fail("html in frame name not allowed");
- } catch (IllegalArgumentException e) {
- // Success
- }
- }
-
- public void testQuotesInName() {
- try {
- new NamedFrame("he said \"yuck\"");
- fail("double-quotes in frame name not allowed");
- } catch (IllegalArgumentException e) {
- // Success
- }
- }
-
- public void testApostropheInName() {
- try {
- new NamedFrame("he said 'yuck'");
- fail("apostrophe in frame name not allowed");
- } catch (IllegalArgumentException e) {
- // Success
- }
- }
-}
+/*
+ * Copyright 2007 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;
+
+/**
+ * Tests the {@link NamedFrame} widget.
+ */
+public class NamedFrameTest extends GWTTestCase {
+
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ public void testNormalName() {
+ String name = "testFrame";
+ NamedFrame frame = new NamedFrame(name);
+ assertEquals(name, frame.getName());
+ }
+
+ public void testEmptyName() {
+ try {
+ new NamedFrame("");
+ fail("Empty frame name not allowed");
+ } catch (IllegalArgumentException e) {
+ // Success
+ }
+ }
+
+ public void testWhitespaceName() {
+ try {
+ new NamedFrame(" ");
+ fail("Whitespace-only frame name not allowed");
+ } catch (IllegalArgumentException e) {
+ // Success
+ }
+ }
+
+ public void testHTMLName() {
+ try {
+ new NamedFrame("<b>yuck</b>");
+ fail("html in frame name not allowed");
+ } catch (IllegalArgumentException e) {
+ // Success
+ }
+ }
+
+ public void testQuotesInName() {
+ try {
+ new NamedFrame("he said \"yuck\"");
+ fail("double-quotes in frame name not allowed");
+ } catch (IllegalArgumentException e) {
+ // Success
+ }
+ }
+
+ public void testApostropheInName() {
+ try {
+ new NamedFrame("he said 'yuck'");
+ fail("apostrophe in frame name not allowed");
+ } catch (IllegalArgumentException e) {
+ // Success
+ }
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/ui/VerticalPanelTest.java b/user/test/com/google/gwt/user/client/ui/VerticalPanelTest.java
index 7f424e9..7fb5191 100644
--- a/user/test/com/google/gwt/user/client/ui/VerticalPanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/VerticalPanelTest.java
@@ -1,69 +1,69 @@
-/*
- * Copyright 2007 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 java.util.Iterator;
-
-/**
- * A test for {@link VerticalPanel}.
- */
-public class VerticalPanelTest extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.user.User";
- }
-
- public void testInsertMultipleTimes() {
- VerticalPanel p = new VerticalPanel();
-
- TextBox tb = new TextBox();
- p.add(tb);
- p.add(tb);
- p.add(tb);
-
- assertEquals(1, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(tb));
- Iterator i = p.iterator();
- assertTrue(i.hasNext());
- assertTrue(tb.equals(i.next()));
- assertFalse(i.hasNext());
-
- Label l = new Label();
- p.add(l);
- p.add(l);
- p.add(l);
- assertEquals(2, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(tb));
- assertEquals(1, p.getWidgetIndex(l));
-
- p.insert(l, 0);
- assertEquals(2, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(l));
- assertEquals(1, p.getWidgetIndex(tb));
-
- p.insert(l, 1);
- assertEquals(2, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(l));
- assertEquals(1, p.getWidgetIndex(tb));
-
- p.insert(l, 2);
- assertEquals(2, p.getWidgetCount());
- assertEquals(0, p.getWidgetIndex(tb));
- assertEquals(1, p.getWidgetIndex(l));
- }
-}
+/*
+ * Copyright 2007 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 java.util.Iterator;
+
+/**
+ * A test for {@link VerticalPanel}.
+ */
+public class VerticalPanelTest extends GWTTestCase {
+
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ public void testInsertMultipleTimes() {
+ VerticalPanel p = new VerticalPanel();
+
+ TextBox tb = new TextBox();
+ p.add(tb);
+ p.add(tb);
+ p.add(tb);
+
+ assertEquals(1, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(tb));
+ Iterator i = p.iterator();
+ assertTrue(i.hasNext());
+ assertTrue(tb.equals(i.next()));
+ assertFalse(i.hasNext());
+
+ Label l = new Label();
+ p.add(l);
+ p.add(l);
+ p.add(l);
+ assertEquals(2, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(tb));
+ assertEquals(1, p.getWidgetIndex(l));
+
+ p.insert(l, 0);
+ assertEquals(2, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(l));
+ assertEquals(1, p.getWidgetIndex(tb));
+
+ p.insert(l, 1);
+ assertEquals(2, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(l));
+ assertEquals(1, p.getWidgetIndex(tb));
+
+ p.insert(l, 2);
+ assertEquals(2, p.getWidgetCount());
+ assertEquals(0, p.getWidgetIndex(tb));
+ assertEquals(1, p.getWidgetIndex(l));
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/ui/impl/ClippedImagePrototypeTest.java b/user/test/com/google/gwt/user/client/ui/impl/ClippedImagePrototypeTest.java
index afc1b79..24627da 100644
--- a/user/test/com/google/gwt/user/client/ui/impl/ClippedImagePrototypeTest.java
+++ b/user/test/com/google/gwt/user/client/ui/impl/ClippedImagePrototypeTest.java
@@ -1,161 +1,161 @@
-/*
- * Copyright 2007 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.impl;
-
-import com.google.gwt.junit.client.GWTTestCase;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.ImageTest;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.LoadListener;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.Timer;
-
-import java.util.ArrayList;
-
-/**
- * Tests for the ClippedImagePrototype implementation. Tests are done to ensure
- * that clipped images are generated which match the prototype's specification,
- * and that applications of the prototype to existing images in both
- * clipped/unclipped mode change the image so that it matches the prototype.
- * Tests are also done to ensure that load events fire correctly after the
- * application of the prototype to the image.
- */
-public class ClippedImagePrototypeTest extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.user.User";
- }
-
- /**
- * Tests that a clipped image can be transformed to match a given prototype.
- * Also checks to make sure that a load event is fired on when
- * {@link com.google.gwt.user.client.ui.impl.ClippedImagePrototype#applyTo(com.google.gwt.user.client.ui.Image)}
- * is called.
- */
- public void testApplyToClippedImage() {
-
- final Image image = new Image("counting-backwards.png", 12, 13, 8, 8);
-
- assertEquals(12, image.getOriginLeft());
- assertEquals(13, image.getOriginTop());
- assertEquals(8, image.getWidth());
- assertEquals(8, image.getHeight());
- assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
-
- final ArrayList onloadEventFireCounter = new ArrayList();
-
- image.addLoadListener(new LoadListener() {
- public void onError(Widget sender) {
- fail("The image " + ((Image) sender).getUrl() + " failed to load.");
- }
-
- public void onLoad(Widget sender) {
- onloadEventFireCounter.add(new Object());
-
- if (image.getOriginLeft() == 12 && image.getOriginTop() == 13) {
- ClippedImagePrototype clippedImagePrototype = new ClippedImagePrototype(
- "counting-forwards.png", 16, 16, 16, 16);
-
- clippedImagePrototype.applyTo(image);
-
- assertEquals(16, image.getOriginLeft());
- assertEquals(16, image.getOriginTop());
- assertEquals(16, image.getWidth());
- assertEquals(16, image.getHeight());
- assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
- }
- }
- });
-
- RootPanel.get().add(image);
- delayTestFinish(2000);
-
- Timer t = new Timer() {
- public void run() {
- assertEquals(2, onloadEventFireCounter.size());
- finishTest();
- }
- };
-
- t.schedule(1000);
- }
-
- /**
- * Tests that an unclipped image can be transformed to match a given
- * prototype. Also checks to make sure that a load event is fired on when
- * <code>applyTo(Image)</code> is called.
- */
- /*
- * This test has been commented out because of issue #863
- *
- * public void testApplyToUnclippedImage() {
- * final Image image = new Image("counting-backwards.png");
- *
- * assertEquals(0, image.getOriginLeft()); assertEquals(0,
- * image.getOriginTop()); assertEquals("unclipped",
- * ImageTest.getCurrentImageStateName(image));
- *
- * final ArrayList onloadEventFireCounter = new ArrayList();
- *
- * image.addLoadListener(new LoadListener() { public void onError(Widget
- * sender) { fail("The image " + ((Image) sender).getUrl() + " failed to
- * load."); }
- *
- * public void onLoad(Widget sender) { onloadEventFireCounter.add(new
- * Object());
- *
- * if (ImageTest.getCurrentImageStateName(image).equals("unclipped")) {
- *
- * assertEquals(32, image.getWidth()); assertEquals(32, image.getHeight());
- *
- * ClippedImagePrototype clippedImagePrototype = new
- * ClippedImagePrototype("counting-forwards.png", 16, 16, 16, 16);
- *
- * clippedImagePrototype.adjust(image);
- *
- * assertEquals(16, image.getOriginLeft()); assertEquals(16,
- * image.getOriginTop()); assertEquals(16, image.getWidth()); assertEquals(16,
- * image.getHeight()); assertEquals("counting-forwards.png", image.getUrl());
- * assertEquals("clipped", ImageTest.getCurrentImageStateName(image)); } } });
- *
- * RootPanel.get().add(image); delayTestFinish(2000);
- *
- * Timer t = new Timer() { public void run() { assertEquals(2,
- * onloadEventFireCounter.size()); finishTest(); } };
- *
- * t.schedule(1000); }
- */
-
- /**
- * Tests that new clipped images can be generated from a prototype by calling
- * {@link ClippedImagePrototype#createImage()}.
- */
- public void testGenerateNewImage() {
- ClippedImagePrototype clippedImagePrototype = new ClippedImagePrototype(
- "counting-forwards.png", 16, 16, 16, 16);
-
- Image image = clippedImagePrototype.createImage();
-
- RootPanel.get().add(image);
-
- assertEquals(16, image.getOriginLeft());
- assertEquals(16, image.getOriginTop());
- assertEquals(16, image.getWidth());
- assertEquals(16, image.getHeight());
- assertEquals("counting-forwards.png", image.getUrl());
- assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
- }
-}
+/*
+ * Copyright 2007 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.impl;
+
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwt.user.client.ui.ImageTest;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.LoadListener;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.Timer;
+
+import java.util.ArrayList;
+
+/**
+ * Tests for the ClippedImagePrototype implementation. Tests are done to ensure
+ * that clipped images are generated which match the prototype's specification,
+ * and that applications of the prototype to existing images in both
+ * clipped/unclipped mode change the image so that it matches the prototype.
+ * Tests are also done to ensure that load events fire correctly after the
+ * application of the prototype to the image.
+ */
+public class ClippedImagePrototypeTest extends GWTTestCase {
+
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ /**
+ * Tests that a clipped image can be transformed to match a given prototype.
+ * Also checks to make sure that a load event is fired on when
+ * {@link com.google.gwt.user.client.ui.impl.ClippedImagePrototype#applyTo(com.google.gwt.user.client.ui.Image)}
+ * is called.
+ */
+ public void testApplyToClippedImage() {
+
+ final Image image = new Image("counting-backwards.png", 12, 13, 8, 8);
+
+ assertEquals(12, image.getOriginLeft());
+ assertEquals(13, image.getOriginTop());
+ assertEquals(8, image.getWidth());
+ assertEquals(8, image.getHeight());
+ assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
+
+ final ArrayList onloadEventFireCounter = new ArrayList();
+
+ image.addLoadListener(new LoadListener() {
+ public void onError(Widget sender) {
+ fail("The image " + ((Image) sender).getUrl() + " failed to load.");
+ }
+
+ public void onLoad(Widget sender) {
+ onloadEventFireCounter.add(new Object());
+
+ if (image.getOriginLeft() == 12 && image.getOriginTop() == 13) {
+ ClippedImagePrototype clippedImagePrototype = new ClippedImagePrototype(
+ "counting-forwards.png", 16, 16, 16, 16);
+
+ clippedImagePrototype.applyTo(image);
+
+ assertEquals(16, image.getOriginLeft());
+ assertEquals(16, image.getOriginTop());
+ assertEquals(16, image.getWidth());
+ assertEquals(16, image.getHeight());
+ assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
+ }
+ }
+ });
+
+ RootPanel.get().add(image);
+ delayTestFinish(2000);
+
+ Timer t = new Timer() {
+ public void run() {
+ assertEquals(2, onloadEventFireCounter.size());
+ finishTest();
+ }
+ };
+
+ t.schedule(1000);
+ }
+
+ /**
+ * Tests that an unclipped image can be transformed to match a given
+ * prototype. Also checks to make sure that a load event is fired on when
+ * <code>applyTo(Image)</code> is called.
+ */
+ /*
+ * This test has been commented out because of issue #863
+ *
+ * public void testApplyToUnclippedImage() {
+ * final Image image = new Image("counting-backwards.png");
+ *
+ * assertEquals(0, image.getOriginLeft()); assertEquals(0,
+ * image.getOriginTop()); assertEquals("unclipped",
+ * ImageTest.getCurrentImageStateName(image));
+ *
+ * final ArrayList onloadEventFireCounter = new ArrayList();
+ *
+ * image.addLoadListener(new LoadListener() { public void onError(Widget
+ * sender) { fail("The image " + ((Image) sender).getUrl() + " failed to
+ * load."); }
+ *
+ * public void onLoad(Widget sender) { onloadEventFireCounter.add(new
+ * Object());
+ *
+ * if (ImageTest.getCurrentImageStateName(image).equals("unclipped")) {
+ *
+ * assertEquals(32, image.getWidth()); assertEquals(32, image.getHeight());
+ *
+ * ClippedImagePrototype clippedImagePrototype = new
+ * ClippedImagePrototype("counting-forwards.png", 16, 16, 16, 16);
+ *
+ * clippedImagePrototype.adjust(image);
+ *
+ * assertEquals(16, image.getOriginLeft()); assertEquals(16,
+ * image.getOriginTop()); assertEquals(16, image.getWidth()); assertEquals(16,
+ * image.getHeight()); assertEquals("counting-forwards.png", image.getUrl());
+ * assertEquals("clipped", ImageTest.getCurrentImageStateName(image)); } } });
+ *
+ * RootPanel.get().add(image); delayTestFinish(2000);
+ *
+ * Timer t = new Timer() { public void run() { assertEquals(2,
+ * onloadEventFireCounter.size()); finishTest(); } };
+ *
+ * t.schedule(1000); }
+ */
+
+ /**
+ * Tests that new clipped images can be generated from a prototype by calling
+ * {@link ClippedImagePrototype#createImage()}.
+ */
+ public void testGenerateNewImage() {
+ ClippedImagePrototype clippedImagePrototype = new ClippedImagePrototype(
+ "counting-forwards.png", 16, 16, 16, 16);
+
+ Image image = clippedImagePrototype.createImage();
+
+ RootPanel.get().add(image);
+
+ assertEquals(16, image.getOriginLeft());
+ assertEquals(16, image.getOriginTop());
+ assertEquals(16, image.getWidth());
+ assertEquals(16, image.getHeight());
+ assertEquals("counting-forwards.png", image.getUrl());
+ assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
+ }
+}