package com.vaadin.tests.components.treetable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import com.vaadin.tests.components.table.Tables;
import com.vaadin.v7.data.Container;
import com.vaadin.v7.data.Container.Hierarchical;
import com.vaadin.v7.data.util.HierarchicalContainer;
import com.vaadin.v7.ui.Table;
import com.vaadin.v7.ui.Table.CellStyleGenerator;
import com.vaadin.v7.ui.Tree.CollapseEvent;
import com.vaadin.v7.ui.Tree.CollapseListener;
import com.vaadin.v7.ui.Tree.ExpandEvent;
import com.vaadin.v7.ui.Tree.ExpandListener;
import com.vaadin.v7.ui.TreeTable;
public class TreeTableTest extends Tables<TreeTable>
implements CollapseListener, ExpandListener {
@Override
protected Class<TreeTable> getTestClass() {
return TreeTable.class;
}
private int rootItemIds = 3;
private CellStyleGenerator rootGreenSecondLevelRed = new com.vaadin.v7.ui.Table.CellStyleGenerator() {
@Override
public String getStyle(Table source, Object itemId, Object propertyId) {
if (propertyId != null) {
return null;
}
Hierarchical c = getComponent().getContainerDataSource();
if (c.isRoot(itemId)) {
return "green";
}
Object parent = c.getParent(itemId);
if (!c.isRoot(parent)) {
return "red";
}
return null;
}
@Override
public String toString() {
return "Root green, second level red";
}
};
private CellStyleGenerator evenItemsBold = new CellStyleGenerator() {
@Override
public String getStyle(Table source, Object itemId, Object propertyId) {
if (propertyId != null) {
return null;
}
Hierarchical c = getComponent().getContainerDataSource();
int idx = 0;
for (Iterator<?> i = c.getItemIds().iterator(); i.hasNext();) {
Object id = i.next();
if (id == itemId) {
if (idx % 2 == 1) {
return "bold";
} else {
return null;
}
}
idx++;
}
return null;
}
@Override
public String toString() {
return "Even items bold";
}
};
@Override
protected void createActions() {
super.createActions();
// Causes container changes so doing this first..
createRootItemSelectAction(CATEGORY_DATA_SOURCE);
createExpandCollapseActions(CATEGORY_FEATURES);
createChildrenAllowedAction(CATEGORY_DATA_SOURCE);
createListeners(CATEGORY_LISTENERS);
// createItemStyleGenerator(CATEGORY_FEATURES);
createBooleanAction("Animate collapse/expand", CATEGORY_STATE, false,
animationCommand);
// TODO: DropHandler
// TODO: DragMode
// TODO: ActionHandler
}
@Override
protected Container createContainer(int properties, int items) {
return createHierarchicalContainer(properties, items, rootItemIds);
}
private void createListeners(String category) {
createBooleanAction("Item click listener", category, false,
itemClickListenerCommand);
createBooleanAction("Expand listener", category, false,
expandListenerCommand);
createBooleanAction("Collapse listener", category, false,
collapseListenerCommand);
}
private Container.Hierarchical createHierarchicalContainer(int properties,
int items, int roots) {
Container.Hierarchical c = new HierarchicalContainer();
populateContainer(c, properties, items);
if (items <= roots) {
return c;
}
// "roots" roots, each with
// "firstLevel" children, two with no children (one with childAllowed,
// one without)
// ("firstLevel"-2)*"secondLevel" children ("secondLevel"/2 with
// childAllowed, "secondLevel"/2 without)
// N*M+N*(M-2)*C = items
// items=N(M+MC-2C)
// Using secondLevel=firstLevel/2 =>
// items = roots*(firstLevel+firstLevel*firstLevel/2-2*firstLevel/2)
// =roots*(firstLevel+firstLevel^2/2-firstLevel)
// = roots*firstLevel^2/2
// => firstLevel = sqrt(items/roots*2)
int firstLevel = (int) Math.ceil(Math.sqrt(items / roots * 2.0));
int secondLevel = firstLevel / 2;
while (roots * (1 + 2 + (firstLevel - 2) * secondLevel) < items) {
// Increase something so we get enough items
secondLevel++;
}
List<Object> itemIds = new ArrayList<>(c.getItemIds());
int nextItemId = roots;
for (int rootIndex = 0; rootIndex < roots; rootIndex++) {
// roots use items 0..roots-1
Object rootItemId = itemIds.get(rootIndex);
// force roots to be roots even though they automatically should be
c.setParent(rootItemId, null);
for (int firstLevelIndex = 0; firstLevelIndex < firstLevel; firstLevelIndex++) {
if (nextItemId >= items) {
break;
}
Object firstLevelItemId = itemIds.get(nextItemId++);
c.setParent(firstLevelItemId, rootItemId);
if (firstLevelIndex < 2) {
continue;
}
// firstLevelChildren 2.. have child nodes
for (int secondLevelIndex = 0; secondLevelIndex < secondLevel; secondLevelIndex++) {
if (nextItemId >= items) {
break;
}
Object secondLevelItemId = itemIds.get(nextItemId++);
c.setParent(secondLevelItemId, firstLevelItemId);
}
}
}
return c;
}
private void createRootItemSelectAction(String category) {
LinkedHashMap<String, Integer> options = new LinkedHashMap<>();
for (int i = 1; i <= 10; i++) {
options.put(String.valueOf(i), i);
}
options.put("20", 20);
options.put("50", 50);
options.put("100", 100);
createSelectAction("Number of root items", category, options, "3",
rootItemIdsCommand);
}
private void createExpandCollapseActions(String category) {
LinkedHashMap<String, Object> options = new LinkedHashMap<>();
for (Object id : getComponent().getItemIds()) {
options.put(id.toString(), id);
}
createMultiClickAction("Expand", category, options, expandItemCommand,
null);
// createMultiClickAction("Expand recursively", category, options,
// expandItemRecursivelyCommand, null);
createMultiClickAction("Collapse", category, options,
collapseItemCommand, null);
}
private void createChildrenAllowedAction(String category) {
LinkedHashMap<String, Object> options = new LinkedHashMap<>();
for (Object id : getComponent().getItemIds()) {
options.put(id.toString(), id);
}
createMultiToggleAction("Children allowed", category, options,
setChildrenAllowedCommand, true);
}
/*
* COMMANDS
*/
private Command<TreeTable, Integer> rootItemIdsCommand = new Command<TreeTable, Integer>() {
@Override
public void execute(TreeTable c, Integer value, Object data) {
rootItemIds = value;
updateContainer();
}
};
private Command<TreeTable, Object> expandItemCommand = new Command<TreeTable, Object>() {
@Override
public void execute(TreeTable c, Object itemId, Object data) {
c.setCollapsed(itemId, false);
}
};
private Command<TreeTable, Object> collapseItemCommand = new Command<TreeTable, Object>() {
@Override
public void execute(TreeTable c, Object itemId, Object data) {
c.setCollapsed(itemId, true);
}
};
private Command<TreeTable, Boolean> setChildrenAllowedCommand = new Command<TreeTable, Boolean>() {
@Override
public void execute(TreeTable c, Boolean areChildrenAllowed,
Object itemId) {
c.setChildrenAllowed(itemId, areChildrenAllowed);
}
};
private Command<TreeTable, Boolean> expandListenerCommand = new Command<TreeTable, Boolean>() {
@Override
public void execute(TreeTable c, Boolean value, Object data) {
if (value) {
c.addListener((ExpandListener) TreeTableTest.this);
} else {
c.removeListener((ExpandListener) TreeTableTest.this);
}
}
};
private Command<TreeTable, Boolean> collapseListenerCommand = new Command<TreeTable, Boolean>() {
@Override
public void execute(TreeTable c, Boolean value, Object data) {
if (value) {
c.addListener((CollapseListener) TreeTableTest.this);
} else {
c.removeListener((CollapseListener) TreeTableTest.this);
}
}
};
protected Command<TreeTable, Boolean> animationCommand = new Command<TreeTable, Boolean>() {
@Override
public void execute(TreeTable c, Boolean enabled, Object data) {
c.setAnimationsEnabled(enabled);
}
};
@Override
public void nodeCollapse(CollapseEvent event) {
log(event.getClass().getSimpleName() + ": " + event.getItemId());
}
@Override
public void nodeExpand(ExpandEvent event) {
log(event.getClass().getSimpleName() + ": " + event.getItemId());
}
}