]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fixing issue with TwinColSelect not correctly retaining visible selection (#11799)
authorTatu Lund <tatu@vaadin.com>
Tue, 19 Nov 2019 09:04:44 +0000 (11:04 +0200)
committerAnna Koskinen <Ansku@users.noreply.github.com>
Tue, 19 Nov 2019 09:04:44 +0000 (11:04 +0200)
There is a bug in TwinColSelect loging, it retains selection by indexes not by values after being sorted when new item has been added. This is a fixed by changing updateListBox method to retain the selection as it is being called after selection is being done.

Fixes: #11287
client/src/main/java/com/vaadin/client/ui/VTwinColSelect.java

index 6cbdb944ec932473de1d93a6d8985207a5752077..8618f9b52d3c34c40748a164197827cf50c95b33 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Set;
 import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
 
+import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.dom.client.Style.Overflow;
 import com.google.gwt.dom.client.Style.Position;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -37,6 +38,7 @@ import com.google.gwt.event.dom.client.KeyDownHandler;
 import com.google.gwt.event.dom.client.MouseDownEvent;
 import com.google.gwt.event.dom.client.MouseDownHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.HTML;
@@ -80,6 +82,7 @@ public class VTwinColSelect extends Composite implements MultiSelectWidget,
     private static final int VISIBLE_COUNT = 10;
 
     private static final int DEFAULT_COLUMN_COUNT = 10;
+    private static int scheduledScrollToItem = -1;
 
     private final DoubleClickListBox optionsListBox;
 
@@ -327,15 +330,28 @@ public class VTwinColSelect extends Composite implements MultiSelectWidget,
 
     private static void updateListBox(ListBox listBox,
             List<JsonObject> options) {
+        List<String> selected = new ArrayList<String>();
+        // Retain right visible selection, see #11287
+        for (int i = 0; i < listBox.getItemCount(); ++i) {
+            if (listBox.isItemSelected(i)) {
+                selected.add(listBox.getItemText(i));
+            }
+        }
         for (int i = 0; i < options.size(); i++) {
             final JsonObject item = options.get(i);
             // reuse existing option if possible
+            String caption = MultiSelectWidget.getCaption(item);
             if (i < listBox.getItemCount()) {
-                listBox.setItemText(i, MultiSelectWidget.getCaption(item));
+                listBox.setItemText(i, caption);
                 listBox.setValue(i, MultiSelectWidget.getKey(item));
             } else {
-                listBox.addItem(MultiSelectWidget.getCaption(item),
-                        MultiSelectWidget.getKey(item));
+                listBox.addItem(caption, MultiSelectWidget.getKey(item));
+            }
+            boolean isSelected = selected.contains(caption);
+            listBox.setItemSelected(i, isSelected);
+            if (isSelected) {
+                // Ensure that last selected item is visible
+                scrollToView(listBox,i);
             }
         }
         // remove extra
@@ -344,6 +360,19 @@ public class VTwinColSelect extends Composite implements MultiSelectWidget,
         }
     }
 
+    private static void scrollToView(ListBox listBox, int i) {
+        if (scheduledScrollToItem == -1) {
+            scheduledScrollToItem = i;
+            Scheduler.get().scheduleDeferred(() -> {
+                 Element el = (Element) listBox.getElement().getChild(scheduledScrollToItem);
+                 el.scrollIntoView();
+                 scheduledScrollToItem = -1;
+            });
+        } else {
+            scheduledScrollToItem = i;
+        }
+    }
+
     private static boolean[] getSelectionBitmap(ListBox listBox) {
         final boolean[] selectedIndexes = new boolean[listBox.getItemCount()];
         for (int i = 0; i < listBox.getItemCount(); i++) {