Fixing a bug in Cell Widgets when using the BOUND_TO_SELECTION KeyboardSelectionPolicy in which programmatically deselecting a value makes the value unselectable until the user selects a different value. For example, in the list A, B, C, if you programmatically deselect value B, then value B cannot be selected unless the user selects value A or C first. We now correctly detect this case and update the state with a null selected value, which allows us to detect the change when the user selects value B.
Review at http://gwt-code-reviews.appspot.com/1578805
Review by: skybrian@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10724 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/cellview/client/HasDataPresenter.java b/user/src/com/google/gwt/user/cellview/client/HasDataPresenter.java
index 08875c1..a7d87f5 100644
--- a/user/src/com/google/gwt/user/cellview/client/HasDataPresenter.java
+++ b/user/src/com/google/gwt/user/cellview/client/HasDataPresenter.java
@@ -1163,7 +1163,7 @@
* or we will have a null selection event while we wait for asynchronous
* data to load.
*/
- if (newKey != null && !newKey.equals(oldKey)) {
+ if (newKey != null) {
// Check both values for selection before setting selection, or the
// selection model may resolve state early.
boolean oldValueWasSelected =
@@ -1171,15 +1171,20 @@
boolean newValueWasSelected =
(newValue == null) ? false : selectionModel.isSelected(newValue);
- // Deselect the old value.
- if (oldValueWasSelected) {
- selectionModel.setSelected(oldValue, false);
- }
-
- // Select the new value.
- pending.selectedValue = newValue;
- if (newValue != null && !newValueWasSelected) {
- selectionModel.setSelected(newValue, true);
+ if (!newKey.equals(oldKey)) {
+ // Deselect the old value.
+ if (oldValueWasSelected) {
+ selectionModel.setSelected(oldValue, false);
+ }
+
+ // Select the new value.
+ pending.selectedValue = newValue;
+ if (newValue != null && !newValueWasSelected) {
+ selectionModel.setSelected(newValue, true);
+ }
+ } else if (!newValueWasSelected) {
+ // The value was programmatically deselected.
+ pending.selectedValue = null;
}
}
}
diff --git a/user/test/com/google/gwt/user/cellview/client/HasDataPresenterTest.java b/user/test/com/google/gwt/user/cellview/client/HasDataPresenterTest.java
index e6c7fb1..95835c7 100644
--- a/user/test/com/google/gwt/user/cellview/client/HasDataPresenterTest.java
+++ b/user/test/com/google/gwt/user/cellview/client/HasDataPresenterTest.java
@@ -630,6 +630,41 @@
}
/**
+ * Test that programmatically deselecting a row works.
+ */
+ public void testSetKeyboardSelectedRowBoundWithDeselect() {
+ HasData<String> listView = new MockHasData<String>();
+ MockView<String> view = new MockView<String>();
+ HasDataPresenter<String> presenter = new HasDataPresenter<String>(listView, view, 10, null);
+ presenter.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.BOUND_TO_SELECTION);
+ presenter.setVisibleRange(new Range(0, 10));
+ populatePresenter(presenter);
+ presenter.flush();
+
+ // Add a selection model.
+ MockSingleSelectionModel<String> model = new MockSingleSelectionModel<String>(null);
+ presenter.setSelectionModel(model);
+ presenter.flush();
+ assertEquals(null, model.getSelectedObject());
+
+ // Select an item.
+ presenter.setKeyboardSelectedRow(1, false, false);
+ presenter.flush();
+ assertTrue(model.isSelected("test 1"));
+
+ // Deselect the item.
+ model.setSelected("test 1", false);
+ assertFalse(model.isSelected("test 1"));
+ presenter.flush();
+ assertEquals(1, presenter.getKeyboardSelectedRow());
+
+ // Reselect the item.
+ presenter.setKeyboardSelectedRow(1, false, false);
+ presenter.flush();
+ assertTrue(model.isSelected("test 1"));
+ }
+
+ /**
* Test that we only get one selection event when keyboard selection changes.
*/
public void testSetKeyboardSelectedRowFiresOneSelectionEvent() {