summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java75
-rw-r--r--client/src/main/java/com/vaadin/client/data/DataSource.java7
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java83
-rw-r--r--client/src/main/java/com/vaadin/client/widgets/Grid.java128
-rw-r--r--client/src/test/java/com/vaadin/client/ui/grid/ListDataSourceTest.java10
5 files changed, 159 insertions, 144 deletions
diff --git a/client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java b/client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java
index 237b6ecf45..95e013ed28 100644
--- a/client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java
+++ b/client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java
@@ -17,13 +17,18 @@
package com.vaadin.client.data;
import java.util.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Stream;
import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.vaadin.client.Profiler;
+import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.grid.Range;
/**
@@ -159,8 +164,8 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
@Override
public void updateRow() {
int index = indexOf(row);
- if (index >= 0 && dataChangeHandler != null) {
- dataChangeHandler.dataUpdated(index, 1);
+ if (index >= 0) {
+ getHandlers().forEach(dch -> dch.dataUpdated(index, 1));
}
}
}
@@ -176,7 +181,7 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
private final HashMap<Integer, T> indexToRowMap = new HashMap<Integer, T>();
private final HashMap<Object, Integer> keyToIndexMap = new HashMap<Object, Integer>();
- private DataChangeHandler dataChangeHandler;
+ private Set<DataChangeHandler> dataChangeHandlers = new LinkedHashSet<>();
private CacheStrategy cacheStrategy = new CacheStrategy.DefaultCacheStrategy();
@@ -292,9 +297,9 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
.partitionWith(cached);
handleMissingRows(missingCachePartition[0]);
handleMissingRows(missingCachePartition[2]);
- } else if (dataChangeHandler != null) {
- dataChangeHandler.dataAvailable(cached.getStart(),
- cached.length());
+ } else {
+ getHandlers().forEach(dch -> dch
+ .dataAvailable(cached.getStart(), cached.length()));
}
}
@@ -411,14 +416,19 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
}
@Override
- public void setDataChangeHandler(DataChangeHandler dataChangeHandler) {
- this.dataChangeHandler = dataChangeHandler;
+ public Registration addDataChangeHandler(
+ final DataChangeHandler dataChangeHandler) {
+ Objects.requireNonNull(dataChangeHandler,
+ "DataChangeHandler can't be null");
+ dataChangeHandlers.add(dataChangeHandler);
- if (dataChangeHandler != null && !cached.isEmpty()) {
+ if (!cached.isEmpty()) {
// Push currently cached data to the implementation
dataChangeHandler.dataUpdated(cached.getStart(), cached.length());
dataChangeHandler.dataAvailable(cached.getStart(), cached.length());
}
+
+ return () -> dataChangeHandlers.remove(dataChangeHandler);
}
/**
@@ -452,21 +462,19 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
Range newUsefulData = partition[1];
if (!newUsefulData.isEmpty()) {
// Update the parts that are actually inside
- for (int i = newUsefulData.getStart(); i < newUsefulData
- .getEnd(); i++) {
+ int start = newUsefulData.getStart();
+ for (int i = start; i < newUsefulData.getEnd(); i++) {
final T row = rowData.get(i - firstRowIndex);
indexToRowMap.put(Integer.valueOf(i), row);
keyToIndexMap.put(getRowKey(row), Integer.valueOf(i));
}
- if (dataChangeHandler != null) {
- Profiler.enter(
- "AbstractRemoteDataSource.setRowData notify dataChangeHandler");
- dataChangeHandler.dataUpdated(newUsefulData.getStart(),
- newUsefulData.length());
- Profiler.leave(
- "AbstractRemoteDataSource.setRowData notify dataChangeHandler");
- }
+ Profiler.enter(
+ "AbstractRemoteDataSource.setRowData notify dataChangeHandler");
+ int length = newUsefulData.length();
+ getHandlers().forEach(dch -> dch.dataUpdated(start, length));
+ Profiler.leave(
+ "AbstractRemoteDataSource.setRowData notify dataChangeHandler");
// Potentially extend the range
if (cached.isEmpty()) {
@@ -484,10 +492,9 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
cached = newUsefulData;
}
}
- if (dataChangeHandler != null) {
- dataChangeHandler.dataAvailable(cached.getStart(),
- cached.length());
- }
+
+ getHandlers().forEach(dch -> dch.dataAvailable(cached.getStart(),
+ cached.length()));
updatePinnedRows(rowData);
}
@@ -515,6 +522,12 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
ensureCoverageCheck();
Profiler.leave("AbstractRemoteDataSource.setRowData");
+
+ }
+
+ private Stream<DataChangeHandler> getHandlers() {
+ Set<DataChangeHandler> copy = new LinkedHashSet<>(dataChangeHandlers);
+ return copy.stream();
}
private void updatePinnedRows(final List<T> rowData) {
@@ -565,9 +578,8 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
cached = cached.offsetBy(-removedRange.length());
}
- if (dataChangeHandler != null) {
- dataChangeHandler.dataRemoved(firstRowIndex, count);
- }
+ getHandlers().forEach(dch -> dch.dataRemoved(firstRowIndex, count));
+
ensureCoverageCheck();
Profiler.leave("AbstractRemoteDataSource.removeRowData");
@@ -612,9 +624,9 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
keyToIndexMap.remove(getRowKey(row));
}
}
- if (dataChangeHandler != null) {
- dataChangeHandler.dataAdded(firstRowIndex, count);
- }
+
+ getHandlers().forEach(dch -> dch.dataAdded(firstRowIndex, count));
+
ensureCoverageCheck();
Profiler.leave("AbstractRemoteDataSource.insertRowData");
@@ -760,9 +772,8 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
size = newSize;
dropFromCache(getCachedRange());
cached = Range.withLength(0, 0);
- if (dataChangeHandler != null) {
- dataChangeHandler.resetDataAndSize(newSize);
- }
+
+ getHandlers().forEach(dch -> dch.resetDataAndSize(newSize));
}
protected int indexOfKey(Object rowKey) {
diff --git a/client/src/main/java/com/vaadin/client/data/DataSource.java b/client/src/main/java/com/vaadin/client/data/DataSource.java
index daf1f8656c..3457b7b9fc 100644
--- a/client/src/main/java/com/vaadin/client/data/DataSource.java
+++ b/client/src/main/java/com/vaadin/client/data/DataSource.java
@@ -16,6 +16,8 @@
package com.vaadin.client.data;
+import com.vaadin.shared.Registration;
+
/**
* Source of data for widgets showing lazily loaded data based on indexable
* items (e.g. rows) of a specified type. The data source is a lazy view into a
@@ -140,7 +142,7 @@ public interface DataSource<T> {
* discards the previously set range.
* <p>
* This method triggers lazy loading of data if necessary. The change
- * handler registered using {@link #setDataChangeHandler(DataChangeHandler)}
+ * handler registered using {@link #addDataChangeHandler(DataChangeHandler)}
* is informed when new data has been loaded.
* <p>
* After any possible lazy loading and updates are done, the change handler
@@ -181,7 +183,8 @@ public interface DataSource<T> {
* @param dataChangeHandler
* the data change handler
*/
- public void setDataChangeHandler(DataChangeHandler dataChangeHandler);
+ public Registration addDataChangeHandler(
+ DataChangeHandler dataChangeHandler);
/**
* Gets a {@link RowHandle} of a row object in the cache.
diff --git a/client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java b/client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java
index 928b0ecf35..584e765127 100644
--- a/client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java
+++ b/client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java
@@ -21,13 +21,18 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Stream;
import com.vaadin.client.data.DataChangeHandler;
import com.vaadin.client.data.DataSource;
import com.vaadin.client.widget.grid.events.SelectAllEvent;
import com.vaadin.client.widget.grid.events.SelectAllHandler;
+import com.vaadin.shared.Registration;
import com.vaadin.shared.util.SharedUtil;
/**
@@ -110,9 +115,8 @@ public class ListDataSource<T> implements DataSource<T> {
@Override
public void updateRow() {
- if (changeHandler != null) {
- changeHandler.dataUpdated(ds.indexOf(getRow()), 1);
- }
+ getHandlers()
+ .forEach(dch -> dch.dataUpdated(ds.indexOf(getRow()), 1));
}
}
@@ -156,9 +160,7 @@ public class ListDataSource<T> implements DataSource<T> {
@Override
public boolean add(T e) {
if (ds.add(e)) {
- if (changeHandler != null) {
- changeHandler.dataAdded(ds.size() - 1, 1);
- }
+ getHandlers().forEach(dch -> dch.dataAdded(ds.size() - 1, 1));
return true;
}
return false;
@@ -168,9 +170,7 @@ public class ListDataSource<T> implements DataSource<T> {
public boolean remove(Object o) {
int index = ds.indexOf(o);
if (ds.remove(o)) {
- if (changeHandler != null) {
- changeHandler.dataRemoved(index, 1);
- }
+ getHandlers().forEach(dch -> dch.dataRemoved(index, 1));
return true;
}
return false;
@@ -185,9 +185,7 @@ public class ListDataSource<T> implements DataSource<T> {
public boolean addAll(Collection<? extends T> c) {
int idx = ds.size();
if (ds.addAll(c)) {
- if (changeHandler != null) {
- changeHandler.dataAdded(idx, c.size());
- }
+ getHandlers().forEach(dch -> dch.dataAdded(idx, c.size()));
return true;
}
return false;
@@ -196,9 +194,7 @@ public class ListDataSource<T> implements DataSource<T> {
@Override
public boolean addAll(int index, Collection<? extends T> c) {
if (ds.addAll(index, c)) {
- if (changeHandler != null) {
- changeHandler.dataAdded(index, c.size());
- }
+ getHandlers().forEach(dch -> dch.dataAdded(index, c.size()));
return true;
}
return false;
@@ -207,12 +203,8 @@ public class ListDataSource<T> implements DataSource<T> {
@Override
public boolean removeAll(Collection<?> c) {
if (ds.removeAll(c)) {
- if (changeHandler != null) {
- // Have to update the whole list as the removal does not
- // have to be a continuous range
- changeHandler.dataUpdated(0, ds.size());
- changeHandler.dataAvailable(0, ds.size());
- }
+ getHandlers().forEach(dch -> dch.dataUpdated(0, ds.size()));
+ getHandlers().forEach(dch -> dch.dataAvailable(0, ds.size()));
return true;
}
return false;
@@ -221,12 +213,8 @@ public class ListDataSource<T> implements DataSource<T> {
@Override
public boolean retainAll(Collection<?> c) {
if (ds.retainAll(c)) {
- if (changeHandler != null) {
- // Have to update the whole list as the retain does not
- // have to be a continuous range
- changeHandler.dataUpdated(0, ds.size());
- changeHandler.dataAvailable(0, ds.size());
- }
+ getHandlers().forEach(dch -> dch.dataUpdated(0, ds.size()));
+ getHandlers().forEach(dch -> dch.dataAvailable(0, ds.size()));
return true;
}
return false;
@@ -236,9 +224,7 @@ public class ListDataSource<T> implements DataSource<T> {
public void clear() {
int size = ds.size();
ds.clear();
- if (changeHandler != null) {
- changeHandler.dataRemoved(0, size);
- }
+ getHandlers().forEach(dch -> dch.dataRemoved(0, size));
}
@Override
@@ -249,26 +235,20 @@ public class ListDataSource<T> implements DataSource<T> {
@Override
public T set(int index, T element) {
T prev = ds.set(index, element);
- if (changeHandler != null) {
- changeHandler.dataUpdated(index, 1);
- }
+ getHandlers().forEach(dch -> dch.dataUpdated(index, 1));
return prev;
}
@Override
public void add(int index, T element) {
ds.add(index, element);
- if (changeHandler != null) {
- changeHandler.dataAdded(index, 1);
- }
+ getHandlers().forEach(dch -> dch.dataAdded(index, 1));
}
@Override
public T remove(int index) {
T removed = ds.remove(index);
- if (changeHandler != null) {
- changeHandler.dataRemoved(index, 1);
- }
+ getHandlers().forEach(dch -> dch.dataRemoved(index, 1));
return removed;
}
@@ -346,7 +326,7 @@ public class ListDataSource<T> implements DataSource<T> {
/**
* Handler for listening to changes in the underlying list.
*/
- private DataChangeHandler changeHandler;
+ private Set<DataChangeHandler> changeHandlers = new LinkedHashSet<>();
/**
* Constructs a new list data source.
@@ -392,9 +372,8 @@ public class ListDataSource<T> implements DataSource<T> {
"Trying to fetch rows outside of array");
}
- if (changeHandler != null) {
- changeHandler.dataAvailable(firstRowIndex, numberOfRows);
- }
+ getHandlers()
+ .forEach(dch -> dch.dataAvailable(firstRowIndex, numberOfRows));
}
@Override
@@ -408,8 +387,12 @@ public class ListDataSource<T> implements DataSource<T> {
}
@Override
- public void setDataChangeHandler(DataChangeHandler dataChangeHandler) {
- this.changeHandler = dataChangeHandler;
+ public Registration addDataChangeHandler(
+ DataChangeHandler dataChangeHandler) {
+ Objects.requireNonNull(dataChangeHandler,
+ "DataChangeHandler can't be null");
+ changeHandlers.add(dataChangeHandler);
+ return () -> changeHandlers.remove(dataChangeHandler);
}
/**
@@ -443,9 +426,7 @@ public class ListDataSource<T> implements DataSource<T> {
*/
public void sort(Comparator<T> comparator) {
Collections.sort(ds, comparator);
- if (changeHandler != null) {
- changeHandler.dataUpdated(0, ds.size());
- }
+ getHandlers().forEach(dch -> dch.dataUpdated(0, ds.size()));
}
/**
@@ -475,4 +456,10 @@ public class ListDataSource<T> implements DataSource<T> {
}
};
}
+
+ private Stream<DataChangeHandler> getHandlers() {
+ Set<DataChangeHandler> copy = new LinkedHashSet<>(changeHandlers);
+ return copy.stream();
+ }
+
}
diff --git a/client/src/main/java/com/vaadin/client/widgets/Grid.java b/client/src/main/java/com/vaadin/client/widgets/Grid.java
index 53be286ee0..990c85dd1c 100644
--- a/client/src/main/java/com/vaadin/client/widgets/Grid.java
+++ b/client/src/main/java/com/vaadin/client/widgets/Grid.java
@@ -174,6 +174,7 @@ import com.vaadin.client.widgets.Escalator.SubPartArguments;
import com.vaadin.client.widgets.Grid.Editor.State;
import com.vaadin.client.widgets.Grid.StaticSection.StaticCell;
import com.vaadin.client.widgets.Grid.StaticSection.StaticRow;
+import com.vaadin.shared.Registration;
import com.vaadin.shared.data.sort.SortDirection;
import com.vaadin.shared.ui.grid.GridConstants;
import com.vaadin.shared.ui.grid.GridConstants.Section;
@@ -4022,6 +4023,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
* on initialization, but not after that.
*/
private DataSource<T> dataSource;
+ private Registration changeHandler;
/**
* Currently available row range in DataSource.
@@ -6700,73 +6702,85 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
selectionModel.reset();
- if (this.dataSource != null) {
- this.dataSource.setDataChangeHandler(null);
+ if (changeHandler != null) {
+ changeHandler.remove();
+ changeHandler = null;
}
this.dataSource = dataSource;
- dataSource.setDataChangeHandler(new DataChangeHandler() {
- @Override
- public void dataUpdated(int firstIndex, int numberOfItems) {
- escalator.getBody().refreshRows(firstIndex, numberOfItems);
- }
+ changeHandler = dataSource
+ .addDataChangeHandler(new DataChangeHandler() {
+ @Override
+ public void dataUpdated(int firstIndex, int numberOfItems) {
+ escalator.getBody().refreshRows(firstIndex,
+ numberOfItems);
+ }
- @Override
- public void dataRemoved(int firstIndex, int numberOfItems) {
- escalator.getBody().removeRows(firstIndex, numberOfItems);
- Range removed = Range.withLength(firstIndex, numberOfItems);
- cellFocusHandler.rowsRemovedFromBody(removed);
- }
+ @Override
+ public void dataRemoved(int firstIndex, int numberOfItems) {
+ escalator.getBody().removeRows(firstIndex,
+ numberOfItems);
+ Range removed = Range.withLength(firstIndex,
+ numberOfItems);
+ cellFocusHandler.rowsRemovedFromBody(removed);
+ }
- @Override
- public void dataAdded(int firstIndex, int numberOfItems) {
- escalator.getBody().insertRows(firstIndex, numberOfItems);
- Range added = Range.withLength(firstIndex, numberOfItems);
- cellFocusHandler.rowsAddedToBody(added);
- }
+ @Override
+ public void dataAdded(int firstIndex, int numberOfItems) {
+ escalator.getBody().insertRows(firstIndex,
+ numberOfItems);
+ Range added = Range.withLength(firstIndex,
+ numberOfItems);
+ cellFocusHandler.rowsAddedToBody(added);
+ }
- @Override
- public void dataAvailable(int firstIndex, int numberOfItems) {
- currentDataAvailable = Range.withLength(firstIndex,
- numberOfItems);
- fireEvent(new DataAvailableEvent(currentDataAvailable));
- }
+ @Override
+ public void dataAvailable(int firstIndex,
+ int numberOfItems) {
+ currentDataAvailable = Range.withLength(firstIndex,
+ numberOfItems);
+ fireEvent(new DataAvailableEvent(currentDataAvailable));
+ }
- @Override
- public void resetDataAndSize(int newSize) {
- RowContainer body = escalator.getBody();
- int oldSize = body.getRowCount();
-
- // Hide all details.
- Set<Integer> oldDetails = new HashSet<Integer>(visibleDetails);
- for (int i : oldDetails) {
- setDetailsVisible(i, false);
- }
+ @Override
+ public void resetDataAndSize(int newSize) {
+ RowContainer body = escalator.getBody();
+ int oldSize = body.getRowCount();
+
+ // Hide all details.
+ Set<Integer> oldDetails = new HashSet<Integer>(
+ visibleDetails);
+ for (int i : oldDetails) {
+ setDetailsVisible(i, false);
+ }
- if (newSize > oldSize) {
- body.insertRows(oldSize, newSize - oldSize);
- cellFocusHandler.rowsAddedToBody(
- Range.withLength(oldSize, newSize - oldSize));
- } else if (newSize < oldSize) {
- body.removeRows(newSize, oldSize - newSize);
- cellFocusHandler.rowsRemovedFromBody(
- Range.withLength(newSize, oldSize - newSize));
- }
+ if (newSize > oldSize) {
+ body.insertRows(oldSize, newSize - oldSize);
+ cellFocusHandler.rowsAddedToBody(Range
+ .withLength(oldSize, newSize - oldSize));
+ } else if (newSize < oldSize) {
+ body.removeRows(newSize, oldSize - newSize);
+ cellFocusHandler.rowsRemovedFromBody(Range
+ .withLength(newSize, oldSize - newSize));
+ }
- if (newSize > 0) {
- dataIsBeingFetched = true;
- Range visibleRowRange = escalator.getVisibleRowRange();
- dataSource.ensureAvailability(visibleRowRange.getStart(),
- visibleRowRange.length());
- } else {
- // We won't expect any data more data updates, so just make
- // the bookkeeping happy
- dataAvailable(0, 0);
- }
+ if (newSize > 0) {
+ dataIsBeingFetched = true;
+ Range visibleRowRange = escalator
+ .getVisibleRowRange();
+ dataSource.ensureAvailability(
+ visibleRowRange.getStart(),
+ visibleRowRange.length());
+ } else {
+ // We won't expect any data more data updates, so
+ // just make
+ // the bookkeeping happy
+ dataAvailable(0, 0);
+ }
- assert body.getRowCount() == newSize;
- }
- });
+ assert body.getRowCount() == newSize;
+ }
+ });
int previousRowCount = escalator.getBody().getRowCount();
if (previousRowCount != 0) {
diff --git a/client/src/test/java/com/vaadin/client/ui/grid/ListDataSourceTest.java b/client/src/test/java/com/vaadin/client/ui/grid/ListDataSourceTest.java
index 89a2e80679..b3a4f24ebb 100644
--- a/client/src/test/java/com/vaadin/client/ui/grid/ListDataSourceTest.java
+++ b/client/src/test/java/com/vaadin/client/ui/grid/ListDataSourceTest.java
@@ -56,7 +56,7 @@ public class ListDataSourceTest {
DataChangeHandler handler = EasyMock
.createNiceMock(DataChangeHandler.class);
- ds.setDataChangeHandler(handler);
+ ds.addDataChangeHandler(handler);
handler.dataAdded(4, 1);
EasyMock.expectLastCall();
@@ -80,7 +80,7 @@ public class ListDataSourceTest {
DataChangeHandler handler = EasyMock
.createNiceMock(DataChangeHandler.class);
- ds.setDataChangeHandler(handler);
+ ds.addDataChangeHandler(handler);
handler.dataAdded(4, 3);
EasyMock.expectLastCall();
@@ -106,7 +106,7 @@ public class ListDataSourceTest {
DataChangeHandler handler = EasyMock
.createNiceMock(DataChangeHandler.class);
- ds.setDataChangeHandler(handler);
+ ds.addDataChangeHandler(handler);
handler.dataRemoved(3, 1);
EasyMock.expectLastCall();
@@ -128,7 +128,7 @@ public class ListDataSourceTest {
DataChangeHandler handler = EasyMock
.createNiceMock(DataChangeHandler.class);
- ds.setDataChangeHandler(handler);
+ ds.addDataChangeHandler(handler);
handler.dataRemoved(0, 3);
EasyMock.expectLastCall();
@@ -148,7 +148,7 @@ public class ListDataSourceTest {
DataChangeHandler handler = EasyMock
.createNiceMock(DataChangeHandler.class);
- ds.setDataChangeHandler(handler);
+ ds.addDataChangeHandler(handler);
handler.dataRemoved(0, 4);
EasyMock.expectLastCall();