Changes required to make the Scaffold app look like the mocks. Added null checks AbstractProxyListActivity to prevent NPEs. Relaxed the CellTable used in AbstractProxyListView to be any HasData and added a protected method that takes a HasData instead of a CellTable. Fixed a bug in SingleSelectionModel where setting the selected value to null would cause an infinite loop.

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

Review by: rjrjr@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8886 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/app/place/AbstractProxyListActivity.java b/user/src/com/google/gwt/app/place/AbstractProxyListActivity.java
index 359571f..96f0956 100644
--- a/user/src/com/google/gwt/app/place/AbstractProxyListActivity.java
+++ b/user/src/com/google/gwt/app/place/AbstractProxyListActivity.java
@@ -253,6 +253,10 @@
     fireCountRequest(new Receiver<Long>() {
       @Override
       public void onSuccess(Long response) {
+        if (view == null) {
+          // This activity is dead
+          return;
+        }
         HasData<P> table = getView().asHasData();
         int rows = response.intValue();
         table.setRowCount(rows, true);
@@ -274,6 +278,10 @@
     fireCountRequest(new Receiver<Long>() {
       @Override
       public void onSuccess(Long response) {
+        if (view == null) {
+          // This activity is dead
+          return;
+        }
         getView().asHasData().setRowCount(response.intValue(), true);
         onRangeChanged(view.asHasData());
       }
diff --git a/user/src/com/google/gwt/app/place/AbstractProxyListView.java b/user/src/com/google/gwt/app/place/AbstractProxyListView.java
index 244d3fd..e8e2aa7 100644
--- a/user/src/com/google/gwt/app/place/AbstractProxyListView.java
+++ b/user/src/com/google/gwt/app/place/AbstractProxyListView.java
@@ -44,12 +44,12 @@
 public abstract class AbstractProxyListView<P extends EntityProxy> extends
     Composite implements ProxyListView<P> {
 
-  private CellTable<P> table;
+  private HasData<P> display;
   private Set<String> paths = new HashSet<String>();
   private Delegate<P> delegate;
 
   public HasData<P> asHasData() {
-    return table;
+    return display;
   }
 
   @Override
@@ -65,14 +65,13 @@
     this.delegate = delegate;
   }
 
-  protected void init(Widget root, CellTable<P> table, Button newButton,
-      List<PropertyColumn<P, ?>> columns) {
+  protected void init(Widget root, HasData<P> display, Button newButton,
+      Set<String> columns) {
     super.initWidget(root);
-    this.table = table;
+    this.display = display;
 
-    for (PropertyColumn<P, ?> column : columns) {
-      table.addColumn(column, column.getDisplayName());
-      paths.addAll(Arrays.asList(column.getPaths()));
+    if (columns != null && columns.size() > 0) {
+      paths.addAll(columns);
     }
 
     newButton.addClickHandler(new ClickHandler() {
@@ -82,6 +81,21 @@
     });
   }
 
+  /**
+   * @deprecated use {@link #init(Widget, HasData, Button, Set)} instead
+   */
+  @Deprecated
+  protected void init(Widget root, CellTable<P> table, Button newButton,
+      List<PropertyColumn<P, ?>> columns) {
+    Set<String> cols = new HashSet<String>(); 
+    for (PropertyColumn<P, ?> column : columns) {
+      table.addColumn(column, column.getDisplayName());
+      cols.addAll(Arrays.asList(column.getPaths()));
+    }
+
+    this.init(root, table, newButton, cols);
+  }
+
   @Override
   protected void initWidget(Widget widget) {
     throw new UnsupportedOperationException(
diff --git a/user/test/com/google/gwt/view/client/SingleSelectionModelTest.java b/user/test/com/google/gwt/view/client/SingleSelectionModelTest.java
index 7682268..77825e9 100644
--- a/user/test/com/google/gwt/view/client/SingleSelectionModelTest.java
+++ b/user/test/com/google/gwt/view/client/SingleSelectionModelTest.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2010 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
@@ -43,7 +43,7 @@
     delayTestFinish(2000);
     model.setSelected("test", true);
   }
-  
+
   public void testNoDuplicateChangeEvent() {
     SingleSelectionModel<String> model = createSelectionModel(null);
     SelectionChangeEvent.Handler handler = new SelectionChangeEvent.Handler() {
@@ -57,7 +57,7 @@
     model.setSelected("test", true); // Should not fire change event
     model.setSelected("test", true); // Should not fire change event
   }
-  
+
   public void testNoDuplicateChangeEvent2() {
     SingleSelectionModel<String> model = createSelectionModel(null);
     SelectionChangeEvent.Handler handler = new SelectionChangeEvent.Handler() {
@@ -89,6 +89,19 @@
     assertFalse(model.isSelected("test0"));
   }
 
+  public void testSetSelectedNull() {
+    SingleSelectionModel<String> model = createSelectionModel(null);
+
+    model.setSelected("test", true);
+    assertTrue(model.isSelected("test"));
+
+    // Null cannot be selected, but it deselects the current item.
+    model.setSelected(null, true);
+    assertNull(model.getSelectedObject());
+    assertFalse(model.isSelected("test"));
+    assertFalse(model.isSelected(null));
+  }
+
   public void testSetSelectedWithKeyProvider() {
     ProvidesKey<String> keyProvider = new ProvidesKey<String>() {
       public Object getKey(String item) {