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

- *   *&#47;

- *  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

- *   *&#47;

- *  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

- *   *&#47;

- *  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
+ *   *&#47;
+ *  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
+ *   *&#47;
+ *  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
+ *   *&#47;
+ *  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>&lt;img&gt;</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>&lt;img&gt;</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));
+  }
+}