DefaultSelectionModel#setSelected currently adds an exception even if the default selection state equals the specified state. Also adds test cases for all selection models.
Review at http://gwt-code-reviews.appspot.com/658801
Review by: jgw@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8321 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/view/client/DefaultSelectionModel.java b/user/src/com/google/gwt/view/client/DefaultSelectionModel.java
index 4284be8..285a1b4 100644
--- a/user/src/com/google/gwt/view/client/DefaultSelectionModel.java
+++ b/user/src/com/google/gwt/view/client/DefaultSelectionModel.java
@@ -73,12 +73,11 @@
*/
public void setSelected(T object, boolean selected) {
Object key = getKey(object);
- Boolean currentlySelected = exceptions.get(key);
- if (currentlySelected != null
- && currentlySelected.booleanValue() != selected) {
- exceptions.remove(key);
- } else {
+ if (isDefaultSelected(object) != selected) {
+ // If the state is different than the default state, add an exception.
exceptions.put(key, selected);
+ } else {
+ exceptions.remove(key);
}
scheduleSelectionChangeEvent();
diff --git a/user/src/com/google/gwt/view/client/SelectionModel.java b/user/src/com/google/gwt/view/client/SelectionModel.java
index 88a0da6..8ae0df6 100644
--- a/user/src/com/google/gwt/view/client/SelectionModel.java
+++ b/user/src/com/google/gwt/view/client/SelectionModel.java
@@ -111,6 +111,11 @@
private final HandlerManager handlerManager = new HandlerManager(this);
/**
+ * Set to true if the next scheduled event should be cancelled.
+ */
+ private boolean isEventCancelled;
+
+ /**
* Set to true if an event is scheduled to be fired.
*/
private boolean isEventScheduled;
@@ -146,17 +151,29 @@
this.keyProvider = keyProvider;
}
+ protected void fireSelectionChangeEvent() {
+ if (isEventScheduled) {
+ isEventCancelled = true;
+ }
+ SelectionChangeEvent.fire(AbstractSelectionModel.this);
+ }
+
/**
* Schedules a {@link SelectionModel.SelectionChangeEvent} to fire at the
* end of the current event loop.
*/
protected void scheduleSelectionChangeEvent() {
+ isEventCancelled = false;
if (!isEventScheduled) {
isEventScheduled = true;
Scheduler.get().scheduleFinally(new ScheduledCommand() {
public void execute() {
isEventScheduled = false;
- SelectionChangeEvent.fire(AbstractSelectionModel.this);
+ if (isEventCancelled) {
+ isEventCancelled = false;
+ return;
+ }
+ fireSelectionChangeEvent();
}
});
}
diff --git a/user/test/com/google/gwt/view/ViewSuite.java b/user/test/com/google/gwt/view/ViewSuite.java
new file mode 100644
index 0000000..07fa087
--- /dev/null
+++ b/user/test/com/google/gwt/view/ViewSuite.java
@@ -0,0 +1,47 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.view;
+
+import com.google.gwt.junit.tools.GWTTestSuite;
+import com.google.gwt.view.client.AbstractListViewAdapterTest;
+import com.google.gwt.view.client.AbstractSelectionModelTest;
+import com.google.gwt.view.client.AsyncListViewAdapterTest;
+import com.google.gwt.view.client.DefaultNodeInfoTest;
+import com.google.gwt.view.client.DefaultSelectionModelTest;
+import com.google.gwt.view.client.MultiSelectionModelTest;
+import com.google.gwt.view.client.RangeTest;
+import com.google.gwt.view.client.SingleSelectionModelTest;
+
+import junit.framework.Test;
+
+/**
+ * Tests of the view package.
+ */
+public class ViewSuite {
+ public static Test suite() {
+ GWTTestSuite suite = new GWTTestSuite("Test suite for all view classes");
+
+ suite.addTestSuite(AbstractListViewAdapterTest.class);
+ suite.addTestSuite(AbstractSelectionModelTest.class);
+ suite.addTestSuite(AsyncListViewAdapterTest.class);
+ suite.addTestSuite(DefaultNodeInfoTest.class);
+ suite.addTestSuite(DefaultSelectionModelTest.class);
+ suite.addTestSuite(MultiSelectionModelTest.class);
+ suite.addTestSuite(RangeTest.class);
+ suite.addTestSuite(SingleSelectionModelTest.class);
+ return suite;
+ }
+}
diff --git a/user/test/com/google/gwt/view/client/AbstractSelectionModelTest.java b/user/test/com/google/gwt/view/client/AbstractSelectionModelTest.java
new file mode 100644
index 0000000..f9a8333
--- /dev/null
+++ b/user/test/com/google/gwt/view/client/AbstractSelectionModelTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.view.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.view.client.SelectionModel.AbstractSelectionModel;
+import com.google.gwt.view.client.SelectionModel.SelectionChangeEvent;
+import com.google.gwt.view.client.SelectionModel.SelectionChangeHandler;
+
+/**
+ * Tests for {@link AbstractSelectionModel}.
+ */
+public class AbstractSelectionModelTest extends GWTTestCase {
+
+ /**
+ * A mock {@link SelectionChangeHandler} used for testing.
+ */
+ private static class MockSelectionChangeHandler implements
+ SelectionChangeHandler {
+
+ private boolean eventFired;
+
+ public void assertEventFired(boolean expected) {
+ assertEquals(expected, eventFired);
+ }
+
+ public void onSelectionChange(SelectionChangeEvent event) {
+ eventFired = true;
+ }
+ }
+
+ /**
+ * A mock {@link SelectionModel} used for testing.
+ *
+ * @param <T> the data type
+ */
+ private static class MockSelectionModel<T> extends AbstractSelectionModel<T> {
+ public boolean isSelected(T object) {
+ return false;
+ }
+
+ public void setSelected(T object, boolean selected) {
+ }
+ }
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.view.View";
+ }
+
+ public void testFireSelectionChangeEvent() {
+ AbstractSelectionModel<String> model = createSelectionModel();
+ MockSelectionChangeHandler handler = new MockSelectionChangeHandler();
+ model.addSelectionChangeHandler(handler);
+
+ model.fireSelectionChangeEvent();
+ handler.assertEventFired(true);
+ }
+
+ public void testScheduleSelectionChangeEvent() {
+ AbstractSelectionModel<String> model = createSelectionModel();
+ final MockSelectionChangeHandler handler = new MockSelectionChangeHandler() {
+ @Override
+ public void onSelectionChange(SelectionChangeEvent event) {
+ // We should only see one event fired.
+ assertEventFired(false);
+ super.onSelectionChange(event);
+ }
+ };
+ model.addSelectionChangeHandler(handler);
+
+ // Schedule the event multiple times.
+ delayTestFinish(2000);
+ model.scheduleSelectionChangeEvent();
+ model.scheduleSelectionChangeEvent();
+ model.scheduleSelectionChangeEvent();
+ model.scheduleSelectionChangeEvent();
+ model.scheduleSelectionChangeEvent();
+ model.scheduleSelectionChangeEvent();
+ handler.assertEventFired(false);
+
+ new Timer() {
+ @Override
+ public void run() {
+ handler.assertEventFired(true);
+ finishTest();
+ }
+ }.schedule(1000);
+ }
+
+ public void testSetKeyProvider() {
+ AbstractSelectionModel<String> model = createSelectionModel();
+
+ // By default, use the object as a key.
+ assertNull(model.getKeyProvider());
+ assertEquals("test", model.getKey("test"));
+ assertEquals(null, model.getKey(null));
+
+ // Defer to the key provider if one is set.
+ ProvidesKey<String> keyProvider = new ProvidesKey<String>() {
+ public Object getKey(String item) {
+ return item == null ? item : item.toUpperCase();
+ }
+ };
+ model.setKeyProvider(keyProvider);
+ assertEquals(keyProvider, model.getKeyProvider());
+ assertEquals("TEST", model.getKey("test"));
+ assertEquals(null, model.getKey(null));
+ }
+
+ protected AbstractSelectionModel<String> createSelectionModel() {
+ return new MockSelectionModel<String>();
+ }
+}
diff --git a/user/test/com/google/gwt/view/client/DefaultSelectionModelTest.java b/user/test/com/google/gwt/view/client/DefaultSelectionModelTest.java
new file mode 100644
index 0000000..247bfaa
--- /dev/null
+++ b/user/test/com/google/gwt/view/client/DefaultSelectionModelTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.view.client;
+
+import com.google.gwt.view.client.SelectionModel.SelectionChangeEvent;
+import com.google.gwt.view.client.SelectionModel.SelectionChangeHandler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tests for {@link DefaultSelectionModel}.
+ */
+public class DefaultSelectionModelTest extends AbstractSelectionModelTest {
+
+ /**
+ * A mock {@link DefaultSelectionModel} used for testing. By default, all
+ * strings that start with "selected" are selected.
+ */
+ private static class MockDefaultSelectionModel extends
+ DefaultSelectionModel<String> {
+
+ @Override
+ public boolean isDefaultSelected(String object) {
+ return object == null ? false : object.startsWith("selected");
+ }
+ }
+
+ public void testIsSelectedWithoutExceptions() {
+ DefaultSelectionModel<String> model = createSelectionModel();
+ assertFalse(model.isSelected(null));
+ assertFalse(model.isSelected("test"));
+ assertTrue(model.isSelected("selected"));
+ assertTrue(model.isSelected("selected0"));
+ }
+
+ public void testSelectedChangeEvent() {
+ DefaultSelectionModel<String> model = createSelectionModel();
+ SelectionChangeHandler handler = new SelectionChangeHandler() {
+ public void onSelectionChange(SelectionChangeEvent event) {
+ finishTest();
+ }
+ };
+ model.addSelectionChangeHandler(handler);
+
+ delayTestFinish(2000);
+ model.setSelected("test", true);
+ }
+
+ public void testSetSelectedDefault() {
+ Map<Object, Boolean> exceptions = new HashMap<Object, Boolean>();
+ DefaultSelectionModel<String> model = createSelectionModel();
+ assertTrue(model.isSelected("selected0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(0, model.getExceptions(exceptions).size());
+
+ model.setSelected("selected0", true);
+ assertTrue(model.isSelected("selected0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(0, model.getExceptions(exceptions).size());
+
+ model.setSelected("selected0", false);
+ assertFalse(model.isSelected("selected0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(1, model.getExceptions(exceptions).size());
+ assertFalse(exceptions.get("selected0"));
+
+ model.setSelected("selected0", true);
+ assertTrue(model.isSelected("selected0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(0, model.getExceptions(exceptions).size());
+ }
+
+ public void testSetSelectedNonDefault() {
+ DefaultSelectionModel<String> model = createSelectionModel();
+ assertFalse(model.isSelected("test0"));
+ assertFalse(model.isSelected("test1"));
+ assertTrue(model.isSelected("selected0"));
+
+ model.setSelected("test0", true);
+ assertTrue(model.isSelected("test0"));
+ assertFalse(model.isSelected("test1"));
+ assertTrue(model.isSelected("selected0"));
+
+ model.setSelected("test1", true);
+ assertTrue(model.isSelected("test0"));
+ assertTrue(model.isSelected("test1"));
+ assertTrue(model.isSelected("selected0"));
+
+ model.setSelected("test1", false);
+ assertTrue(model.isSelected("test0"));
+ assertFalse(model.isSelected("test1"));
+ assertTrue(model.isSelected("selected0"));
+ }
+
+ public void testSetSelectedWithKeyProvider() {
+ Map<Object, Boolean> exceptions = new HashMap<Object, Boolean>();
+ DefaultSelectionModel<String> model = createSelectionModel();
+ ProvidesKey<String> keyProvider = new ProvidesKey<String>() {
+ public Object getKey(String item) {
+ return item.toUpperCase();
+ }
+ };
+ model.setKeyProvider(keyProvider);
+ assertFalse(model.isSelected("test"));
+ assertTrue(model.isSelected("selected0"));
+ assertFalse(model.isSelected("SELECTED0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(0, model.getExceptions(exceptions).size());
+
+ model.setSelected("selected0", true);
+ assertFalse(model.isSelected("test"));
+ assertTrue(model.isSelected("selected0"));
+ assertFalse(model.isSelected("SELECTED0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(0, model.getExceptions(exceptions).size());
+
+ model.setSelected("selected0", false);
+ assertFalse(model.isSelected("test"));
+ assertFalse(model.isSelected("selected0"));
+ assertFalse(model.isSelected("SELECTED0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(1, model.getExceptions(exceptions).size());
+ assertFalse(exceptions.get("SELECTED0"));
+
+ model.setSelected("selected0", true);
+ assertFalse(model.isSelected("test"));
+ assertTrue(model.isSelected("selected0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(0, model.getExceptions(exceptions).size());
+
+ model.setSelected("test", true);
+ assertTrue(model.isSelected("test"));
+ assertTrue(model.isSelected("selected0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(1, model.getExceptions(exceptions).size());
+ assertTrue(exceptions.get("TEST"));
+
+ model.setSelected("test", false);
+ assertFalse(model.isSelected("test"));
+ assertTrue(model.isSelected("selected0"));
+ assertTrue(model.isSelected("selected1"));
+ assertEquals(0, model.getExceptions(exceptions).size());
+ }
+
+ @Override
+ protected DefaultSelectionModel<String> createSelectionModel() {
+ return new MockDefaultSelectionModel();
+ }
+}
diff --git a/user/test/com/google/gwt/view/client/MultiSelectionModelTest.java b/user/test/com/google/gwt/view/client/MultiSelectionModelTest.java
new file mode 100644
index 0000000..449e04d
--- /dev/null
+++ b/user/test/com/google/gwt/view/client/MultiSelectionModelTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.view.client;
+
+import com.google.gwt.view.client.SelectionModel.SelectionChangeEvent;
+import com.google.gwt.view.client.SelectionModel.SelectionChangeHandler;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Tests for {@link MultiSelectionModel}.
+ */
+public class MultiSelectionModelTest extends AbstractSelectionModelTest {
+
+ public void testGetSelectedSet() {
+ MultiSelectionModel<String> model = createSelectionModel();
+ Set<String> selected = new HashSet<String>();
+ assertEquals(selected, model.getSelectedSet());
+
+ model.setSelected("test0", true);
+ selected.add("test0");
+ assertEquals(selected, model.getSelectedSet());
+
+ model.setSelected("test1", true);
+ selected.add("test1");
+ assertEquals(selected, model.getSelectedSet());
+
+ model.setSelected("test0", false);
+ selected.remove("test0");
+ assertEquals(selected, model.getSelectedSet());
+ }
+
+ public void testSelectedChangeEvent() {
+ MultiSelectionModel<String> model = createSelectionModel();
+ SelectionChangeHandler handler = new SelectionChangeHandler() {
+ public void onSelectionChange(SelectionChangeEvent event) {
+ finishTest();
+ }
+ };
+ model.addSelectionChangeHandler(handler);
+
+ delayTestFinish(2000);
+ model.setSelected("test", true);
+ }
+
+ public void testSetSelected() {
+ MultiSelectionModel<String> model = createSelectionModel();
+ assertFalse(model.isSelected("test0"));
+
+ model.setSelected("test0", true);
+ assertTrue(model.isSelected("test0"));
+
+ model.setSelected("test1", true);
+ assertTrue(model.isSelected("test1"));
+ assertTrue(model.isSelected("test0"));
+
+ model.setSelected("test1", false);
+ assertFalse(model.isSelected("test1"));
+ assertTrue(model.isSelected("test0"));
+ }
+
+ public void testSetSelectedWithKeyProvider() {
+ MultiSelectionModel<String> model = createSelectionModel();
+ ProvidesKey<String> keyProvider = new ProvidesKey<String>() {
+ public Object getKey(String item) {
+ return item.toUpperCase();
+ }
+ };
+ model.setKeyProvider(keyProvider);
+ assertFalse(model.isSelected("test0"));
+
+ model.setSelected("test0", true);
+ assertTrue(model.isSelected("test0"));
+ assertTrue(model.isSelected("TEST0"));
+
+ model.setSelected("test1", true);
+ assertTrue(model.isSelected("test1"));
+ assertTrue(model.isSelected("TEST1"));
+ assertTrue(model.isSelected("test0"));
+ assertTrue(model.isSelected("TEST0"));
+
+ model.setSelected("test1", false);
+ assertFalse(model.isSelected("test1"));
+ assertFalse(model.isSelected("TEST1"));
+ assertTrue(model.isSelected("test0"));
+ assertTrue(model.isSelected("TEST0"));
+ }
+
+ @Override
+ protected MultiSelectionModel<String> createSelectionModel() {
+ return new MultiSelectionModel<String>();
+ }
+}
diff --git a/user/test/com/google/gwt/view/client/SingleSelectionModelTest.java b/user/test/com/google/gwt/view/client/SingleSelectionModelTest.java
new file mode 100644
index 0000000..1476ecd
--- /dev/null
+++ b/user/test/com/google/gwt/view/client/SingleSelectionModelTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.view.client;
+
+import com.google.gwt.view.client.SelectionModel.SelectionChangeEvent;
+import com.google.gwt.view.client.SelectionModel.SelectionChangeHandler;
+
+/**
+ * Tests for {@link SingleSelectionModel}.
+ */
+public class SingleSelectionModelTest extends AbstractSelectionModelTest {
+
+ public void testGetSelectedObject() {
+ SingleSelectionModel<String> model = createSelectionModel();
+ assertNull(model.getSelectedObject());
+
+ model.setSelected("test", true);
+ assertEquals("test", model.getSelectedObject());
+
+ model.setSelected("test", false);
+ assertNull(model.getSelectedObject());
+ }
+
+ public void testSelectedChangeEvent() {
+ SingleSelectionModel<String> model = createSelectionModel();
+ SelectionChangeHandler handler = new SelectionChangeHandler() {
+ public void onSelectionChange(SelectionChangeEvent event) {
+ finishTest();
+ }
+ };
+ model.addSelectionChangeHandler(handler);
+
+ delayTestFinish(2000);
+ model.setSelected("test", true);
+ }
+
+ public void testSetSelected() {
+ SingleSelectionModel<String> model = createSelectionModel();
+ assertFalse(model.isSelected("test0"));
+
+ model.setSelected("test0", true);
+ assertTrue(model.isSelected("test0"));
+
+ model.setSelected("test1", true);
+ assertTrue(model.isSelected("test1"));
+ assertFalse(model.isSelected("test0"));
+
+ model.setSelected("test1", false);
+ assertFalse(model.isSelected("test1"));
+ assertFalse(model.isSelected("test0"));
+ }
+
+ public void testSetSelectedWithKeyProvider() {
+ SingleSelectionModel<String> model = createSelectionModel();
+ ProvidesKey<String> keyProvider = new ProvidesKey<String>() {
+ public Object getKey(String item) {
+ return item.toUpperCase();
+ }
+ };
+ model.setKeyProvider(keyProvider);
+ assertFalse(model.isSelected("test0"));
+
+ model.setSelected("test0", true);
+ assertTrue(model.isSelected("test0"));
+ assertTrue(model.isSelected("TEST0"));
+
+ model.setSelected("test1", true);
+ assertTrue(model.isSelected("test1"));
+ assertTrue(model.isSelected("TEST1"));
+ assertFalse(model.isSelected("test0"));
+
+ model.setSelected("test1", false);
+ assertFalse(model.isSelected("test1"));
+ assertFalse(model.isSelected("test0"));
+ }
+
+ @Override
+ protected SingleSelectionModel<String> createSelectionModel() {
+ return new SingleSelectionModel<String>();
+ }
+}