This is my exercise code to create a Tree List with expand/collapsible subgroups.
The code was derived from Vogellas Nebula NatTable – Commands & Events – Tutorial.
My Code
The data rows of the table:
package tryout.treelist;
public class Area {
private String name;
private long population;
public Area(String name, long population) {
super();
this.name = name;
this.population = population;
}
public String getName() {
return name;
}
public long getPopulation() {
return population;
}
@Override
public String toString() {
return name + " Population: " + population;
}
}
The tree node wrapper
package tryout.treelist;
import java.util.ArrayList;
import java.util.List;
public class TreeItem<T> {
private T item;
private TreeItem<T> parent;
private List<TreeItem<T>> children = new ArrayList<>();
public TreeItem(T item, TreeItem<T> parent){
this.item=item;
this.parent=parent;
this.parent.addChild(this);
}
public TreeItem(T content) {
this.item=content;
}
private void addChild(TreeItem<T> treeItem) {
children.add(treeItem);
}
public TreeItem<T> getParent() {
return parent;
}
public boolean hasChildren() {
return children.size() > 0;
}
public T getItem() {
return item;
}
}
The tree format definition for such nodes:
package tryout.treelist;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import ca.odell.glazedlists.TreeList;
class TreeItemFormat implements TreeList.Format<TreeItem<Area>> {
@Override
public void getPath(List<TreeItem<Area>> path, TreeItem<Area> element) {
List<TreeItem<Area>> path1 = new ArrayList<>();
if (element.getParent() != null) {
getPath(path1, element.getParent());
path.addAll(path1);
}
path.add(element);
}
@Override
public boolean allowsChildren(TreeItem<Area> element) {
return element.hasChildren();
}
@Override
public Comparator<? super TreeItem<Area>> getComparator(int depth) {
return (o1, o2) -> o1.getItem().toString().compareTo(o2.getItem().toString());
}
}
The GUI view defining the NAT table and the data fed to it:
package tryout.treelist;
import java.util.Collection;
import javax.annotation.PostConstruct;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.data.ExtendedReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.tree.GlazedListTreeData;
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.tree.GlazedListTreeRowModel;
import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.tree.TreeLayer;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import com.google.common.collect.ImmutableList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.TreeList;
public class SimpleTreePart {
@PostConstruct
public void createComposite(Composite parent) {
parent.setLayout(new GridLayout());
// Properties of the Area items inside the TreeItems
String[] propertyNames = { "item.name", "item.population" };
IColumnPropertyAccessor<TreeItem<Area>> columnPropertyAccessor = new ExtendedReflectiveColumnPropertyAccessor<TreeItem<Area>>(
propertyNames);
EventList<TreeItem<Area>> eventList = GlazedLists.eventList(getSampleAreaTreeItems());
TreeList<TreeItem<Area>> treeList = new TreeList<TreeItem<Area>>(eventList, new TreeItemFormat(),
TreeList.nodesStartExpanded());
ListDataProvider<TreeItem<Area>> dataProvider = new ListDataProvider<>(treeList, columnPropertyAccessor);
DataLayer dataLayer = new DataLayer(dataProvider);
setColumWidthPercentage(dataLayer);
GlazedListTreeData<TreeItem<Area>> glazedListTreeData = new GlazedListTreeData<>(treeList);
GlazedListTreeRowModel<TreeItem<Area>> glazedListTreeRowModel = new GlazedListTreeRowModel<>(
glazedListTreeData);
TreeLayer treeLayer = new TreeLayer(dataLayer, glazedListTreeRowModel);
treeLayer.setRegionName(GridRegion.BODY);
new NatTable(parent, treeLayer, true);
GridLayoutFactory.fillDefaults().generateLayout(parent);
}
private Collection<TreeItem<Area>> getSampleAreaTreeItems() {
TreeItem<Area> globe = new TreeItem<Area>(new Area("Globe", 8000));
TreeItem<Area> europe = new TreeItem<Area>(new Area("Europe", 983), globe);
TreeItem<Area> switzerland = new TreeItem<Area>(new Area("Switzerland", 8), europe);
TreeItem<Area> germany = new TreeItem<Area>(new Area("Germany", 85), europe);
TreeItem<Area> russia = new TreeItem<Area>(new Area("Russia", 140), europe);
TreeItem<Area> asia = new TreeItem<Area>(new Area("Asia", 3203), globe);
TreeItem<Area> japan = new TreeItem<Area>(new Area("Japan", 203), asia);
TreeItem<Area> china = new TreeItem<Area>(new Area("China", 1230), asia);
TreeItem<Area> india = new TreeItem<Area>(new Area("India", 1130), asia);
return ImmutableList.of(globe, asia, japan, china, india, europe, switzerland, germany, russia);
}
private void setColumWidthPercentage(DataLayer dataLayer) {
dataLayer.setColumnPercentageSizing(true);
dataLayer.setColumnWidthPercentageByPosition(0, 50);
dataLayer.setColumnWidthPercentageByPosition(1, 50);
}
}
And the main class to run the code:
package tryout.treelist;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class TreeListMain {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(300, 130);
shell.setText("Tree List Example");
shell.setLayout(new RowLayout());
new SimpleTreePart().createComposite(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}