From 8374a0aa32dec95d8fb72f6f0d3cf286cc3684f4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Fri, 27 Jul 2012 14:00:39 +0000 Subject: [PATCH] Preserve selection order for multi select value (#8109, #8787) svn changeset:24030/svn branch:6.8 --- src/com/vaadin/ui/AbstractSelect.java | 13 +- src/com/vaadin/ui/Table.java | 21 +- .../abstractfield/AbstractFieldTest.java | 15 +- .../table/MultiSelectValueOrder.html | 275 ++++++++++++++++++ 4 files changed, 309 insertions(+), 15 deletions(-) create mode 100644 tests/testbench/com/vaadin/tests/components/table/MultiSelectValueOrder.html diff --git a/src/com/vaadin/ui/AbstractSelect.java b/src/com/vaadin/ui/AbstractSelect.java index bb49626741..71624804fa 100644 --- a/src/com/vaadin/ui/AbstractSelect.java +++ b/src/com/vaadin/ui/AbstractSelect.java @@ -426,12 +426,15 @@ public abstract class AbstractSelect extends AbstractField implements // (non-visible items can not be deselected) final Collection visible = getVisibleItemIds(); if (visible != null) { + // Don't remove those that will be added to preserve order + visible.removeAll(s); + @SuppressWarnings("unchecked") Set newsel = (Set) getValue(); if (newsel == null) { - newsel = new HashSet(); + newsel = new LinkedHashSet(); } else { - newsel = new HashSet(newsel); + newsel = new LinkedHashSet(newsel); } newsel.removeAll(visible); newsel.addAll(s); @@ -645,10 +648,10 @@ public abstract class AbstractSelect extends AbstractField implements if (isMultiSelect()) { if (newValue == null) { - super.setValue(new HashSet(), repaintIsNotNeeded); + super.setValue(new LinkedHashSet(), repaintIsNotNeeded); } else if (Collection.class.isAssignableFrom(newValue.getClass())) { - super.setValue(new HashSet((Collection) newValue), - repaintIsNotNeeded); + super.setValue(new LinkedHashSet( + (Collection) newValue), repaintIsNotNeeded); } } else if (newValue == null || items.containsId(newValue)) { super.setValue(newValue, repaintIsNotNeeded); diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index 60b6122270..c4d90d7790 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -2295,7 +2295,7 @@ public class Table extends AbstractSelect implements Action.Container, * @return */ private Set getItemIdsInRange(Object itemId, final int length) { - HashSet ids = new HashSet(); + HashSet ids = new LinkedHashSet(); for (int i = 0; i < length; i++) { assert itemId != null; // should not be null unless client-server // are out of sync @@ -2318,18 +2318,12 @@ public class Table extends AbstractSelect implements Action.Container, Set renderedItemIds = getCurrentlyRenderedItemIds(); @SuppressWarnings("unchecked") - HashSet newValue = new HashSet( + HashSet newValue = new LinkedHashSet( (Collection) getValue()); if (variables.containsKey("clearSelections")) { // the client side has instructed to swipe all previous selections newValue.clear(); - } else { - /* - * first clear all selections that are currently rendered rows (the - * ones that the client side counterpart is aware of) - */ - newValue.removeAll(renderedItemIds); } /* @@ -2346,6 +2340,7 @@ public class Table extends AbstractSelect implements Action.Container, requestRepaint(); } else if (id != null && containsId(id)) { newValue.add(id); + renderedItemIds.remove(id); } } @@ -2355,9 +2350,17 @@ public class Table extends AbstractSelect implements Action.Container, String[] split = range.split("-"); Object startItemId = itemIdMapper.get(split[0]); int length = Integer.valueOf(split[1]); - newValue.addAll(getItemIdsInRange(startItemId, length)); + Set itemIdsInRange = getItemIdsInRange(startItemId, + length); + newValue.addAll(itemIdsInRange); + renderedItemIds.removeAll(itemIdsInRange); } } + /* + * finally clear all currently rendered rows (the ones that the client + * side counterpart is aware of) that the client didn't send as selected + */ + newValue.removeAll(renderedItemIds); if (!isNullSelectionAllowed() && newValue.isEmpty()) { // empty selection not allowed, keep old value diff --git a/tests/testbench/com/vaadin/tests/components/abstractfield/AbstractFieldTest.java b/tests/testbench/com/vaadin/tests/components/abstractfield/AbstractFieldTest.java index 40cc2948ee..c1107061ed 100644 --- a/tests/testbench/com/vaadin/tests/components/abstractfield/AbstractFieldTest.java +++ b/tests/testbench/com/vaadin/tests/components/abstractfield/AbstractFieldTest.java @@ -28,6 +28,8 @@ public abstract class AbstractFieldTest extends AbstractComponentTest implements ValueChangeListener, ReadOnlyStatusChangeListener, FocusListener, BlurListener { + private boolean sortValueChanges = true; + @Override protected void createActions() { super.createActions(); @@ -69,6 +71,17 @@ public abstract class AbstractFieldTest extends } } }); + + MenuItem sortValueChangesItem = abstractField.addItem( + "Show sorted value changes", new MenuBar.Command() { + public void menuSelected(MenuItem selectedItem) { + sortValueChanges = selectedItem.isChecked(); + log("Show sorted value changes: " + + sortValueChanges); + } + }); + sortValueChangesItem.setCheckable(true); + sortValueChangesItem.setChecked(true); } } @@ -171,7 +184,7 @@ public abstract class AbstractFieldTest extends @SuppressWarnings({ "rawtypes", "unchecked" }) private String getValue(Property property) { Object o = property.getValue(); - if (o instanceof Collection) { + if (o instanceof Collection && sortValueChanges) { // Sort collections to avoid problems with values printed in // different order try { diff --git a/tests/testbench/com/vaadin/tests/components/table/MultiSelectValueOrder.html b/tests/testbench/com/vaadin/tests/components/table/MultiSelectValueOrder.html new file mode 100644 index 0000000000..4bac7741da --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/table/MultiSelectValueOrder.html @@ -0,0 +1,275 @@ + + + + + + +New Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
New Test
open/run/com.vaadin.tests.components.table.Tables?restartApplication
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item06,9
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item473,0
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[1]/VMenuBar[0]#item133,13
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item014,10
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item375,5
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[1]/VMenuBar[0]#item064,6
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item116,8
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item322,6
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[1]/VMenuBar[0]#item116,12
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item129,6
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item140,7
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[0]/domChild[0]48,18
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_00. ValueChangeEvent, new value: '[Item 5]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[1]/domChild[0]40,12:ctrl
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_01. ValueChangeEvent, new value: '[Item 5, Item 3]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[6]/domChild[1]/domChild[0]54,15:ctrl
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_02. ValueChangeEvent, new value: '[Item 5, Item 3, Item 7]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[8]/domChild[1]/domChild[0]54,9:shift+ctrl
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_03. ValueChangeEvent, new value: '[Item 5, Item 3, Item 7, Item 8, Item 9]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[1]/domChild[0]67,8:ctrl
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_04. ValueChangeEvent, new value: '[Item 5, Item 3, Item 7, Item 8, Item 9, Item 1]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[2]/domChild[0]71,8:shift+ctrl
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_05. ValueChangeEvent, new value: '[Item 5, Item 3, Item 7, Item 8, Item 9, Item 1, Item 2, Item 4]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[2]/domChild[0]56,6:ctrl
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_06. ValueChangeEvent, new value: '[Item 3, Item 7, Item 8, Item 9, Item 1, Item 2, Item 4]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[2]/domChild[0]67,11:ctrl
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_07. ValueChangeEvent, new value: '[Item 3, Item 7, Item 8, Item 9, Item 1, Item 2, Item 4, Item 5]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item033,9
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item444,7
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[1]/VMenuBar[0]#item240,11
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[2]/VMenuBar[0]#item258,8
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item038,6
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item414,8
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[1]/VMenuBar[0]#item355,3
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[2]/VMenuBar[0]#item021,3
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item126,7
mouseClickvaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item130,6
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[1]/domChild[0]60,9
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_00. ValueChangeEvent, new value: '[Item 5]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[1]/domChild[0]38,9
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_01. ValueChangeEvent, new value: '[Item 5, Item 3]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[1]/domChild[0]46,13
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_02. ValueChangeEvent, new value: '[Item 5, Item 3, Item 4]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[1]/domChild[0]65,8
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_03. ValueChangeEvent, new value: '[Item 5, Item 4]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[2]/domChild[0]45,7
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_04. ValueChangeEvent, new value: '[Item 4]'
mouseClickvaadin=runcomvaadintestscomponentstableTables::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[2]/domChild[0]35,9
assertTextvaadin=runcomvaadintestscomponentstableTables::PID_SLog_row_05. ValueChangeEvent, new value: '[Item 4, Item 5]'
+ + -- 2.39.5