blob: 5cdb06f45b59c65fd2d410d959c61d7dd48192f6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2020 Original authors and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Original authors and others - initial API and implementation
* Dirk Fauth <dirk.fauth@googlemail.com> - added missing generic type arguments
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.extension.glazedlists;
import org.eclipse.nebula.widgets.nattable.data.IColumnAccessor;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.event.ListEvent;
/**
* This class implements "last row" caching for much faster column value access
* on the table. As normally the default implementation would fetch the row
* object for each cell in a column, we know what the last row we fetched was,
* and if it's a re-request of the same row as last time, we simply return the
* last cached row object (assuming the list didn't change in some important
* way, as then we clear out our cache).
*
* @author Emil Crumhorn
*
* @deprecated Use a default {@link ListDataProvider} instead as the performance
* boost can not be verified with current Java and GlazedLists
* implementations and as this implementation is not thread-safe it
* introduces more issues than it tries to solve.
*/
@Deprecated
public class GlazedListsDataProvider<T> extends ListDataProvider<T> {
private int lastRowIndex = -1;
private T lastRowObject = null;
public GlazedListsDataProvider(EventList<T> list, IColumnAccessor<T> columnAccessor) {
super(list, columnAccessor);
// As we cache the last row object for much faster access, we need to
// tell that "tiny cache" that the input changed in any way, so that it
// doesn't use the last row object anymore, as that will cause same rows
// as last to be updated with the old object until the entire table has
// either refreshed twice (for multi-row tables) or it will never
// refresh (single entry tables).
// thus, if it's a delete, we update completely. if it's a modification
// of the current row we have cached, we update as well, inserts we
// don't need to as they are new items and the index will never be the
// same anyway.
list.addListEventListener(event -> {
while (event.next()) {
int sourceIndex = event.getIndex();
int changeType = event.getType();
if (changeType == ListEvent.DELETE
|| sourceIndex == GlazedListsDataProvider.this.lastRowIndex) {
inputChanged();
break;
}
}
});
}
public void inputChanged() {
this.lastRowIndex = -1;
this.lastRowObject = null;
}
@Override
public T getRowObject(int rowIndex) {
if (rowIndex != this.lastRowIndex || this.lastRowObject == null) {
((EventList<T>) this.list).getReadWriteLock().readLock().lock();
try {
return super.getRowObject(rowIndex);
} finally {
((EventList<T>) this.list).getReadWriteLock().readLock().unlock();
}
}
return this.lastRowObject;
}
@Override
public Object getDataValue(int colIndex, int rowIndex) {
// new row to cache
if (rowIndex != this.lastRowIndex || this.lastRowObject == null) {
this.lastRowIndex = rowIndex;
((EventList<T>) this.list).getReadWriteLock().readLock().lock();
try {
this.lastRowObject = this.list.get(rowIndex);
} finally {
((EventList<T>) this.list).getReadWriteLock().readLock().unlock();
}
}
// same row as last, use its object as it's way faster than a
// list.get(row);
return this.columnAccessor.getDataValue(this.lastRowObject, colIndex);
}
}