Adds some more visual tests and some helper methods to create more visual visual
tests still. 
Review by:jlabanca


git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4716 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/reference/code-museum/src/com/google/gwt/museum/DefaultMuseum.gwt.xml b/reference/code-museum/src/com/google/gwt/museum/DefaultMuseum.gwt.xml
index cee0aa1..cb8cede 100644
--- a/reference/code-museum/src/com/google/gwt/museum/DefaultMuseum.gwt.xml
+++ b/reference/code-museum/src/com/google/gwt/museum/DefaultMuseum.gwt.xml
@@ -4,5 +4,5 @@
     <inherits name='com.google.gwt.museum.Museum'/>
     <source path="client/defaultmuseum"/>
       <!-- Specify the app entry point class.                   -->
-    <entry-point class='com.google.gwt.museum.client.defaultmuseum.Issue3190'/>
+    <entry-point class='com.google.gwt.museum.client.defaultmuseum.DefaultMuseum'/>
  </module>
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/common/ControlInputPanel.java b/reference/code-museum/src/com/google/gwt/museum/client/common/ControlInputPanel.java
index d537fb2..c6f7516 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/common/ControlInputPanel.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/common/ControlInputPanel.java
@@ -16,6 +16,7 @@
 

 package com.google.gwt.museum.client.common;

 

+import com.google.gwt.core.client.GWT;

 import com.google.gwt.user.client.ui.Composite;

 import com.google.gwt.user.client.ui.FlexTable;

 import com.google.gwt.user.client.ui.HasText;

@@ -37,9 +38,8 @@
     protected V value;

     protected W widget;

 

