/*
* This software is Copyright 2005,2006,2007,2008 Langdale Consultants.
* Langdale Consultants can be contacted at: http://www.langdale.com.au
*/
package au.com.langdale.jena;
import java.util.HashMap;
import java.util.List;
import org.eclipse.jface.viewers.IElementComparer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import au.com.langdale.ui.util.IconCache;
import au.com.langdale.jena.TreeModelBase.Empty;
import au.com.langdale.jena.TreeModelBase.Node;
import au.com.langdale.jena.TreeModelBase.NodeListener;
import au.com.langdale.kena.OntResource;
/**
* A JFace content provider that links a TreeModel to a Viewer.
* This provider in combination with a TreeModel translates a graph
* or resources to the displayed tree. The TreeModel is assigned
* to the Viewer's input, the provider to the Viewer's contentProvider.
*/
public class JenaTreeProvider implements ITreeContentProvider {
private boolean showRoot;
private TreeModelBase tree;
private static class LabelAdapter extends LabelProvider {
@Override
public Image getImage(Object element) {
return IconCache.getIcons().get(element);
}
@Override
public String getText(Object element) {
return element.toString();
}
}
private static class Comparer implements IElementComparer {
public boolean equals(Object a, Object b) {
return a == b || a.getClass().equals(b.getClass()) && valueOf(a).equals(valueOf(b));
}
private Object valueOf(Object element) {
if( element instanceof Node) {
Node node = (Node) element;
OntResource subject = node.getSubject();
if( subject != null)
return subject;
}
return element;
}
public int hashCode(Object element) {
return valueOf(element).hashCode();
}
}
private static class TreeState {
private TreePath[] expanded;
private ISelection selected;
public TreeState(TreeViewer viewer) {
expanded = viewer.getExpandedTreePaths();
selected = viewer.getSelection();
}
public void applyTo( TreeViewer viewer) {
viewer.setExpandedTreePaths(expanded);
viewer.setSelection(selected);
}
@Override
public String toString() {
StringBuffer result = new StringBuffer();
result.append("TreeState:\n");
for( int i = 0; i < expanded.length; i++) {
result.append(" ");
result.append(expanded[i].getLastSegment().toString());
result.append("\n");
}
result.append("Selection:\n ");
result.append(selected.toString());
result.append("\n");
return result.toString();
}
}
private static class RefreshAdapter implements NodeListener {
private TreeViewer viewer;
private HashMap states = new HashMap();
private Class currentRootType = Empty.class;
private Class getRootType(TreeViewer viewer) {
Object input = viewer.getInput();
if( input instanceof TreeModelBase)
return ((TreeModelBase)input).getRoot().getClass();
else
return input.getClass();
}
public RefreshAdapter(TreeViewer viewer) {
this.viewer = viewer;
}
public void nodeChanged(Node node) {
viewer.update(node, null);
}
public void nodeStructureChanged(Node node) {
saveState();
if(node.getParent() == null)
viewer.refresh();
else
viewer.refresh(node);
currentRootType = getRootType(viewer);
restoreState();
}
private void saveState() {
TreeState state = new TreeState(viewer);
// System.out.println("Save: " + currentRootType + "\n" + state);
states.put(currentRootType, state);
}
private void restoreState() {
TreeState state = (TreeState) states.get(currentRootType);
// System.out.println("Restore: " + currentRootType);
if( state != null) {
// System.out.println(state);
state.applyTo(viewer);
}
}
}
public JenaTreeProvider(boolean showRoot) {
this.showRoot = showRoot;
}
public boolean isShowRoot() {
return showRoot;
}
public void setShowRoot(boolean showRoot) {
this.showRoot = showRoot;
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
dispose();
if( newInput instanceof TreeModelBase ) {
tree = (TreeModelBase) newInput;
if( viewer instanceof TreeViewer)
tree.setNodeListener(new RefreshAdapter((TreeViewer) viewer));
if( viewer instanceof StructuredViewer) {
StructuredViewer struct = ((StructuredViewer)viewer);
struct.setComparer(new Comparer());
struct.setLabelProvider(new LabelAdapter());
}
}
}
public Object getParent(Object element) {
Node parent = ((Node)element).getParent();
if( showRoot || parent == null || parent.getParent() != null)
return parent;
else
return null;
}
public Object[] getChildren(Object element) {
if( element instanceof Node)
return ((Node)element).getChildren().toArray();
else
return getElements(element);
}
public boolean hasChildren(Object element) {
if( element instanceof Node) {
Node node = (Node) element;
return node.getAllowsChildren() && ! node.isLeaf();
}
return true;
}
public Object[] getElements(Object inputElement) {
if( inputElement instanceof TreeModelBase) {
TreeModelBase tree = (TreeModelBase) inputElement;
Node root = tree.getRoot();
if( root != null ) {
if( showRoot )
return new Object[] {root};
List children = root.getChildren();
if( ! children.isEmpty())
return children.toArray();
}
return new Object[] {tree.createEmpty("No information available.")};
}
return new Object[0];
}
public void dispose() {
if( tree != null) {
tree.setNodeListener(null);
tree = null;
}
}
/**
* Utility to combine a TreeViewer, TreeModel and new JenaTreeProvider to
* create a display of a resource hierarchy.
*/
public static void displayJenaTree(TreeViewer viewer, TreeModelBase tree) {
displayJenaTree(viewer, tree, false);
}
/**
* Utility to combine a TreeViewer, TreeModel and new JenaTreeProvider to
* create a display of a resource hierarchy.
* Optionally display the root node.
*/
public static void displayJenaTree(StructuredViewer viewer, TreeModelBase tree, boolean showRoot) {
viewer.setContentProvider(new JenaTreeProvider(showRoot));
viewer.setInput(tree);
}
}