/******************************************************************************* | |
* 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 2.0 | |
* which accompanies this distribution, and is available at | |
* https://www.eclipse.org/legal/epl-2.0/ | |
* | |
* SPDX-License-Identifier: EPL-2.0 | |
* | |
* 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? | |
} | |
} |