Revision: 10290
Author:   [email protected]
Date:     Tue Jun  7 09:30:28 2011
Log:      Extracts AbstractComposite<W> out of Composite, to allow type safe
calls to gwtWidget(). Deprecates ResizeComposite and replaces it with
RequiresResizeComposite, which moves the "must implement
RequireResize" requirement check to compile time.

Review at http://gwt-code-reviews.appspot.com/1453807

Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=10290

Added:
 /trunk/user/src/com/google/gwt/user/client/ui/AbstractComposite.java
 /trunk/user/src/com/google/gwt/user/client/ui/RequiresResizeComposite.java
Modified:
/trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskListView.java /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/MobileWebAppShellDesktop.java /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileWebAppShellMobile.java /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/MobileWebAppShellTablet.java
 /trunk/tools/api-checker/config/gwt23_24userApi.conf
 /trunk/user/src/com/google/gwt/user/client/ui/Composite.java
 /trunk/user/src/com/google/gwt/user/client/ui/ResizeComposite.java
 /trunk/user/src/com/google/gwt/user/client/ui/StackLayoutPanel.java
 /trunk/user/src/com/google/gwt/user/client/ui/TabLayoutPanel.java

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/user/client/ui/AbstractComposite.java Tue Jun 7 09:30:28 2011
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.ui;
+
+import com.google.gwt.event.logical.shared.AttachEvent;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+
+/**
+ * A type of widget that can wrap another widget, hiding the wrapped widget's + * methods. When added to a panel, a composite behaves exactly as if the widget
+ * it wraps had been added.
+ * <p>
+ * The composite is useful for creating a single widget out of an aggregate of
+ * multiple other widgets contained in a single panel.
+ *
+ * @see Composite
+ *
+ * @param <W> the type of IsWidget this composite wraps
+ */
+public class AbstractComposite<W extends IsWidget> extends Widget {
+
+  private W isWidget;
+
+  @Override
+  public boolean isAttached() {
+    if (isWidget != null) {
+      return isWidget.asWidget().isAttached();
+    }
+    return false;
+  }
+
+  @Override
+  public void onBrowserEvent(Event event) {
+    // Fire any handler added to the composite itself.
+    super.onBrowserEvent(event);
+
+    // Delegate events to the widget.
+    getWidget().asWidget().onBrowserEvent(event);
+  }
+
+  /**
+   * Provides subclasses access to the widget that defines this composite.
+   *
+   * @return the widget
+   */
+  protected W getWidget() {
+    return isWidget;
+  }
+
+  /**
+ * Sets the widget to be wrapped by the composite. The wrapped widget must be + * set before calling any {@link Widget} methods on this object, or adding it
+   * to a panel. This method may only be called once for a given composite.
+   * <p>
+ * The widget returned by the wrapped object's {@link IsWidget#asWidget()} method
+   * must be stable. If it changes, the results are unpredictable.
+   *
+   * @param isWidget the widget to be wrapped
+   */
+  protected void initWidget(W isWidget) {
+    // Validate. Make sure the widget is not being set twice.
+    if (this.isWidget != null) {
+ throw new IllegalStateException("initWidget() may only be called once.");
+    }
+
+ // TODO rjrjr: avoids breaking some mocked unit tests, should fix the tests instead + Widget newChild = isWidget instanceof Widget ? (Widget) isWidget : isWidget.asWidget();
+
+    // Detach the new child.
+    newChild.removeFromParent();
+
+    // Use the contained widget's element as the composite's element,
+    // effectively merging them within the DOM.
+    setElement(newChild.getElement());
+
+    // Logical attach.
+    this.isWidget = isWidget;
+
+    // Adopt.
+    newChild.setParent(this);
+  }
+
+  /**
+   *
+   */
+  @Override
+  protected void onAttach() {
+    Widget asWidget = getWidget().asWidget();
+
+    if (!isOrWasAttached()) {
+      asWidget.sinkEvents(eventsToSink);
+      eventsToSink = -1;
+    }
+
+    asWidget.onAttach();
+
+ // Clobber the widget's call to setEventListener(), causing all events to + // be routed to this composite, which will delegate back to the widget by + // default (note: it's not necessary to clear this in onDetach(), because
+    // the widget's onDetach will do so).
+    DOM.setEventListener(getElement(), this);
+
+    // Call onLoad() directly, because we're not calling super.onAttach().
+    onLoad();
+    AttachEvent.fire(this, true);
+  }
+
+  @Override
+  protected void onDetach() {
+    try {
+      onUnload();
+      AttachEvent.fire(this, false);
+    } finally {
+ // We don't want an exception in user code to keep us from calling the
+      // super implementation (or event listeners won't get cleaned up and
+      // the attached flag will be wrong).
+      getWidget().asWidget().onDetach();
+    }
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/user/client/ui/RequiresResizeComposite.java Tue Jun 7 09:30:28 2011
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 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;
+
+/**
+ * A {@link AbstractComposite} implementation that implements {@link RequiresResize} + * and automatically delegates that interface's methods to its wrapped widget,
+ * which must itself implement {@link RequiresResize}.
+ *
+ * @param <W> the type of widget wrapped
+ */
+public abstract class RequiresResizeComposite<W extends Widget & RequiresResize> extends
+    AbstractComposite<W> implements RequiresResize {
+
+  public void onResize() {
+    getWidget().onResize();
+  }
+}
=======================================
--- /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskListView.java Wed Jun 1 11:32:36 2011 +++ /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/DesktopTaskListView.java Tue Jun 7 09:30:28 2011
@@ -22,7 +22,7 @@
 import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
 import com.google.gwt.user.cellview.client.TextColumn;
-import com.google.gwt.user.client.ui.ResizeComposite;
+import com.google.gwt.user.client.ui.RequiresResizeComposite;
 import com.google.gwt.view.client.NoSelectionModel;
 import com.google.gwt.view.client.SelectionChangeEvent;
 import com.google.gwt.view.client.SelectionModel;
@@ -33,7 +33,7 @@
 /**
  * View used to display the list of Tasks.
  */
-public class DesktopTaskListView extends ResizeComposite implements TaskListView { +public class DesktopTaskListView extends RequiresResizeComposite<DataGrid<?>> implements TaskListView {

   /**
    * Displays the list of tasks.
=======================================
--- /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/MobileWebAppShellDesktop.java Wed Jun 1 07:45:02 2011 +++ /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/desktop/MobileWebAppShellDesktop.java Tue Jun 7 09:30:28 2011
@@ -49,7 +49,7 @@
 import com.google.gwt.user.client.ui.IsWidget;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.ResizeComposite;
+import com.google.gwt.user.client.ui.RequiresResizeComposite;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
 import com.google.gwt.view.client.SelectionChangeEvent;
@@ -63,7 +63,7 @@
 /**
  * Desktop version of the UI shell.
  */
-public class MobileWebAppShellDesktop extends ResizeComposite implements MobileWebAppShell { +public class MobileWebAppShellDesktop extends RequiresResizeComposite<DockLayoutPanel> implements MobileWebAppShell {

   /**
    * CSS override used for the main menu.
@@ -71,7 +71,7 @@
   interface MainMenuStyle extends CellList.Style {
   }

- interface MobileWebAppShellDesktopUiBinder extends UiBinder<Widget, MobileWebAppShellDesktop> { + interface MobileWebAppShellDesktopUiBinder extends UiBinder<DockLayoutPanel, MobileWebAppShellDesktop> {
   }

   /**
@@ -147,7 +147,6 @@

   /**
    * Construct a new {@link MobileWebAppShellDesktop}.
-   * @param clientFactory the {@link ClientFactory} of shared resources
    */
public MobileWebAppShellDesktop(EventBus bus, final PlaceController placeController, TaskListView taskListView, TaskEditView taskEditView, TaskReadView taskReadView) {
=======================================
--- /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileWebAppShellMobile.java Wed Jun 1 07:45:02 2011 +++ /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/mobile/MobileWebAppShellMobile.java Tue Jun 7 09:30:28 2011
@@ -36,15 +36,15 @@
 import com.google.gwt.user.client.ui.DeckLayoutPanel;
 import com.google.gwt.user.client.ui.IsWidget;
 import com.google.gwt.user.client.ui.LayoutPanel;
-import com.google.gwt.user.client.ui.ResizeComposite;
+import com.google.gwt.user.client.ui.RequiresResizeComposite;
 import com.google.gwt.user.client.ui.Widget;

 /**
  * Mobile version of the UI shell.
  */
-public class MobileWebAppShellMobile extends ResizeComposite implements MobileWebAppShell {
-
- interface MobileWebAppShellMobileUiBinder extends UiBinder<Widget, MobileWebAppShellMobile> { +public class MobileWebAppShellMobile extends RequiresResizeComposite<LayoutPanel> implements MobileWebAppShell {
+
+ interface MobileWebAppShellMobileUiBinder extends UiBinder<LayoutPanel, MobileWebAppShellMobile> {
   }

   private static MobileWebAppShellMobileUiBinder uiBinder =
=======================================
--- /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/MobileWebAppShellTablet.java Wed Jun 1 07:45:02 2011 +++ /trunk/samples/mobilewebapp/src/main/java/com/google/gwt/sample/mobilewebapp/client/tablet/MobileWebAppShellTablet.java Tue Jun 7 09:30:28 2011
@@ -34,7 +34,7 @@
 import com.google.gwt.user.client.ui.DockLayoutPanel;
 import com.google.gwt.user.client.ui.IsWidget;
 import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.ResizeComposite;
+import com.google.gwt.user.client.ui.RequiresResizeComposite;
 import com.google.gwt.user.client.ui.SimplePanel;
 import com.google.gwt.user.client.ui.Widget;

@@ -43,9 +43,9 @@
  *
  * TODO(rjrjr): this thing needs a presenter. Not an activity. A presenter.
  */
-public class MobileWebAppShellTablet extends ResizeComposite implements MobileWebAppShell {
-
- interface MobileWebAppShellTabletUiBinder extends UiBinder<Widget, MobileWebAppShellTablet> { +public class MobileWebAppShellTablet extends RequiresResizeComposite<DockLayoutPanel> implements MobileWebAppShell {
+
+ interface MobileWebAppShellTabletUiBinder extends UiBinder<DockLayoutPanel, MobileWebAppShellTablet> {
   }

   private static MobileWebAppShellTabletUiBinder uiBinder =
=======================================
--- /trunk/tools/api-checker/config/gwt23_24userApi.conf Mon Jun 6 10:00:08 2011 +++ /trunk/tools/api-checker/config/gwt23_24userApi.conf Tue Jun 7 09:30:28 2011
@@ -157,3 +157,11 @@
com.google.gwt.user.client.ui.Image::prefetch(Ljava/lang/String;) OVERLOADED_METHOD_CALL com.google.gwt.user.client.ui.Image::setUrl(Ljava/lang/String;) OVERLOADED_METHOD_CALL com.google.gwt.user.client.ui.Image::setUrlAndVisibleRect(Ljava/lang/String;IIII) OVERLOADED_METHOD_CALL
+
+# Change StackLayoutPanel and TabLayoutPanel to get new superclass
+com.google.gwt.user.client.ui.StackLayoutPanel::getWidget() OVERRIDABLE_METHOD_RETURN_TYPE_CHANGE from class com.google.gwt.user.client.ui.Widget to class com.google.gwt.user.client.ui.LayoutPanel +com.google.gwt.user.client.ui.StackLayoutPanel::initWidget(Lcom/google/gwt/user/client/ui/Widget;) MISSING +com.google.gwt.user.client.ui.StackLayoutPanel::setWidget(Lcom/google/gwt/user/client/ui/Widget;) MISSING +com.google.gwt.user.client.ui.TabLayoutPanel::getWidget() OVERRIDABLE_METHOD_RETURN_TYPE_CHANGE from class com.google.gwt.user.client.ui.Widget to class com.google.gwt.user.client.ui.LayoutPanel +com.google.gwt.user.client.ui.TabLayoutPanel::initWidget(Lcom/google/gwt/user/client/ui/Widget;) MISSING +com.google.gwt.user.client.ui.TabLayoutPanel::setWidget(Lcom/google/gwt/user/client/ui/Widget;) MISSING
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/Composite.java Thu Oct 14 06:34:39 2010 +++ /trunk/user/src/com/google/gwt/user/client/ui/Composite.java Tue Jun 7 09:30:28 2011
@@ -15,115 +15,25 @@
  */
 package com.google.gwt.user.client.ui;

-import com.google.gwt.event.logical.shared.AttachEvent;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-
 /**
- * A type of widget that can wrap another widget, hiding the wrapped widget's - * methods. When added to a panel, a composite behaves exactly as if the widget
- * it wraps had been added.
- *
- * <p>
- * The composite is useful for creating a single widget out of an aggregate of
- * multiple other widgets contained in a single panel.
- * </p>
- *
- * <p>
+ * Simple extension of {@link AbstractComposite} that doesn't require type
+ * parameters. This originally was the only implementation of Composite, before + * {@link AbstractComposite} was introduced to allow strong typing and deferred
+ * construction.
+ *
  * <h3>Example</h3>
  * {@example com.google.gwt.examples.CompositeExample}
  * </p>
  */
-public abstract class Composite extends Widget {
-
-  private Widget widget;
-
-  @Override
-  public boolean isAttached() {
-    if (widget != null) {
-      return widget.isAttached();
-    }
-    return false;
-  }
-
-  @Override
-  public void onBrowserEvent(Event event) {
-    // Fire any handler added to the composite itself.
-    super.onBrowserEvent(event);
-
-    // Delegate events to the widget.
-    widget.onBrowserEvent(event);
-  }
-
+public abstract class Composite extends AbstractComposite<Widget> {
+
   /**
-   * Provides subclasses access to the topmost widget that defines this
-   * composite.
-   *
-   * @return the widget
+   * Provided for compatibility with legacy unit tests that mocked
+   * this specific method.
    */
-  protected Widget getWidget() {
-    return widget;
-  }
-
-  /**
- * Sets the widget to be wrapped by the composite. The wrapped widget must be - * set before calling any {@link Widget} methods on this object, or adding it
-   * to a panel. This method may only be called once for a given composite.
-   *
-   * @param widget the widget to be wrapped
-   */
-  protected void initWidget(Widget widget) {
-    // Validate. Make sure the widget is not being set twice.
-    if (this.widget != null) {
-      throw new IllegalStateException("Composite.initWidget() may only be "
-          + "called once.");
-    }
-
-    // Detach the new child.
-    widget.removeFromParent();
-
-    // Use the contained widget's element as the composite's element,
-    // effectively merging them within the DOM.
-    setElement(widget.getElement());
-
-    // Logical attach.
-    this.widget = widget;
-
-    // Adopt.
-    widget.setParent(this);
-  }
-
-  @Override
-  protected void onAttach() {
-    if (!isOrWasAttached()) {
-      widget.sinkEvents(eventsToSink);
-      eventsToSink = -1;
-    }
-
-    widget.onAttach();
-
- // Clobber the widget's call to setEventListener(), causing all events to - // be routed to this composite, which will delegate back to the widget by - // default (note: it's not necessary to clear this in onDetach(), because
-    // the widget's onDetach will do so).
-    DOM.setEventListener(getElement(), this);
-
-    // Call onLoad() directly, because we're not calling super.onAttach().
-    onLoad();
-    AttachEvent.fire(this, true);
-  }
-
-  @Override
-  protected void onDetach() {
-    try {
-      onUnload();
-      AttachEvent.fire(this, false);
-    } finally {
- // We don't want an exception in user code to keep us from calling the
-      // super implementation (or event listeners won't get cleaned up and
-      // the attached flag will be wrong).
-      widget.onDetach();
-    }
+  @Deprecated
+  protected void initWidget(Widget widget) {
+    super.initWidget(widget);
   }

   /**
=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/ResizeComposite.java Mon Sep 13 05:11:29 2010 +++ /trunk/user/src/com/google/gwt/user/client/ui/ResizeComposite.java Tue Jun 7 09:30:28 2011
@@ -19,7 +19,9 @@
* A {@link Composite} implementation that implements {@link RequiresResize} and * automatically delegates that interface's methods to its wrapped widget, which
  * must itself implement {@link RequiresResize}.
+ * @deprecated Use {@link RequiresResizeComposite}
  */
+@Deprecated
 public abstract class ResizeComposite extends Composite implements
     RequiresResize {

=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/StackLayoutPanel.java Thu Feb 17 05:39:09 2011 +++ /trunk/user/src/com/google/gwt/user/client/ui/StackLayoutPanel.java Tue Jun 7 09:30:28 2011
@@ -95,7 +95,7 @@
  * &lt;/g:StackLayoutPanel>
  * </pre>
  */
-public class StackLayoutPanel extends ResizeComposite implements HasWidgets, +public class StackLayoutPanel extends RequiresResizeComposite<LayoutPanel> implements HasWidgets,
     ProvidesResize, IndexedPanel.ForIsWidget, AnimatedLayout,
     HasBeforeSelectionHandlers<Integer>, HasSelectionHandlers<Integer> {

=======================================
--- /trunk/user/src/com/google/gwt/user/client/ui/TabLayoutPanel.java Thu Mar 3 09:02:50 2011 +++ /trunk/user/src/com/google/gwt/user/client/ui/TabLayoutPanel.java Tue Jun 7 09:30:28 2011
@@ -94,7 +94,7 @@
  * &lt;/g:TabLayoutPanel>
  * </pre>
  */
-public class TabLayoutPanel extends ResizeComposite implements HasWidgets,
+public class TabLayoutPanel extends RequiresResizeComposite<LayoutPanel> implements HasWidgets,
     ProvidesResize, IndexedPanel.ForIsWidget, AnimatedLayout,
     HasBeforeSelectionHandlers<Integer>, HasSelectionHandlers<Integer> {

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to