diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/itemlist/ListTransformation.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/itemlist/ListTransformation.java index 83da43f68..36936710b 100644 --- a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/itemlist/ListTransformation.java +++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/itemlist/ListTransformation.java @@ -89,6 +89,7 @@ public void onChanged( // targetList List deleteStaging = new ArrayList<>(); + while (listEvent.next()) { if (listEvent.wasUpdated()) { processUpdateEvent(listEvent); @@ -118,10 +119,13 @@ public void onChanged( */ private void processAddEvent( ListChangeListener.Change listEvent) { - for (int i = listEvent.getFrom(); i < listEvent.getTo(); i++) { - SourceType item = listEvent.getList().get(i); - viewModelList.add(i, ListTransformation.this.function.apply(item)); + + final List toAdd = new ArrayList<>(); + for (int index = listEvent.getFrom(); index < listEvent.getTo(); index++) { + final SourceType item = listEvent.getList().get(index); + toAdd.add(function.apply(item)); } + viewModelList.addAll(listEvent.getFrom(), toAdd); } /** diff --git a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/itemlist/ItemListTest.java b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/itemlist/ItemListTest.java index 8ed5c9005..e1337c2bf 100644 --- a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/itemlist/ItemListTest.java +++ b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/itemlist/ItemListTest.java @@ -16,12 +16,19 @@ package de.saxsys.mvvmfx.utils.itemlist; import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; + /** * Tests for {@link ItemList}. * @@ -143,5 +150,36 @@ public void replaceItemInItemListAtIndex() { Assert.assertEquals(PREFIX + "replacedPerson", itemList .stringListProperty().get(1)); } - + + /** + * This test is used to reproduce the bug #281. + * + * When multiple elements are added to the list in a single method call ({@link ObservableList#addAll(Object[])}, + * only a single change event should be fired. + */ + @Test + public void addMultipleItemsEventListener() { + AtomicInteger counter = new AtomicInteger(0); + + itemList.getTargetList().addListener((ListChangeListener) c -> { + counter.incrementAndGet(); + }); + + listWithModelObjects.addAll(new Person("one"), new Person("two"), new Person("three")); + + assertThat(counter.get()).isEqualTo(1); + } + + @Test + public void removeMultipleItemsEventListener() { + AtomicInteger counter = new AtomicInteger(0); + + itemList.getTargetList().addListener((ListChangeListener) c -> { + counter.incrementAndGet(); + }); + + listWithModelObjects.removeAll(person1, person3); + + assertThat(counter.get()).isEqualTo(1); + } }