-    protected Input(String name, V defaultValue) {

+    protected Input(String name) {

       this.name = name;

-      this.value = defaultValue;

       this.widget = createInputWidget();

     }

 

@@ -73,9 +73,16 @@
 

   public static class IntegerInput extends Input<Integer, TextBox> {

     public IntegerInput(String name, int defaultValue, ControlInputPanel p) {

-      super(name, defaultValue);

+      this(name, defaultValue, defaultValue, p);

+    }

+

+    public IntegerInput(String name, int defaultHostedValue,

+        int defaultWebValue, ControlInputPanel p) {

+      super(name);

+

+      this.value = GWT.isScript() ? defaultWebValue : defaultHostedValue;

       p.add(this);

-      widget.setText(String.valueOf(defaultValue));

+      widget.setText(value.toString());

     }

 

     @Override

@@ -93,7 +100,7 @@
     initWidget(layout);

   }

 

-  private void add(Input input) {

+  private void add(Input<?, ?> input) {

     layout.setText(0, numInputs, input.getName());

     layout.setWidget(1, numInputs, input.widget);

   }

diff --git a/reference/code-museum/src/com/google/gwt/museum/client/common/EventReporter.java b/reference/code-museum/src/com/google/gwt/museum/client/common/EventReporter.java
index 9790aad..df9121f 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/common/EventReporter.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/common/EventReporter.java
@@ -24,6 +24,7 @@
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.FocusEvent;
 import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
 import com.google.gwt.event.dom.client.KeyDownEvent;
 import com.google.gwt.event.dom.client.KeyDownHandler;
 import com.google.gwt.event.dom.client.KeyPressEvent;
@@ -36,15 +37,16 @@
 import com.google.gwt.event.logical.shared.SelectionHandler;
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.ui.ChangeListener;
 import com.google.gwt.user.client.ui.CheckBox;
 import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.FocusListener;
 import com.google.gwt.user.client.ui.HasHTML;
 import com.google.gwt.user.client.ui.HasText;
+import com.google.gwt.user.client.ui.HasWidgets;
 import com.google.gwt.user.client.ui.KeyboardListener;
 import com.google.gwt.user.client.ui.MouseListener;
-import com.google.gwt.user.client.ui.Panel;
 import com.google.gwt.user.client.ui.SuggestionEvent;
 import com.google.gwt.user.client.ui.SuggestionHandler;
 import com.google.gwt.user.client.ui.UIObject;
@@ -73,7 +75,9 @@
       ValueChangeHandler<Boolean> {
     String name;
 
-    public CheckBoxEvent(String name, Panel p) {
+    private HandlerRegistration registration;
+
+    public CheckBoxEvent(String name, HasWidgets p) {
       this.name = name;
       this.setText(name);
       p.add(this);
@@ -81,25 +85,78 @@
       this.setValue(true, true);
     }
 
-    public abstract void addHandler();
+    public abstract HandlerRegistration addHandler();
 
     public void onValueChange(ValueChangeEvent<Boolean> event) {
       if (event.getValue().booleanValue()) {
         report("add " + name);
-        addHandler();
+        registration = addHandler();
       } else {
         report("remove " + name);
         removeHandler();
       }
     }
 
-    public abstract void removeHandler();
+    public void removeHandler() {
+      registration.removeHandler();
+      registration = null;
+    }
   }
 
-  public EventReporter(Panel parent) {
+  /**
+   * Add/remove handlers via check box.
+   * 
+   */
+  public abstract class CheckBoxListener extends CheckBox implements
+      ValueChangeHandler<Boolean> {
+    String name;
+
+    public CheckBoxListener(String name, HasWidgets p) {
+      this.name = name;
+      this.setText(name);
+      p.add(this);
+      this.addValueChangeHandler(this);
+      this.setValue(true, true);
+    }
+
+    public abstract void addListener();
+
+    public void onValueChange(ValueChangeEvent<Boolean> event) {
+      if (event.getValue().booleanValue()) {
+        report("add " + name);
+        addListener();
+      } else {
+        report("remove " + name);
+        removeListener();
+      }
+    }
+
+    public abstract void removeListener();
+  }
+
+  public EventReporter() {
+  }
+
+  public EventReporter(HasWidgets parent) {
     parent.add(this);
   }
 
+  public void addClickHandler(final HasClickHandlers h, HasWidgets p) {
+    addClickHandler(h, p, getInfo(h) + " click handler");
+  }
+
+  public void addClickHandler(final HasClickHandlers h, HasWidgets p,
+      String title) {
+
+    new CheckBoxEvent(title, p) {
+      @Override
+      public HandlerRegistration addHandler() {
+        return h.addClickHandler(EventReporter.this);
+      }
+    };
+  }
+
+  @Override
   public String getInfo(Object sender) {
     if (sender instanceof HasText) {
       return ((HasText) sender).getText();
@@ -121,7 +178,6 @@
     report(event);
   }
 
-  @SuppressWarnings("deprecation")
   public void onChange(Widget sender) {
     report("change on " + getInfo(sender));
   }
@@ -130,7 +186,6 @@
     report(event);
   }
 
-  @SuppressWarnings("deprecation")
   public void onClick(Widget sender) {
     report("click: " + getInfo(sender));
   }
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/common/SimpleLayout.java b/reference/code-museum/src/com/google/gwt/museum/client/common/SimpleLayout.java
new file mode 100644
index 0000000..2a82ea1
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/common/SimpleLayout.java
@@ -0,0 +1,108 @@
+/*

+ * 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.museum.client.common;

+

+import com.google.gwt.user.client.ui.CaptionPanel;

+import com.google.gwt.user.client.ui.Composite;

+import com.google.gwt.user.client.ui.HasWidgets;

+import com.google.gwt.user.client.ui.HorizontalPanel;

+import com.google.gwt.user.client.ui.VerticalPanel;

+import com.google.gwt.user.client.ui.Widget;

+

+import java.util.Iterator;

+

+/**

+ * Helper class to avoid manually assembling vertical and horizontal panels for

+ * these tests. It acts like a "typewriter" layout.

+ * 

+ * So, for instance

+ * <pre>

+ *   // assume the existence of widgets a-z

+ *   SimpleLayout layout = new SimpleLayout();

+ *   layout.add(a);

+ *   layout.add(b);

+ *   layout.nextRow();

+ *   layout.add(c);

+ *   layout.nextRow();

+ *   layout.add(d);

+ *   layout.add(e);

+ *</pre>

+ * 

+ * would be rendered as:

+ * <pre>

+ *  a b 

+ *  c 

+ *  d e

+ *  </pre>

+ * */

+public class SimpleLayout extends Composite implements HasWidgets {

+

+  private final VerticalPanel master = new VerticalPanel();

+  private VerticalPanel allRows = new VerticalPanel();

+  private HorizontalPanel currentRow;

+

+  public SimpleLayout() {

+    initWidget(master);

+    master.add(allRows);

+    nextRow();

+  }

+

+  /**

+   * Adds a widget to the current row with the given caption.

+   */

+  public void add(String caption, Widget w) {

+    CaptionPanel c = new CaptionPanel(caption);

+    c.add(w);

+    add(c);

+  }

+

+  /**

+   * Adds a widget to the current row.

+   */

+  public void add(Widget w) {

+    currentRow.add(w);

+  }

+

+  /**

+   * Adds a footer to this layout table, the footer is guaranteed to be beneath

+   * all the rows.

+   */

+  public void addFooter(Widget w) {

+    master.add(w);

+  }

+

+  public void clear() {

+    master.clear();

+  }

+

+  public Iterator<Widget> iterator() {

+    return master.iterator();

+  }

+

+  /**

+   * Creates another row. After creating this row, all widgets added using

+   * {@link #add(Widget)} and {@link #add(String, Widget)} will be added to the

+   * new row.

+   */

+  public void nextRow() {

+    currentRow = new HorizontalPanel();

+    allRows.add(currentRow);

+  }

+

+  public boolean remove(Widget w) {

+    return master.remove(w);

+  }

+}

diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/SpeedForClippedImageLoading.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/SpeedForClippedImageLoading.java
new file mode 100644
index 0000000..f4dea21
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/SpeedForClippedImageLoading.java
@@ -0,0 +1,104 @@
+/*

+ * 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.museum.client.defaultmuseum;

+

+import com.google.gwt.core.client.Duration;

+import com.google.gwt.core.client.GWT;

+import com.google.gwt.event.dom.client.ClickEvent;

+import com.google.gwt.event.dom.client.ClickHandler;

+import com.google.gwt.event.dom.client.LoadEvent;

+import com.google.gwt.event.dom.client.LoadHandler;

+import com.google.gwt.museum.client.common.AbstractIssue;

+import com.google.gwt.museum.client.common.ControlInputPanel;

+import com.google.gwt.museum.client.common.SimpleLogger;

+import com.google.gwt.museum.client.common.ControlInputPanel.IntegerInput;

+import com.google.gwt.user.client.ui.Button;

+import com.google.gwt.user.client.ui.Image;

+import com.google.gwt.user.client.ui.RootPanel;

+import com.google.gwt.user.client.ui.TreeImages;

+import com.google.gwt.user.client.ui.VerticalPanel;

+import com.google.gwt.user.client.ui.Widget;

+

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * Tests the speed of clipped images.

+ * 

+ */

+public class SpeedForClippedImageLoading extends AbstractIssue {

+  private SimpleLogger log = new SimpleLogger();

+  List<Image> images = new ArrayList<Image>();

+

+  @Override

+  public Widget createIssue() {

+    VerticalPanel v = new VerticalPanel();

+    ControlInputPanel p = new ControlInputPanel();

+    v.add(p);

+    v.add(log);

+    final IntegerInput size = new IntegerInput("how many clipped images", 10,

+        30, p);

+

+    Button createClippedImages = new Button("time the creation",

+        new ClickHandler() {

+          boolean firstTime = true;

+

+          public void onClick(ClickEvent event) {

+            final Duration d = new Duration();

+

+            final int numImages = size.getValue();

+            final TreeImages test = GWT.<TreeImages> create(TreeImages.class);

+

+            for (int i = 0; i < numImages; i++) {

+              Image current = test.treeClosed().createImage();

+

+              if (i == numImages - 1) {

+                current.addLoadHandler(new LoadHandler() {

+                  public void onLoad(LoadEvent event) {

+                    if (firstTime) {

+                      log.report("Took " + d.elapsedMillis()

+                          + " milliseconds to create the images");

+                    }

+                    firstTime = false;

+                  }

+                });

+              }

+              images.add(current);

+              RootPanel.get().add(current);

+            }

+          }

+        });

+

+    v.add(createClippedImages);

+    return v;

+  }

+

+  @Override

+  public String getInstructions() {

+    return "IE has traditionally been very slow compared to the other browsers,  this speed test in intended to allow us to capture and document improvements in the speed of clipped images";

+  }

+

+  @Override

+  public String getSummary() {

+    return "clear() speed check";

+  }

+

+  @Override

+  public boolean hasCSS() {

+    return false;

+  }

+

+}

diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForCustomButtons.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForCustomButtons.java
new file mode 100644
index 0000000..7cf7229
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForCustomButtons.java
@@ -0,0 +1,73 @@
+/*

+ * 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.museum.client.defaultmuseum;

+

+import com.google.gwt.museum.client.common.AbstractIssue;

+import com.google.gwt.museum.client.common.EventReporter;

+import com.google.gwt.museum.client.common.SimpleLayout;

+import com.google.gwt.user.client.ui.PushButton;

+import com.google.gwt.user.client.ui.ToggleButton;

+import com.google.gwt.user.client.ui.Tree;

+import com.google.gwt.user.client.ui.Widget;

+

+/**

+ * Visual test for custom buttons.

+ */

+public class VisualsForCustomButtons extends AbstractIssue {

+

+  @Override

+  public Widget createIssue() {

+    SimpleLayout l = new SimpleLayout();

+    Tree t = new Tree();

+    PushButton a = new PushButton("Simple-dum");

+    t.add(a);

+    PushButton a2 = new PushButton("Simple-dee");

+    t.add(a2);

+    PushButton aUp = new PushButton("A-up");

+    aUp.getDownFace().setHTML("A-down");

+    t.add(aUp);

+

+    ToggleButton b = new ToggleButton("B");

+    t.add(b);

+    l.add(t);

+    l.nextRow();

+    EventReporter<Object, Object> handler = new EventReporter<Object, Object>();

+    l.addFooter(handler);

+    handler.addClickHandler(a, l);

+    handler.addClickHandler(a2, l);

+    handler.addClickHandler(aUp, l);

+    handler.addClickHandler(b, l);

+

+    return l;

+  }

+

+  @Override

+  public String getInstructions() {

+    return "Check for custom buttons";

+  }

+

+  @Override

+  public String getSummary() {

+    return "CustomButton visual test";

+  }

+

+  @Override

+  public boolean hasCSS() {

+

+    return false;

+  }

+

+}

diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBox.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBox.java
index b7d0f78..2c7c111 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBox.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBox.java
@@ -15,6 +15,8 @@
  */

 package com.google.gwt.museum.client.defaultmuseum;

 

+import com.google.gwt.dom.client.Document;

+import com.google.gwt.dom.client.Element;

 import com.google.gwt.event.dom.client.ClickEvent;

 import com.google.gwt.event.dom.client.ClickHandler;

 import com.google.gwt.event.dom.client.MouseDownEvent;

@@ -40,6 +42,8 @@
   MultiWordSuggestOracle girlsNames = new MultiWordSuggestOracle();

   MultiWordSuggestOracle girlsNamesWithDefault = new MultiWordSuggestOracle();

 

+  Element textBoxToWrap;

+

   VisualsForSuggestBox() {

     List<String> femaleNames = Arrays.asList("Jamie", "Jill", "Jackie",

         "Susan", "Helen", "Emily", "Karen", "Emily", "Isabella", "Emma", "Ava",

@@ -59,8 +63,14 @@
   /**

    * This is the entry point method.

    */

+  @Override

   public Widget createIssue() {

     VerticalPanel panel = new VerticalPanel();

+    HTML wrapperText = new HTML(

+        "Make sure this wrapped suggest box works as normal.");

+    panel.add(wrapperText);

+    textBoxToWrap = Document.get().createTextInputElement();

+    wrapperText.getElement().appendChild(textBoxToWrap);

 

     panel.add(new HTML(

         "Select the show button, nothing should open <br/> Type 'e' and select the button again, now a suggestion list should open and close."));

@@ -112,7 +122,6 @@
   }

 

   private SuggestBox simpleSuggestBox() {

-

     SuggestBox b = new SuggestBox(girlsNames);

     return b;

   }

diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBoxEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBoxEvents.java
index 70ab7ad..d96eac9 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBoxEvents.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBoxEvents.java
@@ -93,40 +93,35 @@
         report);
 
     handler.new CheckBoxEvent("KeyDown", p) {
-      HandlerRegistration reg;
-      @Override
-      public void addHandler() {
-        reg = b.addKeyDownHandler(handler);
-      }
 
       @Override
-      public void removeHandler() {
-        reg.removeHandler();
-        reg = null;
+      public HandlerRegistration addHandler() {
+        return b.addKeyDownHandler(handler);
       }
+
     };
 
-    handler.new CheckBoxEvent("ChangeListener", p) {
+    handler.new CheckBoxListener("ChangeListener", p) {
 
       @Override
-      public void addHandler() {
+      public void addListener() {
         b.addChangeListener(handler);
       }
 
       @Override
-      public void removeHandler() {
+      public void removeListener() {
         b.removeChangeListener(handler);
       }
     };
-    handler.new CheckBoxEvent("Suggestion listener", p) {
+    handler.new CheckBoxListener("Suggestion listener", p) {
 
       @Override
-      public void addHandler() {
+      public void addListener() {
         b.addEventHandler(handler);
       }
 
       @Override
-      public void removeHandler() {
+      public void removeListener() {
         b.removeEventHandler(handler);
       }
     };
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForWindowEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForWindowEvents.java
index 56fffb6..dcb7019 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForWindowEvents.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForWindowEvents.java
@@ -24,12 +24,14 @@
 import com.google.gwt.event.logical.shared.ResizeHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.museum.client.common.SimpleLogger;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.Window.ClosingEvent;
 import com.google.gwt.user.client.Window.ScrollEvent;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwt.user.client.ui.Widget;
 
 import java.util.ArrayList;
@@ -41,15 +43,16 @@
     CloseHandler<Window>, Window.ClosingHandler, Window.ScrollHandler,
     ResizeHandler {
   static int numResizes = 0;
-
+  private SimpleLogger messages = new SimpleLogger();
   private ArrayList<HandlerRegistration> registrations = new ArrayList<HandlerRegistration>();
-  private FlowPanel messages = new FlowPanel();
 
   @Override
   public Widget createIssue() {
     FlowPanel out = new FlowPanel();
 
     FlowPanel body = new FlowPanel();
+
+    body.setHeight(Window.getClientHeight() * 2 + "px");
     FlowPanel buttons = new FlowPanel();
 
     Button addHandlersButton = new Button("Add window handlers.");
@@ -66,19 +69,19 @@
       }
     });
 
-    Button clearButton = new Button("Clear events");
-    clearButton.addClickHandler(new ClickHandler() {
-      public void onClick(ClickEvent event) {
-        messages.clear();
-      }
-    });
-
     buttons.add(addHandlersButton);
     buttons.add(removeHandlersButton);
-    buttons.add(clearButton);
 
     body.add(buttons);
     body.add(messages);
+    ScrollPanel p = new ScrollPanel();
+    p.setHeight("100%");
+    p.setWidth("100%");
+    HTML tester = new HTML("scroller");
+    tester.setHeight("500px");
+    tester.getElement().getStyle().setProperty("border", "10px solid green");
+    p.add(tester);
+    body.add(p);
 
     out.add(body);
 
@@ -110,7 +113,8 @@
   }
 
   public void onResize(ResizeEvent event) {
-    Window.setTitle("Got resize " + numResizes++);
+    messages.report("Got resize " + numResizes++ + " with values "
+        + event.getWidth() + ", " + event.getHeight());
   }
 
   public void onWindowClosing(ClosingEvent event) {
@@ -118,23 +122,27 @@
   }
 
   public void onWindowScroll(ScrollEvent event) {
-    addMessage("Got a window scroll!");
+    addMessage("Got a window scroll with " + event.getScrollLeft() + ", "
+        + event.getScrollTop());
   }
 
   private void addMessage(String msg) {
-    messages.add(new Label(msg));
+    messages.report(msg);
   }
 
   private void removeWindowHandlers() {
     for (HandlerRegistration reg : registrations) {
       reg.removeHandler();
     }
+    registrations.clear();
   }
 
   private void setupWindowHandlers() {
-    registrations.add(Window.addCloseHandler(this));
-    registrations.add(Window.addResizeHandler(this));
-    registrations.add(Window.addWindowClosingHandler(this));
-    registrations.add(Window.addWindowScrollHandler(this));
+    if (registrations.size() == 0) {
+      registrations.add(Window.addCloseHandler(this));
+      registrations.add(Window.addResizeHandler(this));
+      registrations.add(Window.addWindowClosingHandler(this));
+      registrations.add(Window.addWindowScrollHandler(this));
+    }
   }
 }
\ No newline at end of file