I’ve built my first TreeGrid component and I can’t get TreeGrid to display the hierarchy. The table is rendered flat without any tree structure.
The debug in my container class indicates the items are added with the proper hierarchy.
I’m using TreeGrid 0.7.4 and Vaadin 7.7.7.
Here’s my table class:
[code]
mport java.util.List;
import org.vaadin.treegrid.TreeGrid;
import com.magnicomp.model.Group;
import com.magnicomp.vaadin.model.container.GroupContainer;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.ui.Grid;
@SuppressWarnings(“serial”)
public class GroupTable extends TreeGrid {
private List<? extends Group> groups;
public GroupTable(List<? extends Group> items) {
setGroups(items);
init();
}
private void init() {
setContainerDataSource(createContainer());
setSelectionMode(Grid.SelectionMode.SINGLE);
setColumnReorderingAllowed(true);
setHierarchyColumn(GroupContainer.PROP_NAME);
setColumns(GroupContainer.PROP_NAME, GroupContainer.PROP_DESC);
}
private IndexedContainer createContainer() {
List<? extends Group> items = getGroups();
GroupContainer container = new GroupContainer(items);
return container;
}
protected List<? extends Group> getGroups() {
return groups;
}
protected void setGroups(List<? extends Group> groups) {
this.groups = groups;
}
}
[/code]Here is my container class:
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.vaadin.treegrid.container.Measurable;
import com.magnicomp.common.Validate;
import com.magnicomp.except.OperationFailedException;
import com.magnicomp.except.RecursionException;
import com.magnicomp.model.Group;
import com.magnicomp.model.GroupType;
import com.magnicomp.model.Origin;
import com.magnicomp.trace.Trace;
import com.magnicomp.trace.TraceFactory;
import com.magnicomp.ui.container.GroupContainerBuilder;
import com.magnicomp.ui.property.GroupPropertyManager;
import com.magnicomp.vaadin.model.container.GroupContainer;
import com.vaadin.data.Collapsible;
import com.vaadin.data.Item;
import com.vaadin.data.util.HierarchicalContainer;
@SuppressWarnings("serial")
public class GroupContainer extends HierarchicalContainer implements Collapsible, Measurable {
private Trace log = TraceFactory.create(this);
private List<? extends Group> groups;
private HashMap<Group,Object> entityToItemId = new HashMap<>();
private HashMap<Object,Group> itemIdToEntity = new HashMap<>();
private HashMap<Object,Boolean> expandedNodes = new HashMap<>();
/*
* Use property name values which match the Hibernate entity names.
*/
public final static String PROP_OBJECT = GroupContainerBuilder.PROP_OBJECT;
public final static String PROP_NAME = GroupPropertyManager.ID_NAME;
public final static String PROP_DN = GroupPropertyManager.ID_DISTINGUISHEDNAME;
public final static String PROP_LABEL = GroupPropertyManager.ID_LABEL;
public final static String PROP_DESC = GroupPropertyManager.ID_DESCRIPTION;
public final static String PROP_PARENT_NAME = GroupPropertyManager.ID_PARENT;
public final static String PROP_CANONICALSOURCE = GroupPropertyManager.ID_CANONICALSOURCE;
public final static String PROP_ID = GroupPropertyManager.ID_ID;
public final static String PROP_ORIGIN = GroupPropertyManager.ID_ORIGIN;
public final static String PROP_TYPE = GroupPropertyManager.ID_TYPE;
public GroupContainer(List<? extends Group> groups) {
this.groups = groups;
init();
}
private void init() {
String m = "init";
int d = 0;
log.debug(m, d, "Initializing");
addContainerProperty(PROP_OBJECT, Group.class, null);
addContainerProperty(PROP_NAME, String.class, "");
addContainerProperty(PROP_PARENT_NAME, String.class, "");
addContainerProperty(PROP_DESC, String.class, "");
addContainerProperty(PROP_DN, String.class, "");
addContainerProperty(PROP_LABEL, String.class, "");
addContainerProperty(PROP_CANONICALSOURCE, String.class, "");
addContainerProperty(PROP_ID, String.class, "");
addContainerProperty(PROP_ORIGIN, Origin.class, null);
addContainerProperty(PROP_TYPE, GroupType.class, null);
populateItems();
showDebugTree();
// log.debug(m, d+1, "Sorting container");
// boolean ascending = true;
// sort(new Object [] { PROP_NAME }, new boolean []
{ ascending });
}
private void showDebugTree() {
String m = "showDebugTree";
int d = 0;
for (Object itemId : getItemIds()) {
Group group = itemIdToEntity.get(itemId);
log.debug(m, d, "ITEM Group: \"%s\" ID: %s", group.getName(), itemId);
Collection<?> childrenIds = getChildren(itemId);
if (childrenIds != null && childrenIds.size() > 0) {
for (Object childId : childrenIds) {
Group child = itemIdToEntity.get(childId);
log.debug(m, d+1, "CHILD Group: \"%s\" ID: %s", child.getName(), itemId);
}
}
}
}
private void populateItems() {
String m = "populateItems";
int d = 0;
log.debug(m, d, "Populating Entity data");
for (Group group : groups) {
if (entityToItemId.get(group) != null)
continue;
populateItem(group, 0);
}
}
/***
* -RECURSE-
* Populate the given item in the container.
* @param group
* @param depth
* @return
*/
@SuppressWarnings("unchecked")
private Object populateItem(Group group, int depth) {
String m = "populateItem";
int d = depth;
if (depth >= 100)
throw new RecursionException("Recursion problem at depth " + depth);
// Sanity check
if (group == null || group.getName() == null)
return null;
log.debug(m, d, "Group: \"%s\" dbID: %s",
group.getName(), group.getDbID());
Group parent = group.getParent();
Object parentId = null;
if (parent != null) {
log.debug(m, d+1, "Parent is \"%s\"", parent.getName());
parentId = entityToItemId.get(parent);
if (parentId == null) {
/*
* -DESCEND-
* Parent has not yet been added so do so now
*/
log.debug(m, d+1, "Add parent first");
parentId = populateItem(parent, d+1);
Validate.notNull(parentId, "PopulateItem for parent failed to return parent ID: " + parent);
log.debug(m, d+1, "Added parent with ID: %s", parentId);
}
}
Object itemId = null;
if (parentId != null)
itemId = addItemAfter(parentId);
else
itemId = addItem();
log.debug(m, d+1, "Adding itemId: %s (%s)", itemId, group.getName());
Item item = getItem(itemId);
if (item == null)
throw new OperationFailedException("Group addItem %s failed", itemId);
item.getItemProperty(PROP_OBJECT).setValue(group);
item.getItemProperty(PROP_NAME).setValue(group.getName());
item.getItemProperty(PROP_DESC).setValue(group.getDescription());
// Always set the PARENT property even if null
item.getItemProperty(PROP_PARENT_NAME).setValue((parent != null) ? parent.getName() : null);
item.getItemProperty(PROP_DN).setValue(group.getDistinguishedName());
item.getItemProperty(PROP_LABEL).setValue(group.getLabel());
item.getItemProperty(PROP_CANONICALSOURCE).setValue(group.getCanonicalSource());
item.getItemProperty(PROP_ID).setValue(group.getID());
item.getItemProperty(PROP_ORIGIN).setValue(group.getOrigin());
item.getItemProperty(PROP_TYPE).setValue(group.getType());
if (parentId != null) {
log.debug(m, d+2, "Set itemID %s parent to %s (%s)",
itemId, parentId, (parent != null) ? parent.getName() : null);
setParent(itemId, parentId);
}
boolean childrenAllowed = (group.getChildren() != null && group.getChildren().size() > 0) ? true : false;
// setChildrenAllowed(itemId, childrenAllowed);
setChildrenAllowed(itemId, true);
entityToItemId.put(group, itemId);
itemIdToEntity.put(itemId, group);
return itemId;
}
@Override
public int getDepth(Object itemId) {
String m = "getDepth";
int d = 0;
int depth = 0;
while (!isRoot(itemId)) {
depth ++;
itemId = getParent(itemId);
}
log.debug(m, d, "ItemID: %s Depth: %s", itemId, depth);
return depth;
}
@Override
public boolean hasChildren(Object itemId) {
Group group = itemIdToEntity.get(itemId);
Validate.notNull(group, "Unable to find group for itemID: " + itemId);
boolean value = (group.getChildren() != null && group.getChildren().size() > 0) ? true : false;
return value;
}
@Override
public void setCollapsed(Object itemId, boolean collapsed) {
String m = "setCollapsed";
int d = 0;
log.debug(m, d, "Set collapsed itemID: %s Collapsed: %s", itemId, collapsed);
expandedNodes.put(itemId, !collapsed);
}
@Override
public boolean isCollapsed(Object itemId) {
Boolean collapsed = expandedNodes.get(itemId);
if (collapsed == null)
return false;
return collapsed;
}
}