blob: 049103512aea9401c54034f04bf9c7b8fd76ca54 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2012, 2021 Original NatTable 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 NatTable authors and others - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ecommons.waltable.data;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* Enables the use of a {@link List} containing POJO(s) as a backing data source.
*
* By default a bean at position 'X' in the list is displayed in
* row 'X' in the table. The properties of the bean are used to
* populate the columns. A {@link IColumnPropertyResolver} is used to
* retrieve column data from the bean properties.
*
* By implementing filter logic within {@link AbstractFilterListDataProvider#show(Object)}
* it is possible to create a static filter. All data access methods will skip invisible
* items within the wrapped list and delegate access to the visible items.
*
* NOTE: This way of static filtering can cause performance issues for huge data sets
* where a lot of items are filtered, because data access will always calculate the visible row
* position. Trying to use a caching mechanism would create some issues for deleting or inserting
* new data to the wrapped list.
*
* TODO add caching that reacts on insert/delete actions on the wrapped list
*
* @param <T> type of the Objects in the backing list.
* @see IColumnPropertyResolver
*/
public abstract class AbstractFilterListDataProvider<T> extends ListDataProvider<T> {
public AbstractFilterListDataProvider(final List<T> list, final IColumnAccessor<T> columnAccessor) {
super(list, columnAccessor);
}
/**
* Iterates over the whole list of data objects and checks the visibility for
* every object. The number of non visible items will be subtracted from the
* size of the wrapped list to return the number of visible items.
*/
@Override
public long getRowCount() {
long numberOfInvisible= 0;
for (final T object : this.list) {
if (!show(object)) {
numberOfInvisible++;
}
}
return this.list.size() - numberOfInvisible;
}
/**
* Get the data value for the columnIndex and the visible rowIndex.
*/
@Override
public Object getDataValue(final long columnIndex, final long rowIndex, final int flags, final IProgressMonitor monitor) {
final T rowObj= getRowObject(rowIndex);
return this.columnAccessor.getDataValue(rowObj, columnIndex);
}
/**
* Set the data value for the columnIndex and the visible rowIndex.
*/
@Override
public void setDataValue(final long columnIndex, final long rowIndex, final Object newValue) {
final T rowObj= getRowObject(rowIndex);
this.columnAccessor.setDataValue(rowObj, columnIndex, newValue);
}
/**
* Returns the object for the visible rowIndex.
* To do this it is iterated over the wrapped list, taking the invisible
* items into account, so the real row index for the given visible row index
* is calculated.
*/
@Override
public T getRowObject(final long rowIndex) {
if (rowIndex >= Integer.MAX_VALUE) {
return null;
}
T object= null;
long count= 0;
int realRowIndex= 0;
while (count <= rowIndex) {
object= this.list.get(realRowIndex);
if (show(object)) {
count++;
}
realRowIndex++;
}
return object;
}
/**
* Returns the visible rowIndex for the given object.
* To do this the real row index for the object within the wrapped list
* is searched and then all invisible items are subtracted from the
* real row index to calculate the visible row index.
*/
@Override
public long indexOfRowObject(final T rowObject) {
final int realRowIndex= this.list.indexOf(rowObject);
int filteredIndex= realRowIndex;
//now find number of not visible items
T vf= null;
for (int i= 0; i <= realRowIndex; i++) {
vf= this.list.get(i);
if (!show(vf)) {
filteredIndex--;
}
}
return filteredIndex;
}
/**
* Within this method the filter logic should be applied.
* Return false if the object should not be visible within the grid.
* Return true if it should be visible.
* @param object The object that should be checked.
* @return true if the object should be visible, false if not
*/
protected abstract boolean show(T object);
}