Adds a new InitializeEvent and integrates it with the Rich Text Area.  The
event is fired after the RichText area is initialized (which can mean different
things on different browsers).

Patch by: zundel
Review by: jlabanca


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6147 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/event/logical/shared/HasInitializeHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasInitializeHandlers.java
new file mode 100644
index 0000000..1eba044
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasInitializeHandlers.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.event.shared.HasHandlers;
+
+/**
+ * A widget that implements this interface is a public source of
+ * {@link InitializeEvent} events.
+ * 
+ */
+public interface HasInitializeHandlers extends HasHandlers {
+  /**
+   * Adds a {@link InitializeEvent} handler.
+   * 
+   * @param handler the handler
+   * @return the registration for the event
+   */
+  HandlerRegistration addInitializeHandler(InitializeHandler handler);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/logical/shared/InitializeEvent.java b/user/src/com/google/gwt/event/logical/shared/InitializeEvent.java
new file mode 100644
index 0000000..fbb46df
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/InitializeEvent.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HasHandlers;
+
+/**
+ * Fired when the event source is initialized.
+ */
+public class InitializeEvent extends GwtEvent<InitializeHandler> {
+
+  /**
+   * The event type.
+   */
+  private static Type<InitializeHandler> TYPE;
+
+  /**
+   * Fires a initialize event on all registered handlers in the handler source.
+   * 
+   * @param <S> The handler source
+   * @param source the source of the handlers
+   */
+  public static <S extends HasInitializeHandlers & HasHandlers> void fire(
+      S source) {
+    if (TYPE != null) {
+      InitializeEvent event = new InitializeEvent();
+      source.fireEvent(event);
+    }
+  }
+
+  /**
+   * Ensures the existence of the handler hook and then returns it.
+   * 
+   * @return returns a handler hook
+   */
+  public static Type<InitializeHandler> getType() {
+    if (TYPE == null) {
+      TYPE = new Type<InitializeHandler>();
+    }
+    return TYPE;
+  }
+
+  /**
+   * Construct a new {@link InitializeEvent}.
+   * 
+   */
+  protected InitializeEvent() {
+  }
+
+  @Override
+  public final Type<InitializeHandler> getAssociatedType() {
+    return TYPE;
+  }
+
+  @Override
+  protected void dispatch(InitializeHandler handler) {
+    handler.onInitialize(this);
+  }
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/InitializeHandler.java b/user/src/com/google/gwt/event/logical/shared/InitializeHandler.java
new file mode 100644
index 0000000..705419c
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/InitializeHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2009 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler for {@link InitializeEvent} events.
+ */
+public interface InitializeHandler extends EventHandler {
+  /**
+   * Fired when the widget is initialized.
+   * 
+   * @param event the event
+   */
+  void onInitialize(InitializeEvent event);
+}
\ No newline at end of file
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 92731c5..28f6af0 100644
--- a/user/src/com/google/gwt/user/client/ui/RichTextArea.java
+++ b/user/src/com/google/gwt/user/client/ui/RichTextArea.java
@@ -17,6 +17,10 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.HasAllMouseHandlers;
+import com.google.gwt.event.logical.shared.HasInitializeHandlers;
+import com.google.gwt.event.logical.shared.InitializeEvent;
+import com.google.gwt.event.logical.shared.InitializeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.ui.impl.RichTextAreaImpl;
 
 /**
@@ -24,8 +28,8 @@
  * 
  * 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
+ * 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.
  * 
@@ -33,14 +37,15 @@
  * <img class='gallery' src='RichTextArea.png'/>
  * </p>
  * 
- * <h3>CSS Style Rules</h3>
- * <ul class="css">
- * <li>.gwt-RichTextArea { }</li>
- * </ul>
+ * <h3>CSS Style Rules</h3> 
+ * <dl>
+ *   <dt>.gwt-RichTextArea</dt>
+ *   <dd>Applied to the rich text element.</dd>
+ * </dl>
  */
 @SuppressWarnings("deprecation")
 public class RichTextArea extends FocusWidget implements HasHTML,
-    SourcesMouseEvents, HasAllMouseHandlers {
+    SourcesMouseEvents, HasAllMouseHandlers, HasInitializeHandlers {
 
   /**
    * <p>
@@ -51,10 +56,10 @@
    * </p>
    * <p>
    * The formatter will format the user selected text in the
-   * {@link RichTextArea}.  As a result, it will only work reliably if the
+   * {@link RichTextArea}. As a result, it will only work reliably if the
    * {@link RichTextArea} is attached, visible to on the page, and has been
-   * focused at least once.  If you just want to initialize the content of
-   * the {@link RichTextArea}, use {@link RichTextArea#setHTML(String)} instead. 
+   * focused at least once. If you just want to initialize the content of the
+   * {@link RichTextArea}, use {@link RichTextArea#setHTML(String)} instead.
    * </p>
    * 
    * @deprecated use {@link Formatter} instead
@@ -186,10 +191,10 @@
    * </p>
    * <p>
    * The formatter will format the user selected text in the
-   * {@link RichTextArea}.  As a result, it will only work reliably if the
+   * {@link RichTextArea}. As a result, it will only work reliably if the
    * {@link RichTextArea} is attached, visible to on the page, and has been
-   * focused at least once.  If you just want to initialize the content of
-   * the {@link RichTextArea}, use {@link RichTextArea#setHTML(String)} instead. 
+   * focused at least once. If you just want to initialize the content of the
+   * {@link RichTextArea}, use {@link RichTextArea#setHTML(String)} instead.
    * </p>
    * 
    * @deprecated use {@link Formatter} instead
@@ -260,255 +265,46 @@
   }
 
   /**
-   * <p>
-   * This interface is used to access full formatting options, when available.
-   * If the implementation supports full formatting, then
-   * {@link RichTextArea#getFormatter()} will return an instance of this
-   * class.
-   * </p>
-   * <p>
-   * The formatter will format the user selected text in the
-   * {@link RichTextArea}.  As a result, it will only work reliably if the
-   * {@link RichTextArea} is attached, visible to on the page, and has been
-   * focused at least once.  If you just want to initialize the content of
-   * the {@link RichTextArea}, use {@link RichTextArea#setHTML(String)} instead. 
-   * </p>
-   */
-  public interface Formatter extends ExtendedFormatter {
-    /**
-     * Creates a link to the supplied URL.
-     * 
-     * @param url the URL to be linked to
-     */
-    void createLink(String url);
-  
-    /**
-     * Gets the background color.
-     * 
-     * @return the background color
-     */
-    String getBackColor();
-  
-    /**
-     * Gets the foreground color.
-     * 
-     * @return the foreground color
-     */
-    String getForeColor();
-  
-    /**
-     * Inserts a horizontal rule.
-     */
-    void insertHorizontalRule();
-  
-    /**
-     * Inserts generic html.
-     * 
-     * @param html the HTML to insert
-     */
-    void insertHTML(String html);
-  
-    /**
-     * 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 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 strikethrough?
-     * 
-     * @return true if the current region is strikethrough
-     */
-    boolean isStrikethrough();
-  
-    /**
-     * 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();
-  
-    /**
-     * Left indent.
-     */
-    void leftIndent();
-  
-    /**
-     * Redo an action that was just undone.
-     */
-    void redo();
-  
-    /**
-     * Removes all formatting on the selected text.
-     */
-    void removeFormat();
-  
-    /**
-     * Removes any link from the selected text.
-     */
-    void removeLink();
-    
-    /**
-     * Right indent.
-     */
-    void rightIndent();
-  
-    /**
-     * 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 strikethrough.
-     */
-    void toggleStrikethrough();
-  
-    /**
-     * Toggles subscript.
-     */
-    void toggleSubscript();
-  
-    /**
-     * Toggles superscript.
-     */
-    void toggleSuperscript();
-  
-    /**
-     * Toggles underline.
-     */
-    void toggleUnderline();
-  
-    /**
-     * Undo the last action.
-     */
-    void undo();
-  }
-
-  /**
    * 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 a Medium font.
+     */
+    public static final FontSize MEDIUM = new FontSize(4);
+
+    /**
+     * Represents a Small font.
+     */
+    public static final FontSize SMALL = new FontSize(3);
+
+    /**
      * Represents an X-Large font.
      */
     public static final FontSize X_LARGE = new FontSize(6);
 
     /**
+     * Represents an X-Small font.
+     */
+    public static final FontSize X_SMALL = new FontSize(2);
+
+    /**
      * Represents an XX-Large font.
      */
     public static final FontSize XX_LARGE = new FontSize(7);
 
+    /**
+     * Represents an XX-Small font.
+     */
+    public static final FontSize XX_SMALL = new FontSize(1);
+
     private int number;
 
     private FontSize(int number) {
@@ -531,6 +327,214 @@
   }
 
   /**
+   * <p>
+   * This interface is used to access full formatting options, when available.
+   * If the implementation supports full formatting, then
+   * {@link RichTextArea#getFormatter()} will return an instance of this class.
+   * </p>
+   * <p>
+   * The formatter will format the user selected text in the
+   * {@link RichTextArea}. As a result, it will only work reliably if the
+   * {@link RichTextArea} is attached, visible to on the page, and has been
+   * focused at least once. If you just want to initialize the content of the
+   * {@link RichTextArea}, use {@link RichTextArea#setHTML(String)} instead.
+   * </p>
+   */
+  public interface Formatter extends ExtendedFormatter {
+    /**
+     * Creates a link to the supplied URL.
+     * 
+     * @param url the URL to be linked to
+     */
+    void createLink(String url);
+
+    /**
+     * Gets the background color.
+     * 
+     * @return the background color
+     */
+    String getBackColor();
+
+    /**
+     * Gets the foreground color.
+     * 
+     * @return the foreground color
+     */
+    String getForeColor();
+
+    /**
+     * Inserts a horizontal rule.
+     */
+    void insertHorizontalRule();
+
+    /**
+     * Inserts generic html.
+     * 
+     * @param html the HTML to insert
+     */
+    void insertHTML(String html);
+
+    /**
+     * 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 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 strikethrough?
+     * 
+     * @return true if the current region is strikethrough
+     */
+    boolean isStrikethrough();
+
+    /**
+     * 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();
+
+    /**
+     * Left indent.
+     */
+    void leftIndent();
+
+    /**
+     * Redo an action that was just undone.
+     */
+    void redo();
+
+    /**
+     * Removes all formatting on the selected text.
+     */
+    void removeFormat();
+
+    /**
+     * Removes any link from the selected text.
+     */
+    void removeLink();
+
+    /**
+     * Right indent.
+     */
+    void rightIndent();
+
+    /**
+     * 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 strikethrough.
+     */
+    void toggleStrikethrough();
+
+    /**
+     * Toggles subscript.
+     */
+    void toggleSubscript();
+
+    /**
+     * Toggles superscript.
+     */
+    void toggleSuperscript();
+
+    /**
+     * Toggles underline.
+     */
+    void toggleUnderline();
+
+    /**
+     * Undo the last action.
+     */
+    void undo();
+  }
+
+  /**
    * Justification enumeration. The three values are <code>left</code>,
    * <code>right</code>, <code>center</code>.
    */
@@ -576,10 +580,15 @@
   public RichTextArea() {
     setElement(impl.getElement());
     setStyleName("gwt-RichTextArea");
+    impl.setWidget(this);
+  }
+
+  public HandlerRegistration addInitializeHandler(InitializeHandler handler) {
+    return addHandler(handler, InitializeEvent.getType());
   }
 
   /**
-   * Gets the basic rich text formatting interface.  Note that formatting can
+   * Gets the basic rich text formatting interface. Note that formatting can
    * only be done when the {@link RichTextArea} is attached, visible on the
    * page, and has been focused by the user.
    * 
@@ -592,9 +601,9 @@
   }
 
   /**
-   * Gets the full rich text formatting interface.  Note that formatting can
-   * only be done when the {@link RichTextArea} is attached, visible on the
-   * page, and has been focused by the user.
+   * Gets the full rich text formatting interface. Note that formatting can only
+   * be done when the {@link RichTextArea} is attached, visible on the page, and
+   * has been focused by the user.
    * 
    * @return <code>null</code> if full formatting is not supported
    * @deprecated use {@link #getFormatter()} instead
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 0228633..e2e70f4 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
@@ -15,13 +15,15 @@
  */
 package com.google.gwt.user.client.ui.impl;
 
+import com.google.gwt.event.logical.shared.InitializeEvent;
 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.
+ * Base class for RichText platform implementations. The default version simply
+ * creates a text area with no rich text support.
  * 
  * This is not currently used by any user-agent, but will provide a
  * &lt;textarea&gt; fallback in the event a future browser fails to implement
@@ -30,6 +32,7 @@
 public class RichTextAreaImpl {
 
   protected Element elem;
+  protected RichTextArea richTextWidget;
 
   public RichTextAreaImpl() {
     elem = createElement();
@@ -56,7 +59,7 @@
       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) {
@@ -67,6 +70,10 @@
     DOM.setElementProperty(elem, "value", text);
   }
 
+  public void setWidget(RichTextArea richTextWidget) {
+    this.richTextWidget = richTextWidget;
+  }
+
   public void uninitElement() {
   }
 
@@ -76,10 +83,13 @@
 
   protected void hookEvents() {
     DOM.sinkEvents(elem, Event.MOUSEEVENTS | Event.KEYEVENTS | Event.ONCHANGE
-      | Event.ONCLICK | Event.FOCUSEVENTS);
+        | Event.ONCLICK | Event.FOCUSEVENTS);
   }
 
   protected void onElementInitialized() {
     hookEvents();
+    if (richTextWidget != null) {
+      InitializeEvent.fire(richTextWidget);
+    }
   }
 }
diff --git a/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java b/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java
index fc4ecd0..7b8e981 100644
--- a/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java
+++ b/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java
@@ -16,6 +16,8 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.logical.shared.InitializeEvent;
+import com.google.gwt.event.logical.shared.InitializeHandler;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.ui.RichTextArea.BasicFormatter;
@@ -148,6 +150,20 @@
     }.schedule(500);
   }
 
+  /** 
+   * See that the custom InitializeEvent fires.
+   */
+  public void testRichTextInitializeEvent() {
+    delayTestFinish(3000);
+    final RichTextArea richTextArea = new RichTextArea();
+    richTextArea.addInitializeHandler(new InitializeHandler() {
+      public void onInitialize(InitializeEvent event) {
+        finishTest();
+      }
+    });
+    RootPanel.get().add(richTextArea);
+  }
+
   /**
    * Test that a delayed set of HTML is reflected. Some platforms have timing
    * subtleties that need to be tested.