package com.vaadin.tests.components.table;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.v7.data.Container;
import com.vaadin.v7.data.Item;
import com.vaadin.v7.data.Property;
import com.vaadin.v7.data.util.AbstractContainer;
import com.vaadin.v7.data.util.BeanItem;
@SuppressWarnings("serial")
public class ExpandingContainer extends AbstractContainer implements
Container.Ordered, Container.Indexed, Container.ItemSetChangeNotifier {
public static final List<String> PROPERTY_IDS = Arrays.asList("id",
"column1", "column2");
private final Label sizeLabel;
private final Logger log = Logger.getLogger(this.getClass().getName());
private int currentSize = 300;
private boolean loggingEnabled;
public ExpandingContainer(Label sizeLabel) {
this.sizeLabel = sizeLabel;
updateLabel();
}
private void log(String message) {
if (loggingEnabled) {
log.info(message);
}
}
// Expand container if we scroll past 85%
public int checkExpand(int index) {
log("checkExpand(" + index + ")");
if (index >= currentSize * 0.85) {
final int oldsize = currentSize;
currentSize = (int) (oldsize * 1.3333);
log("*** getSizeWithHint(" + index + "): went past 85% of size="
+ oldsize + ", new size=" + currentSize);
updateLabel();
}
return currentSize;
}
@Override
public void fireItemSetChange() {
super.fireItemSetChange();
}
private void updateLabel() {
sizeLabel.setValue("Container size: " + currentSize);
}
public void triggerItemSetChange() {
log("*** triggerItemSetChange(): scheduling item set change event");
final VaadinSession session = VaadinSession.getCurrent();
new Thread() {
@Override
public void run() {
ExpandingContainer.this.invoke(session, new Runnable() {
@Override
public void run() {
log("*** Firing item set change event");
ExpandingContainer.this.fireItemSetChange();
}
});
}
}.start();
}
private void invoke(VaadinSession session, Runnable action) {
session.lock();
VaadinSession previousSession = VaadinSession.getCurrent();
VaadinSession.setCurrent(session);
try {
action.run();
} finally {
session.unlock();
VaadinSession.setCurrent(previousSession);
}
}
// Container
@Override
public BeanItem<MyBean> getItem(Object itemId) {
if (!(itemId instanceof Integer)) {
return null;
}
final int index = ((Integer) itemId).intValue();
return new BeanItem<>(new MyBean(index));
}
@Override
public Collection<Integer> getItemIds() {
return new IntList(size());
}
@Override
public List<String> getContainerPropertyIds() {
return PROPERTY_IDS;
}
@Override
@SuppressWarnings("rawtypes")
public Property/* <?> */ getContainerProperty(Object itemId,
Object propertyId) {
BeanItem<MyBean> item = getItem(itemId);
return item != null ? item.getItemProperty(propertyId) : null;
}
@Override
public Class<?> getType(Object propertyId) {
return Component.class;
}
@Override
public int size() {
return currentSize;
}
@Override
public boolean containsId(Object itemId) {
if (!(itemId instanceof Integer)) {
return false;
}
int index = ((Integer) itemId).intValue();
checkExpand(index);
return index >= 0 && index < currentSize;
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public Item addItem(Object itemId) {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public Item addItem() {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public boolean removeItem(Object itemId) {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public boolean addContainerProperty(Object propertyId, Class<?> type,
Object defaultValue) {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public boolean removeContainerProperty(Object propertyId) {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public boolean removeAllItems() {
throw new UnsupportedOperationException();
}
// Container.Indexed
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public Object addItemAt(int index) {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public Item addItemAt(int index, Object newItemId) {
throw new UnsupportedOperationException();
}
@Override
public Integer getIdByIndex(int index) {
if (index < 0) {
throw new IndexOutOfBoundsException("index < " + index);
}
final int size = currentSize;
if (index >= size) {
throw new IndexOutOfBoundsException(
"index=" + index + " but size=" + size);
}
checkExpand(index);
return index;
}
@Override
public List<Integer> getItemIds(int startIndex, int numberOfItems) {
if (numberOfItems < 0) {
throw new IllegalArgumentException("numberOfItems < 0");
}
final int size = currentSize;
checkExpand(startIndex);
if (startIndex < 0 || startIndex > size) {
throw new IndexOutOfBoundsException(
"startIndex=" + startIndex + " but size=" + size);
}
if (startIndex + numberOfItems > size) {
numberOfItems = size - startIndex;
}
return new IntList(startIndex, numberOfItems);
}
@Override
public int indexOfId(Object itemId) {
if (!(itemId instanceof Integer)) {
return -1;
}
final int index = ((Integer) itemId).intValue();
checkExpand(index);
if (index < 0 || index >= currentSize) {
return -1;
}
return index;
}
// Container.Ordered
@Override
public Integer nextItemId(Object itemId) {
if (!(itemId instanceof Integer)) {
return null;
}
int index = ((Integer) itemId).intValue();
checkExpand(index);
if (index < 0 || index + 1 >= currentSize) {
return null;
}
return index + 1;
}
@Override
public Integer prevItemId(Object itemId) {
if (!(itemId instanceof Integer)) {
return null;
}
int index = ((Integer) itemId).intValue();
checkExpand(index);
if (index - 1 < 0 || index >= currentSize) {
return null;
}
return index - 1;
}
@Override
public Integer firstItemId() {
return currentSize == 0 ? null : 0;
}
@Override
public Integer lastItemId() {
final int size = currentSize;
return size == 0 ? null : size - 1;
}
@Override
public boolean isFirstId(Object itemId) {
if (!(itemId instanceof Integer)) {
return false;
}
final int index = ((Integer) itemId).intValue();
checkExpand(index);
final int size = currentSize;
return size > 0 && index == 0;
}
@Override
public boolean isLastId(Object itemId) {
if (!(itemId instanceof Integer)) {
return false;
}
int index = ((Integer) itemId).intValue();
checkExpand(index);
int size = currentSize;
return size > 0 && index == size - 1;
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public Item addItemAfter(Object previousItemId) {
throw new UnsupportedOperationException();
}
/**
* @throws UnsupportedOperationException
* always
*/
@Override
public Item addItemAfter(Object previousItemId, Object newItemId) {
throw new UnsupportedOperationException();
}
// Container.ItemSetChangeNotifier
@Override
@SuppressWarnings("deprecation")
public void addListener(Container.ItemSetChangeListener listener) {
super.addListener(listener);
}
@Override
public void addItemSetChangeListener(
Container.ItemSetChangeListener listener) {
super.addItemSetChangeListener(listener);
}
@Override
@SuppressWarnings("deprecation")
public void removeListener(Container.ItemSetChangeListener listener) {
super.removeListener(listener);
}
@Override
public void removeItemSetChangeListener(
Container.ItemSetChangeListener listener) {
super.removeItemSetChangeListener(listener);
}
// IntList
private static class IntList extends AbstractList<Integer> {
private final int min;
private final int size;
public IntList(int size) {
this(0, size);
}
public IntList(int min, int size) {
if (size < 0) {
throw new IllegalArgumentException("size < 0");
}
this.min = min;
this.size = size;
}
@Override
public int size() {
return size;
}
@Override
public Integer get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
return min + index;
}
}
// MyBean
public class MyBean {
private final int index;
public MyBean(int index) {
this.index = index;
}
public String getId() {
return "ROW #" + index;
}
public String getColumn1() {
return genText();
}
public String getColumn2() {
return genText();
}
private String genText() {
return "this is a line of text in row #" + index;
}
}
public void logDetails(boolean enabled) {
loggingEnabled = enabled;
}
}