Adding MultiSelectionModel#clear() to clear all selected values. This is slightly more complicated because we resolveChanges() in a finally command, but the JavaDoc explains how we handle this.

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

Review by: rchandia@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9201 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/view/client/MultiSelectionModel.java b/user/src/com/google/gwt/view/client/MultiSelectionModel.java
index 97c9145..2278cfe 100644
--- a/user/src/com/google/gwt/view/client/MultiSelectionModel.java
+++ b/user/src/com/google/gwt/view/client/MultiSelectionModel.java
@@ -52,6 +52,25 @@
   }
 
   /**
+   * Deselect all selected values.
+   */
+  public void clear() {
+    // Clear the current list of pending changes. 
+    selectionChanges.clear();
+
+    /*
+     * Add a pending change to deselect each value that is currently selected.
+     * We cannot just clear the selected set, because then we would not know
+     * which values were selected before we cleared, which we need to know to
+     * determine if we should fire an event.
+     */
+    for (T value : selectedSet.values()) {
+      selectionChanges.put(value, false);
+    }
+    scheduleSelectionChangeEvent();
+  }
+
+  /**
    * Get the set of selected items as a copy.
    *
    * @return the set of selected items
diff --git a/user/test/com/google/gwt/view/client/AbstractSelectionModelTest.java b/user/test/com/google/gwt/view/client/AbstractSelectionModelTest.java
index 3b98b65..1729795 100644
--- a/user/test/com/google/gwt/view/client/AbstractSelectionModelTest.java
+++ b/user/test/com/google/gwt/view/client/AbstractSelectionModelTest.java
@@ -27,16 +27,24 @@
   /**
    * A mock {@link SelectionChangeEvent.Handler} used for testing.
    */
-  private static class MockSelectionChangeHandler
+  static class MockSelectionChangeHandler
       implements SelectionChangeEvent.Handler {
 
     private boolean eventFired;
 
+    /**
+     * Assert that a {@link SelectionChangeEvent} was fired and clear the
+     * boolean.
+     * 
+     * @param expected the expected value
+     */
     public void assertEventFired(boolean expected) {
       assertEquals(expected, eventFired);
+      eventFired = false;
     }
 
     public void onSelectionChange(SelectionChangeEvent event) {
+      assertFalse(eventFired);
       eventFired = true;
     }
   }
diff --git a/user/test/com/google/gwt/view/client/MultiSelectionModelTest.java b/user/test/com/google/gwt/view/client/MultiSelectionModelTest.java
index 61f5c28..3b7ab88 100644
--- a/user/test/com/google/gwt/view/client/MultiSelectionModelTest.java
+++ b/user/test/com/google/gwt/view/client/MultiSelectionModelTest.java
@@ -23,6 +23,67 @@
  */
 public class MultiSelectionModelTest extends AbstractSelectionModelTest {
 
+  public void testClear() {
+    MultiSelectionModel<String> model = createSelectionModel(null);
+    MockSelectionChangeHandler handler = new MockSelectionChangeHandler();
+    model.addSelectionChangeHandler(handler);
+
+    // Select a few values.
+    model.setSelected("test0", true);
+    model.setSelected("test1", true);
+    model.setSelected("test2", true);
+    assertTrue(model.isSelected("test0"));
+    handler.assertEventFired(true);
+
+    // Clear selection and verify that an event is fired.
+    model.clear();
+    assertFalse(model.isSelected("test"));
+    handler.assertEventFired(true);
+  }
+
+  /**
+   * Clearing an empty {@link MultiSelectionModel} should not fire an event,
+   * even if there are pending changes.
+   */
+  public void testClearWhenEmpty() {
+    MultiSelectionModel<String> model = createSelectionModel(null);
+    MockSelectionChangeHandler handler = new MockSelectionChangeHandler();
+    model.addSelectionChangeHandler(handler);
+
+    // Add a pending change.
+    model.setSelected("test", true);
+
+    // Clear selection and verify that no event is fired.
+    model.clear();
+    assertFalse(model.isSelected("test"));
+    handler.assertEventFired(false);
+  }
+
+  /**
+   * Pending changes should apply after the list is cleared. An event should not
+   * be fired if all selected values are reselected.
+   */
+  public void testClearAndReselect() {
+    MultiSelectionModel<String> model = createSelectionModel(null);
+    MockSelectionChangeHandler handler = new MockSelectionChangeHandler();
+    model.addSelectionChangeHandler(handler);
+
+    // Select a few values.
+    model.setSelected("test0", true);
+    model.setSelected("test1", true);
+    model.setSelected("test2", true);
+    assertTrue(model.isSelected("test0"));
+    handler.assertEventFired(true);
+
+    // Clear selection and reselect.  Verify that no event is fired.
+    model.clear();
+    model.setSelected("test0", true);
+    model.setSelected("test1", true);
+    model.setSelected("test2", true);
+    assertTrue(model.isSelected("test0"));
+    handler.assertEventFired(false);
+  }
+
   public void testGetSelectedSet() {
     MultiSelectionModel<String> model = createSelectionModel(null);
     Set<String> selected = new HashSet<String>();