/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.bpel.ui.details.providers; import org.eclipse.bpel.ui.details.tree.ITreeNode; import org.eclipse.jface.viewers.Viewer; /** * A content provider for a tree of ITreeNode objects representing some expansion of * the underlying graph of model objects. CachedTreeContentProvider keeps track of the * parent relationships so the ITreeNode objects don't have to; however, the ITreeNode * objects *must have unique parents*, so our model objects can't represent themselves * directly. After all, our model is a graph, not a tree. Another reason to wrap our * model objects in ITreeNode objects is that there may be different tree expansions * of a particular model object in different contexts (e.g. variable/property versus * variable/part/query). * * To programatically expose a particular branch of the tree, you must first walk down * the content provider from the root to the ITreeNode you want to expose (causing the * necessary ITreeNode objects to be created). Then, you call viewer.expandToLevel() * on this ITreeNode. Using this content provider, the TreeViewer will walk up from * the given node to the deepest already-expanded item, then back down again expanding * the remaining items. */ public class ModelTreeContentProvider extends CachedTreeContentProvider { protected boolean isCondensed; public ModelTreeContentProvider(boolean isCondensed) { super(); this.isCondensed = isCondensed; } public boolean isCondensed() { return isCondensed; } @Override protected Object[] primGetChildren(Object node) { if (!(node instanceof ITreeNode)) return EMPTY_ARRAY; return ((ITreeNode)node).getChildren(); } @Override protected Object[] primGetElements(Object node) { return primGetChildren(node); } @Override protected boolean primHasChildren(Object node) { if (!(node instanceof ITreeNode)) return false; return ((ITreeNode)node).hasChildren(); } /** * Searches each of the nodes in the given array to find the node representing a * particular modelObject. * * If subtreeDepth > 0, the children of each node in the given array are recursively * searched to a depth of subtreeDepth-1. * * Values larger than 1 or 2 should be avoided whenever possible, because all of the * nodes in the subtree up to subtreeDepth have to be created and cached. The most * efficient subtreeDepth is 0. */ public ITreeNode findModelNode(Object[] nodes, Object modelObject, int subtreeDepth) { for (int i = 0; i<nodes.length; i++) { if (!(nodes[i] instanceof ITreeNode)) continue; ITreeNode treeNode = (ITreeNode)nodes[i]; if (treeNode.getModelObject().equals(modelObject)) return treeNode; } ITreeNode result = null; if (subtreeDepth > 0) { for (int i = 0; result==null && i<nodes.length; i++) { result = findModelNode(getChildren(nodes[i]), modelObject, subtreeDepth-1); } } return result; } /* IContentProvider */ @Override public void dispose() { super.dispose(); } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { super.inputChanged(viewer, oldInput, newInput); // TODO: hook model listener? } }