Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Bokowski2007-05-01 02:02:55 +0000
committerBoris Bokowski2007-05-01 02:02:55 +0000
commit73d9a17c9f3145865eba8888e62c3afa14d15a8c (patch)
tree318867466253fe974dced9e8e75b35e625f0ac3a
parent999d2beac0dc4bff388c843e03dd052b5518f873 (diff)
downloadorg.eclipse.e4.databinding-73d9a17c9f3145865eba8888e62c3afa14d15a8c.tar.gz
org.eclipse.e4.databinding-73d9a17c9f3145865eba8888e62c3afa14d15a8c.tar.xz
org.eclipse.e4.databinding-73d9a17c9f3145865eba8888e62c3afa14d15a8c.zip
-rw-r--r--bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java8
-rw-r--r--bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java25
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java8
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java25
-rw-r--r--bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/IPrefetchingTree.java37
-rw-r--r--bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/OrderedTreeContentProvider.java433
-rw-r--r--bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/OrderedTreeNode.java306
-rw-r--r--bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/PrefetchingTree.java40
-rw-r--r--bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/UnorderedTreeContentProvider.java422
-rw-r--r--bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/IParentProvider.java28
-rw-r--r--bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/TreeNode.java (renamed from bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/UnorderedTreeNode.java)101
-rw-r--r--bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/UnorderedTreeContentProvider.java528
-rw-r--r--examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/contentprovider/test/TreeContentProviderTest.java130
13 files changed, 739 insertions, 1352 deletions
diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java
index a60608e4..39a058b2 100644
--- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java
+++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java
@@ -42,7 +42,15 @@ public abstract class AbstractObservableSet extends AbstractObservable implement
protected AbstractObservableSet() {
this(Realm.getDefault());
}
+
+ protected void firstListenerAdded() {
+ super.firstListenerAdded();
+ }
+ protected void lastListenerRemoved() {
+ super.lastListenerRemoved();
+ }
+
protected AbstractObservableSet(Realm realm) {
super(realm);
changeSupport = new ChangeSupport(realm){
diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java
index 6b5e5f65..81941c80 100644
--- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java
+++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java
@@ -15,27 +15,22 @@ import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.set.IObservableSet;
/**
- * Objects that implement this interface are capable of describing a tree by
- * returning the set of children of any given element in the tree.
- *
- * @since 3.3
+ * @since 1.0
+ *
*/
public interface IUnorderedTreeProvider {
-
/**
- * @return the realm shared by all child sets
+ * @return the realm for the createChildSet method
*/
public Realm getRealm();
-
+
/**
- * Returns the children of the given element, or null if the element is a
- * leaf node. The caller of this method is expected to dispose the result
- * set when it is no longer needed.
+ * Returns the children of the given element, or null if the element is a leaf node.
+ * The caller of this method is expected to dispose the result set when it is no
+ * longer needed.
*
- * @param element
- * the tree path of the element to query
- * @return the children of the given element, or null if the element is a
- * leaf node
+ * @param element element to query
+ * @return the children of the given element, or null if the element is a leaf node
*/
- public IObservableSet createChildSet(TreePath element);
+ IObservableSet createChildSet(Object element);
}
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java
index a60608e4..39a058b2 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java
@@ -42,7 +42,15 @@ public abstract class AbstractObservableSet extends AbstractObservable implement
protected AbstractObservableSet() {
this(Realm.getDefault());
}
+
+ protected void firstListenerAdded() {
+ super.firstListenerAdded();
+ }
+ protected void lastListenerRemoved() {
+ super.lastListenerRemoved();
+ }
+
protected AbstractObservableSet(Realm realm) {
super(realm);
changeSupport = new ChangeSupport(realm){
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java
index 6b5e5f65..81941c80 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/tree/IUnorderedTreeProvider.java
@@ -15,27 +15,22 @@ import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.set.IObservableSet;
/**
- * Objects that implement this interface are capable of describing a tree by
- * returning the set of children of any given element in the tree.
- *
- * @since 3.3
+ * @since 1.0
+ *
*/
public interface IUnorderedTreeProvider {
-
/**
- * @return the realm shared by all child sets
+ * @return the realm for the createChildSet method
*/
public Realm getRealm();
-
+
/**
- * Returns the children of the given element, or null if the element is a
- * leaf node. The caller of this method is expected to dispose the result
- * set when it is no longer needed.
+ * Returns the children of the given element, or null if the element is a leaf node.
+ * The caller of this method is expected to dispose the result set when it is no
+ * longer needed.
*
- * @param element
- * the tree path of the element to query
- * @return the children of the given element, or null if the element is a
- * leaf node
+ * @param element element to query
+ * @return the children of the given element, or null if the element is a leaf node
*/
- public IObservableSet createChildSet(TreePath element);
+ IObservableSet createChildSet(Object element);
}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/IPrefetchingTree.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/IPrefetchingTree.java
deleted file mode 100644
index ca443cff..00000000
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/IPrefetchingTree.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2007 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.jface.internal.databinding.internal.viewers;
-
-/**
- * @since 3.3
- *
- */
-public interface IPrefetchingTree {
- /**
- * Returns true if and only if the content provider should
- * try to prefetch the children of the given node.
- * Prefetching uses unused CPU cycles to fetch the children
- * of visible nodes so that they expand faster. This will
- * generally cause the application to run faster so should
- * usually be enabled.
- * <p>
- * In some circumstances computing the children of a node may
- * require network resources that need to be conserved, so
- * prefetching can be explicitly disabled these nodes. This
- * means that the user will need to wait for a "pending" node
- * every time they expand the parent node.
- * </p>
- *
- * @param parentNode
- * @return true iff the children should be eagerly fetched
- */
- boolean shouldPrefetch(Object parentNode);
-}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/OrderedTreeContentProvider.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/OrderedTreeContentProvider.java
deleted file mode 100644
index 783ded31..00000000
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/OrderedTreeContentProvider.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2007 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.jface.internal.databinding.internal.viewers;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.core.databinding.observable.Diffs;
-import org.eclipse.core.databinding.observable.list.IObservableList;
-import org.eclipse.core.databinding.observable.set.AbstractObservableSet;
-import org.eclipse.core.databinding.observable.set.IObservableSet;
-import org.eclipse.core.databinding.observable.set.SetDiff;
-import org.eclipse.core.internal.databinding.observable.tree.IOrderedTreeProvider;
-import org.eclipse.jface.viewers.ITreePathContentProvider;
-import org.eclipse.jface.viewers.ITreeViewerListener;
-import org.eclipse.jface.viewers.TreeExpansionEvent;
-import org.eclipse.jface.viewers.TreePath;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-
-/**
- * Converts an IOrderedTreeProvider into an ITreeContentProvider that is
- * suitable for use with a JFace TreeViewer.
- *
- * <p>
- * This content provider works correctly with trees containing duplicate
- * elements.
- * </p>
- *
- * @since 3.3
- */
-public class OrderedTreeContentProvider implements ITreePathContentProvider {
-
- private HashMap mapElementToTreeNode = new HashMap();
-
- private LinkedList enqueuedPrefetches = new LinkedList();
-
- class KnownElementsSet extends AbstractObservableSet {
-
- /**
- */
- protected KnownElementsSet() {
- super(provider.getRealm());
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.internal.databinding.provisional.observable.set.AbstractObservableSet#getWrappedSet()
- */
- protected Set getWrappedSet() {
- return mapElementToTreeNode.keySet();
- }
-
- void doFireDiff(Set added, Set removed) {
- fireSetChange(Diffs.createSetDiff(added, removed));
- }
-
- void doFireStale(boolean isStale) {
- if (isStale) {
- fireStale();
- } else {
- fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
- Collections.EMPTY_SET));
- }
- }
-
- public Object getElementType() {
- return Object.class;
- }
-
- protected void fireSetChange(SetDiff diff) {
- super.fireSetChange(diff);
- }
- }
-
- KnownElementsSet elements;
-
- private ITreeViewerListener expandListener = new ITreeViewerListener() {
- public void treeCollapsed(TreeExpansionEvent event) {
- }
-
- public void treeExpanded(TreeExpansionEvent event) {
- }
- };
-
- private IPrefetchingTree prefetchingTree;
-
- private IOrderedTreeProvider provider;
-
- private Object pendingNode;
-
- private int avoidViewerUpdates;
-
- private TreeViewer treeViewer;
-
- private int staleCount = 0;
-
- private boolean useRefresh;
-
- private int maxPrefetches = -1;
-
- /**
- * Constructs a content provider that will render the given tree in a
- * TreeViewer.
- *
- * @param provider
- * IObservableTree that provides the contents of the tree. The
- * given provider may optionally implement IPrefetchingTree if it
- * wants to selectively enable or disable prefetching from
- * particular nodes.
- * @param pendingNode
- * element to insert whenever a node is being fetched in the
- * background
- */
- public OrderedTreeContentProvider(IOrderedTreeProvider provider,
- Object pendingNode) {
- this(provider, pendingNode, false);
- }
-
- /**
- * Constructs a content provider that will render the given tree in a
- * TreeViewer.
- *
- * @param provider
- * IObservableTree that provides the contents of the tree
- * @param pendingNode
- * element to insert whenever a node is being fetched in the
- * background
- * @param useRefresh
- * true = notify the viewer of changes by calling refresh(...),
- * false = notify the viewer of changes by calling add(...) and
- * remove(...). Using false is more efficient, but may not work
- * with TreeViewer subclasses.
- */
- public OrderedTreeContentProvider(IOrderedTreeProvider provider,
- Object pendingNode, boolean useRefresh) {
- this.provider = provider;
- this.prefetchingTree = PrefetchingTree.getPrefetchingTree(provider);
- this.pendingNode = pendingNode;
- this.useRefresh = useRefresh;
- elements = new KnownElementsSet();
- }
-
- /**
- * Sets the maximum number of pending prefetches.
- *
- * @param maxPrefetches
- */
- public void setMaxPrefetches(int maxPrefetches) {
- this.maxPrefetches = maxPrefetches;
- }
-
- /* package */IObservableList createChildList(TreePath treePath) {
- Object[] segments = new Object[treePath.getSegmentCount()];
- for (int i = 0; i < segments.length; i++) {
- segments[i] = treePath.getSegment(i);
- }
- return provider.createChildList(new org.eclipse.core.internal.databinding.observable.tree.TreePath(segments));
- }
-
- /* package */void remove(Object element, List removals, boolean lastElement) {
- if (avoidViewerUpdates == 0) {
- for (Iterator iter = removals.iterator(); iter.hasNext();) {
- Object next = iter.next();
-
- OrderedTreeNode nextNode = (OrderedTreeNode) mapElementToTreeNode
- .get(next);
- if (nextNode != null) {
- nextNode.removeParent(element);
- removeIfUnused(nextNode);
- }
- }
-
- if (lastElement || useRefresh) {
- treeViewer.refresh(element);
- } else {
- treeViewer.remove(element, removals.toArray());
- }
- }
- }
-
- /* package */void add(TreePath element, List additions) {
- if (avoidViewerUpdates == 0) {
- // Handle new parents
- addParent(element, additions);
- if (useRefresh) {
- treeViewer.refresh(element);
- } else {
- treeViewer.add(element, additions);
- }
- }
- }
-
- /* package */void insert(TreePath element, Object addition, int position) {
- if (avoidViewerUpdates == 0) {
- // Handle new parents
- addParent(element, Collections.singletonList(addition));
- if (useRefresh) {
- treeViewer.refresh(element);
- } else {
- treeViewer.insert(element, addition, position);
- }
- }
- }
-
- /**
- * Ensures that the given set of children have the given parent as one of
- * their parents.
- *
- * @param parentPath
- * @param children
- */
- private void addParent(TreePath parentPath, List children) {
- for (Iterator iter = children.iterator(); iter.hasNext();) {
- Object next = iter.next();
-
- OrderedTreeNode nextNode = getNode(parentPath.createChildPath(next));
- nextNode.addParent(parentPath);
- }
- }
-
- /**
- * Returns the element that should be inserted into the tree when fetching
- * the children of the node that is both stale and empty.
- *
- * @return the element that should be inserted into the tree when fetching
- * the children of a node that is stale and empty
- */
- public final Object getPendingNode() {
- return pendingNode;
- }
-
- /**
- * Returns the IObservableList representing the children of the given node.
- * Never null.
- *
- * @param parent
- * parent element. Must be a valid node from the tree.
- * @return the list of children of the given parent node
- */
- public IObservableList getChildrenList(TreePath parent) {
- IObservableList result = getNode(parent).getChildrenList();
-
- return result;
- }
-
- public void dispose() {
- if (treeViewer != null) {
- try {
- avoidViewerUpdates++;
- enqueuedPrefetches.clear();
- Object[] keys = mapElementToTreeNode.keySet().toArray();
-
- for (int i = 0; i < keys.length; i++) {
- Object key = keys[i];
-
- OrderedTreeNode result = (OrderedTreeNode) mapElementToTreeNode.get(key);
- if (result != null) {
- result.dispose();
- }
- }
- } finally {
- avoidViewerUpdates--;
- }
- }
- }
-
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- // This should only ever be called for a single viewer
- setViewer(viewer);
-
- if (oldInput != null && newInput != null && oldInput.equals(newInput)) {
- return;
- }
-
- try {
- avoidViewerUpdates++;
- removeIfUnused(oldInput);
- } finally {
- avoidViewerUpdates--;
- }
- }
-
- private void removeIfUnused(Object element) {
- OrderedTreeNode result = (OrderedTreeNode) mapElementToTreeNode
- .get(element);
- if (result != null && result.getParent() == null) {
- mapElementToTreeNode.remove(element);
- elements.doFireDiff(Collections.EMPTY_SET, Collections
- .singleton(element));
- result.dispose();
- }
- }
-
- private void setViewer(Viewer viewer) {
- if (!(viewer instanceof TreeViewer)) {
- throw new IllegalArgumentException(
- "This content provider can only be used with TreeViewers"); //$NON-NLS-1$
- }
- TreeViewer newTreeViewer = (TreeViewer) viewer;
-
- if (newTreeViewer != treeViewer) {
- if (treeViewer != null) {
- treeViewer.removeTreeListener(expandListener);
- }
-
- this.treeViewer = newTreeViewer;
- if (newTreeViewer != null) {
- newTreeViewer.addTreeListener(expandListener);
- }
- }
- }
-
- public Object[] getChildren(TreePath parentElement) {
- List result = getNode(parentElement).getChildren();
-
- addParent(parentElement, result);
-
- return result.toArray();
- }
-
- private OrderedTreeNode getNode(TreePath parentElement) {
- OrderedTreeNode result = (OrderedTreeNode) mapElementToTreeNode
- .get(parentElement);
- if (result == null) {
- result = new OrderedTreeNode(parentElement, this);
- mapElementToTreeNode.put(parentElement, result);
- elements.fireSetChange(Diffs.createSetDiff(Collections
- .singleton(parentElement), Collections.EMPTY_SET));
- }
- return result;
- }
-
- /**
- * Returns the set of all elements that have been discovered in this tree so
- * far. Callers must not dispose this set. Never null.
- *
- * @return the set of all elements that have been discovered in this tree so
- * far.
- */
- public IObservableSet getKnownElements() {
- return elements;
- }
-
- /* package */void changeStale(int staleDelta) {
- staleCount += staleDelta;
- processPrefetches();
- elements.setStale(staleCount != 0);
- }
-
- /**
- * Returns the associated tree viewer.
- *
- * @return the associated tree viewer
- */
- public TreeViewer getViewer() {
- return treeViewer;
- }
-
- /**
- * Returns true iff the given element is stale.
- *
- * @param element
- * the element to query for staleness. Must exist in the tree.
- * @return true iff the given element is stale
- */
- public boolean isDirty(TreePath element) {
- return getChildrenList(element).isStale();
- }
-
- /* package */void enqueuePrefetch(OrderedTreeNode node) {
- if (prefetchingTree.shouldPrefetch(node.getElement())) {
- if (staleCount == 0) {
- // Call node.getChildren()... this will cause us to start
- // listening to the
- // node and will trigger prefetching. Don't call prefetch since
- // this method
- // is intended to be called inside getters (which will simply
- // return the
- // fetched nodes) and prefetch() is intended to be called inside
- // an asyncExec,
- // which will notify the viewer directly of the newly discovered
- // nodes.
- node.getChildren();
- } else {
- enqueuedPrefetches.add(node);
- while (maxPrefetches >= 0
- && enqueuedPrefetches.size() > maxPrefetches) {
- enqueuedPrefetches.removeFirst();
- }
- }
- }
- }
-
- private void processPrefetches() {
- while (staleCount == 0 && !enqueuedPrefetches.isEmpty()) {
- OrderedTreeNode next = (OrderedTreeNode) enqueuedPrefetches.removeLast();
-
- // Note that we don't remove nodes from the prefetch queue when they
- // are disposed,
- // so we may encounter disposed nodes at this time.
- if (!next.isDisposed()) {
- next.prefetch();
- }
- }
- }
-
- public TreePath[] getParents(Object element) {
- return new TreePath[0];
- }
-
- public boolean hasChildren(TreePath path) {
- return getNode(path).shouldShowPlus();
- }
-
- public Object[] getElements(Object inputElement) {
- return getChildren(new TreePath(new Object[]{inputElement}));
- }
-
-}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/OrderedTreeNode.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/OrderedTreeNode.java
deleted file mode 100644
index 6fd08ae2..00000000
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/OrderedTreeNode.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2007 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.jface.internal.databinding.internal.viewers;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.core.databinding.observable.IStaleListener;
-import org.eclipse.core.databinding.observable.Observables;
-import org.eclipse.core.databinding.observable.StaleEvent;
-import org.eclipse.core.databinding.observable.list.IListChangeListener;
-import org.eclipse.core.databinding.observable.list.IObservableList;
-import org.eclipse.core.databinding.observable.list.ListChangeEvent;
-import org.eclipse.core.databinding.observable.list.ListDiffEntry;
-import org.eclipse.jface.viewers.TreePath;
-
-/* package */class OrderedTreeNode implements IListChangeListener,
- IStaleListener {
- private OrderedTreeContentProvider contentProvider;
-
- private TreePath element;
-
- // Stores the set of parents (null if there are less than 2)
- private HashSet parents = null;
-
- // Stores one representative parent. If there is more than one parent,
- // the complete set of parents can be found in the parents set.
- Object parent;
-
- /**
- * List of child elements.
- */
- private IObservableList children;
-
- private boolean hasPendingNode = false;
-
- private boolean isStale;
-
- private boolean listeningToChildren = false;
-
- private boolean prefetchEnqueued = false;
-
- /**
- * @param treePath
- * @param cp
- */
- public OrderedTreeNode(TreePath treePath, OrderedTreeContentProvider cp) {
- this.element = treePath;
- this.contentProvider = cp;
- children = contentProvider.createChildList(treePath);
- if (children == null) {
- children = Observables.emptyObservableList(contentProvider.getKnownElements().getRealm());
- listeningToChildren = true;
- }
- hasPendingNode = children.isStale();
- }
-
- /**
- * @param parent
- */
- public void addParent(Object parent) {
- if (this.parent == null) {
- this.parent = parent;
- } else {
- if (parent.equals(this.parent)) {
- return;
- }
- if (parents == null) {
- parents = new HashSet();
- parents.add(this.parent);
- }
- parents.add(parent);
- }
- }
-
- /**
- * @param parent
- */
- public void removeParent(Object parent) {
- if (this.parents != null) {
- parents.remove(parent);
- }
-
- if (parent == this.parent) {
- if (parents == null || parents.isEmpty()) {
- this.parent = null;
- } else {
- this.parent = parents.iterator().next();
- }
- }
-
- if (this.parents != null && this.parents.size() <= 1) {
- this.parents = null;
- }
- }
-
- /**
- * Returns the list of children for this node. If new children are
- * discovered later, they will be added directly to the viewer.
- *
- * @return the list of children of this node
- */
- public List getChildren() {
- if (!listeningToChildren) {
- listeningToChildren = true;
- children.addListChangeListener(this);
- hasPendingNode = children.isEmpty() && children.isStale();
- children.addStaleListener(this);
- updateStale();
- }
-
- // If the child set is stale and empty, show the "pending" node
- if (hasPendingNode) {
- Object pendingNode = contentProvider.getPendingNode();
- return Collections.singletonList(pendingNode);
- }
- return children;
- }
-
- /**
- * @return the observable list of children for this node
- */
- public IObservableList getChildrenList() {
- return children;
- }
-
- private void updateStale() {
- boolean willBeStale = children.isStale();
- if (willBeStale != isStale) {
- isStale = willBeStale;
-
- contentProvider.changeStale(isStale ? 1 : -1);
- }
- }
-
- /**
- * @return whether this node's children will change soon
- */
- public boolean isStale() {
- return isStale;
- }
-
- /**
- * Returns true if the viewer should show a plus sign for expanding this
- * node.
- *
- * @return <code>true</code> if this node has children
- */
- public boolean shouldShowPlus() {
- if (children == null) {
- // if (!hasPendingNode) {
- // hasPendingNode = true;
- // contentProvider.add(element,
- // Collections.singleton(contentProvider.getPendingNode()));
- // }
- return true;
- }
- if (!listeningToChildren && !prefetchEnqueued) {
- prefetchEnqueued = true;
- contentProvider.enqueuePrefetch(this);
- }
- return !listeningToChildren || hasPendingNode || !children.isEmpty();
- }
-
- /**
- * Disposes this node and removes all remaining children.
- */
- public void dispose() {
- if (children != null) {
- if (listeningToChildren) {
- contentProvider.remove(element, children, true);
- children.removeListChangeListener(this);
- children.removeStaleListener(this);
- }
- children.dispose();
- children = null;
-
- if (listeningToChildren && isStale) {
- contentProvider.changeStale(-1);
- }
- }
- }
-
- /**
- * @return <code>true</code> if this node is disposed
- */
- public boolean isDisposed() {
- return children == null;
- }
-
- /**
- * Returns one representative parent, or null if this node is unparented.
- * Use getParents() to get the complete set of known parents.
- *
- * @return a parent node, or <code>null</code>
- */
- public Object getParent() {
- return parent;
- }
-
- /**
- * @return the set of known parent nodes
- */
- public Set getParents() {
- if (parents == null) {
- if (parent == null) {
- return Collections.EMPTY_SET;
- }
- return Collections.singleton(parent);
- }
- return parents;
- }
-
- /**
- * Called when the child set changes. Should not be called directly by the
- * viewer.
- */
- public void handleListChange(ListChangeEvent event) {
- boolean shouldHavePendingNode = children.isEmpty()
- && children.isStale();
-
- List removals = new ArrayList();
- ListDiffEntry[] differences = event.diff.getDifferences();
- for (int i = 0; i < differences.length; i++) {
- ListDiffEntry diffEntry = differences[i];
- if (diffEntry.isAddition()) {
- contentProvider.insert(element, diffEntry.getElement(),
- diffEntry.getPosition());
- } else {
- removals.add(diffEntry.getElement());
- }
- }
-
- // Check if we should add the pending node
- if (shouldHavePendingNode && !hasPendingNode) {
- contentProvider
- .insert(element, contentProvider.getPendingNode(), 0);
- hasPendingNode = true;
- }
-
- // Check if we should remove the pending node
- if (!shouldHavePendingNode && hasPendingNode) {
- removals.add(contentProvider.getPendingNode());
- hasPendingNode = false;
- }
- if (!removals.isEmpty()) {
- contentProvider.remove(element, removals, children.isEmpty()
- && !hasPendingNode);
- }
-
- updateStale();
- }
-
- public void handleStale(StaleEvent event) {
- boolean shouldHavePendingNode = children.isEmpty()
- && children.isStale();
-
- // Check if we should add the pending node
- if (shouldHavePendingNode && !hasPendingNode) {
- hasPendingNode = shouldHavePendingNode;
- contentProvider.insert(element, Collections
- .singletonList(contentProvider.getPendingNode()), 0);
- }
-
- // Check if we should remove the pending node
- if (!shouldHavePendingNode && hasPendingNode) {
- hasPendingNode = shouldHavePendingNode;
- contentProvider.remove(element, Collections
- .singletonList(contentProvider.getPendingNode()), true);
- }
-
- updateStale();
- }
-
- /**
- * @return the element
- */
- public Object getElement() {
- return element;
- }
-
- /**
- *
- */
- public void prefetch() {
- List children = getChildren();
- if (!children.isEmpty()) {
- contentProvider.add(element, children);
- } else {
- // We need to remove the + sign, and adding/removing elements won't
- // do the trick
- contentProvider.getViewer().refresh(element);
- }
- }
-}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/PrefetchingTree.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/PrefetchingTree.java
deleted file mode 100644
index ac33cd50..00000000
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/PrefetchingTree.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2007 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.jface.internal.databinding.internal.viewers;
-
-
-
-/* package */ class PrefetchingTree implements IPrefetchingTree {
-
- private static IPrefetchingTree instance;
-
- private PrefetchingTree() {
- }
-
- public boolean shouldPrefetch(Object parentNode) {
- return true;
- }
-
- /**
- * @param treeProvider
- * @return a prefetching tree
- */
- public static IPrefetchingTree getPrefetchingTree(Object treeProvider) {
- if (treeProvider instanceof IPrefetchingTree) {
- return (IPrefetchingTree)treeProvider;
- }
- if (instance == null) {
- instance = new PrefetchingTree();
- }
- return instance;
- }
-
-}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/UnorderedTreeContentProvider.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/UnorderedTreeContentProvider.java
deleted file mode 100644
index fbd7dbd4..00000000
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/UnorderedTreeContentProvider.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2007 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.jface.internal.databinding.internal.viewers;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Set;
-
-import org.eclipse.core.databinding.observable.Diffs;
-import org.eclipse.core.databinding.observable.set.AbstractObservableSet;
-import org.eclipse.core.databinding.observable.set.IObservableSet;
-import org.eclipse.core.databinding.observable.set.SetDiff;
-import org.eclipse.core.internal.databinding.observable.tree.IUnorderedTreeProvider;
-import org.eclipse.jface.viewers.ITreePathContentProvider;
-import org.eclipse.jface.viewers.ITreeViewerListener;
-import org.eclipse.jface.viewers.TreeExpansionEvent;
-import org.eclipse.jface.viewers.TreePath;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-
-/**
- * Converts an ITreeProvider into an ITreeContentProvider that is suitable for
- * use with a JFace TreeViewer.
- *
- * <p>
- * This content provider works correctly with trees containing duplicate
- * elements.
- * </p>
- *
- * @since 3.3
- */
-public class UnorderedTreeContentProvider implements ITreePathContentProvider {
-
- private HashMap mapElementToTreeNode = new HashMap();
-
- private LinkedList enqueuedPrefetches = new LinkedList();
-
- class KnownElementsSet extends AbstractObservableSet {
-
- /**
- */
- protected KnownElementsSet() {
- super(provider.getRealm());
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.internal.databinding.provisional.observable.set.AbstractObservableSet#getWrappedSet()
- */
- protected Set getWrappedSet() {
- return mapElementToTreeNode.keySet();
- }
-
- void doFireDiff(Set added, Set removed) {
- fireSetChange(Diffs.createSetDiff(added, removed));
- }
-
- void doFireStale(boolean isStale) {
- if (isStale) {
- fireStale();
- } else {
- fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
- Collections.EMPTY_SET));
- }
- }
-
- public Object getElementType() {
- return new Object();
- }
-
- protected void fireSetChange(SetDiff diff) {
- super.fireSetChange(diff);
- }
- }
-
- KnownElementsSet elements;
-
- private ITreeViewerListener expandListener = new ITreeViewerListener() {
- public void treeCollapsed(TreeExpansionEvent event) {
- }
-
- public void treeExpanded(TreeExpansionEvent event) {
- }
- };
-
- private IPrefetchingTree prefetchingTree;
-
- private IUnorderedTreeProvider provider;
-
- private Object pendingNode;
-
- private int avoidViewerUpdates;
-
- private TreeViewer treeViewer;
-
- private int staleCount = 0;
-
- private boolean useRefresh;
-
- private int maxPrefetches = -1;
-
- /**
- * Constructs a content provider that will render the given tree in a
- * TreeViewer.
- *
- * @param provider
- * IObservableTree that provides the contents of the tree. The
- * given provider map optionally implement IPrefetchingTree if it
- * wants to selectively enable or disable prefetching from
- * particular nodes.
- * @param pendingNode
- * element to insert whenever a node is being fetched in the
- * background
- */
- public UnorderedTreeContentProvider(IUnorderedTreeProvider provider,
- Object pendingNode) {
- this(provider, pendingNode, false);
- }
-
- /**
- * Constructs a content provider that will render the given tree in a
- * TreeViewer.
- *
- * @param provider
- * IObservableTree that provides the contents of the tree
- * @param pendingNode
- * element to insert whenever a node is being fetched in the
- * background
- * @param useRefresh
- * true = notify the viewer of changes by calling refresh(...),
- * false = notify the viewer of changes by calling add(...) and
- * remove(...). Using false is more efficient, but may not work
- * with TreeViewer subclasses.
- */
- public UnorderedTreeContentProvider(IUnorderedTreeProvider provider,
- Object pendingNode, boolean useRefresh) {
- this.provider = provider;
- this.prefetchingTree = PrefetchingTree.getPrefetchingTree(provider);
- this.pendingNode = pendingNode;
- this.useRefresh = useRefresh;
- elements = new KnownElementsSet();
- }
-
- /**
- * Sets the maximum number of pending prefetches.
- *
- * @param maxPrefetches
- */
- public void setMaxPrefetches(int maxPrefetches) {
- this.maxPrefetches = maxPrefetches;
- }
-
- /* package */IObservableSet createChildSet(TreePath treePath) {
- Object[] segments = new Object[treePath.getSegmentCount()];
- for (int i = 0; i < segments.length; i++) {
- segments[i] = treePath.getSegment(i);
- }
- return provider
- .createChildSet(new org.eclipse.core.internal.databinding.observable.tree.TreePath(
- segments));
- }
-
- /* package */void remove(Object element, Set removals, boolean lastElement) {
- if (avoidViewerUpdates == 0) {
- for (Iterator iter = removals.iterator(); iter.hasNext();) {
- Object next = iter.next();
-
- UnorderedTreeNode nextNode = (UnorderedTreeNode) mapElementToTreeNode
- .get(next);
- if (nextNode != null) {
- nextNode.removeParent(element);
- removeIfUnused(nextNode);
- }
- }
-
- if (lastElement || useRefresh) {
- treeViewer.refresh(element);
- } else {
- treeViewer.remove(element, removals.toArray());
- }
- }
- }
-
- /* package */void add(TreePath treePath, Set additions) {
- if (avoidViewerUpdates == 0) {
- // Handle new parents
- addParent(treePath, additions);
- if (useRefresh) {
- treeViewer.refresh(treePath);
- } else {
- treeViewer.add(treePath, additions.toArray());
- }
- }
- }
-
- /**
- * Ensures that the given set of children have the given parent as one of
- * their parents.
- *
- * @param parent
- * @param children
- */
- private void addParent(TreePath parent, Set children) {
- for (Iterator iter = children.iterator(); iter.hasNext();) {
- Object next = iter.next();
-
- UnorderedTreeNode nextNode = getNode(parent.createChildPath(next));
- nextNode.addParent(parent);
- }
- }
-
- /**
- * Returns the element that should be inserted into the tree when fetching
- * the children of the node that is both stale and empty.
- *
- * @return the element that should be inserted into the tree when fetching
- * the children of a node that is stale and empty
- */
- public final Object getPendingNode() {
- return pendingNode;
- }
-
- /**
- * Returns the IObservableSet representing the children of the given node.
- * Never null.
- *
- * @param parent
- * parent element. Must be a valid node from the tree.
- * @return the set of children of the given parent node
- */
- public IObservableSet getChildrenSet(TreePath parent) {
- IObservableSet result = getNode(parent).getChildrenSet();
-
- return result;
- }
-
- public void dispose() {
- if (treeViewer != null) {
- try {
- avoidViewerUpdates++;
- enqueuedPrefetches.clear();
- Object[] keys = mapElementToTreeNode.keySet().toArray();
-
- for (int i = 0; i < keys.length; i++) {
- Object key = keys[i];
-
- UnorderedTreeNode result = (UnorderedTreeNode) mapElementToTreeNode
- .get(key);
- if (result != null) {
- result.dispose();
- }
- }
- } finally {
- avoidViewerUpdates--;
- }
- }
- }
-
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- // This should only ever be called for a single viewer
- setViewer(viewer);
-
- if (oldInput != null && newInput != null && oldInput.equals(newInput)) {
- return;
- }
-
- try {
- avoidViewerUpdates++;
- removeIfUnused(oldInput);
- } finally {
- avoidViewerUpdates--;
- }
- }
-
- private void removeIfUnused(Object element) {
- UnorderedTreeNode result = (UnorderedTreeNode) mapElementToTreeNode
- .get(element);
- if (result != null && result.getParent() == null) {
- mapElementToTreeNode.remove(element);
- elements.doFireDiff(Collections.EMPTY_SET, Collections
- .singleton(element));
- result.dispose();
- }
- }
-
- private void setViewer(Viewer viewer) {
- if (!(viewer instanceof TreeViewer)) {
- throw new IllegalArgumentException(
- "This content provider can only be used with TreeViewers"); //$NON-NLS-1$
- }
- TreeViewer newTreeViewer = (TreeViewer) viewer;
-
- if (newTreeViewer != treeViewer) {
- if (treeViewer != null) {
- treeViewer.removeTreeListener(expandListener);
- }
-
- this.treeViewer = newTreeViewer;
- if (newTreeViewer != null) {
- newTreeViewer.addTreeListener(expandListener);
- }
- }
- }
-
- public Object[] getChildren(TreePath parentPath) {
- Set result = getNode(parentPath).getChildren();
-
- addParent(parentPath, result);
-
- return result.toArray();
- }
-
- private UnorderedTreeNode getNode(TreePath parentPath) {
- UnorderedTreeNode result = (UnorderedTreeNode) mapElementToTreeNode
- .get(parentPath);
- if (result == null) {
- result = new UnorderedTreeNode(parentPath, this);
- mapElementToTreeNode.put(parentPath, result);
- elements.fireSetChange(Diffs.createSetDiff(Collections
- .singleton(parentPath), Collections.EMPTY_SET));
- }
- return result;
- }
-
- public TreePath[] getParents(Object element) {
- return new TreePath[0];
- }
-
- public boolean hasChildren(TreePath element) {
- return getNode(element).shouldShowPlus();
- }
-
- public Object[] getElements(Object inputElement) {
- return getChildren(new TreePath(new Object[]{inputElement}));
- }
-
- /**
- * Returns the set of all elements that have been discovered in this tree so
- * far. Callers must not dispose this set. Never null.
- *
- * @return the set of all elements that have been discovered in this tree so
- * far.
- */
- public IObservableSet getKnownElements() {
- return elements;
- }
-
- /* package */void changeStale(int staleDelta) {
- staleCount += staleDelta;
- processPrefetches();
- elements.setStale(staleCount != 0);
- }
-
- /**
- * Returns the associated tree viewer.
- *
- * @return the associated tree viewer
- */
- public TreeViewer getViewer() {
- return treeViewer;
- }
-
- /**
- * Returns true iff the given element is stale.
- *
- * @param element
- * the element to query for staleness. Must exist in the tree.
- * @return true iff the given element is stale
- */
- public boolean isDirty(TreePath element) {
- return getChildrenSet(element).isStale();
- }
-
- /* package */void enqueuePrefetch(UnorderedTreeNode node) {
- if (prefetchingTree.shouldPrefetch(node.getElement())) {
- if (staleCount == 0) {
- // Call node.getChildren()... this will cause us to start
- // listening to the
- // node and will trigger prefetching. Don't call prefetch since
- // this method
- // is intended to be called inside getters (which will simply
- // return the
- // fetched nodes) and prefetch() is intended to be called inside
- // an asyncExec,
- // which will notify the viewer directly of the newly discovered
- // nodes.
- node.getChildren();
- } else {
- enqueuedPrefetches.add(node);
- while (maxPrefetches >= 0
- && enqueuedPrefetches.size() > maxPrefetches) {
- enqueuedPrefetches.removeFirst();
- }
- }
- }
- }
-
- private void processPrefetches() {
- while (staleCount == 0 && !enqueuedPrefetches.isEmpty()) {
- UnorderedTreeNode next = (UnorderedTreeNode) enqueuedPrefetches
- .removeLast();
-
- // Note that we don't remove nodes from the prefetch queue when they
- // are disposed,
- // so we may encounter disposed nodes at this time.
- if (!next.isDisposed()) {
- next.prefetch();
- }
- }
- }
-}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/IParentProvider.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/IParentProvider.java
new file mode 100644
index 00000000..f4b35bf7
--- /dev/null
+++ b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/IParentProvider.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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
+ * Stefan Xenos, IBM - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.internal.databinding.provisional.viewers;
+
+/**
+ * Returns the parent of elements in a tree.
+ *
+ * @since 3.3
+ */
+public interface IParentProvider {
+
+ /**
+ * TODO: comment me
+ *
+ * @param child
+ * @return TODO: comment
+ */
+ public Object getParent(Object child);
+}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/UnorderedTreeNode.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/TreeNode.java
index f9abf733..9748ff8f 100644
--- a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/internal/viewers/UnorderedTreeNode.java
+++ b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/TreeNode.java
@@ -7,8 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stefan Xenos, IBM - initial API and implementation
*******************************************************************************/
-package org.eclipse.jface.internal.databinding.internal.viewers;
+package org.eclipse.jface.internal.databinding.provisional.viewers;
import java.util.Collections;
import java.util.HashSet;
@@ -20,11 +21,13 @@ import org.eclipse.core.databinding.observable.StaleEvent;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
-import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.core.databinding.observable.set.SetDiff;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.widgets.Control;
-/* package */ class UnorderedTreeNode implements ISetChangeListener, IStaleListener {
+/* package */ class TreeNode implements ISetChangeListener, IStaleListener {
private UnorderedTreeContentProvider contentProvider;
- private TreePath treePath;
+ private Object element;
// Stores the set of parents (null if there are less than 2)
private HashSet parents = null;
@@ -47,12 +50,12 @@ import org.eclipse.jface.viewers.TreePath;
* @param element
* @param cp
*/
- public UnorderedTreeNode(TreePath element, UnorderedTreeContentProvider cp) {
- this.treePath = element;
+ public TreeNode(Object element, UnorderedTreeContentProvider cp) {
+ this.element = element;
this.contentProvider = cp;
children = contentProvider.createChildSet(element);
if (children == null) {
- children = Observables.emptyObservableSet(contentProvider.getKnownElements().getRealm());
+ children = Observables.emptyObservableSet();
listeningToChildren = true;
}
hasPendingNode = children.isStale();
@@ -101,7 +104,7 @@ import org.eclipse.jface.viewers.TreePath;
* Returns the set of children for this node. If new children are discovered later, they
* will be added directly to the viewer.
*
- * @return the set of children
+ * @return TODO
*/
public Set getChildren() {
if (!listeningToChildren) {
@@ -121,7 +124,7 @@ import org.eclipse.jface.viewers.TreePath;
}
/**
- * @return the observable set of children
+ * @return TODO
*/
public IObservableSet getChildrenSet() {
return children;
@@ -137,7 +140,7 @@ import org.eclipse.jface.viewers.TreePath;
}
/**
- * @return <code>true</code> if the children of this node will change soon
+ * @return TODO
*/
public boolean isStale() {
return isStale;
@@ -147,7 +150,7 @@ import org.eclipse.jface.viewers.TreePath;
* Returns true if the viewer should show a plus sign for expanding this
* node.
*
- * @return <code>true</code> if this node may have children
+ * @return TODO
*/
public boolean shouldShowPlus() {
if (children == null) {
@@ -170,7 +173,7 @@ import org.eclipse.jface.viewers.TreePath;
public void dispose() {
if (children != null) {
if (listeningToChildren) {
- contentProvider.remove(treePath, children, true);
+ contentProvider.remove(element, children, true);
children.removeSetChangeListener(this);
children.removeStaleListener(this);
}
@@ -184,7 +187,7 @@ import org.eclipse.jface.viewers.TreePath;
}
/**
- * @return <code>true</code> if this node is disposed
+ * @return TODO
*/
public boolean isDisposed() {
return children == null;
@@ -194,32 +197,49 @@ import org.eclipse.jface.viewers.TreePath;
* Returns one representative parent, or null if this node is unparented. Use
* getParents() to get the complete set of known parents.
*
- * @return a parent node, or null
+ * @return TODO
*/
public Object getParent() {
return parent;
}
/**
- * @return the set of known parent nodes
+ *
+ * @return the set of all known parents for this node
*/
public Set getParents() {
if (parents == null) {
if (parent == null) {
return Collections.EMPTY_SET;
+ } else {
+ return Collections.singleton(parent);
}
- return Collections.singleton(parent);
+ } else {
+ return parents;
}
- return parents;
}
/**
* Called when the child set changes. Should not be called directly by the viewer.
*/
public void handleSetChange(SetChangeEvent event) {
+ SetDiff diff = event.diff;
+ TreeViewer viewer = this.contentProvider.getViewer();
+ if (viewer != null) {
+ Control control = viewer.getControl();
+ if (control != null) {
+ if (control.isDisposed()) {
+ // If the widgetry was disposed without notifying the content provider, then
+ // dispose the content provider now and stop processing events.
+ contentProvider.dispose();
+ return;
+ }
+ }
+ }
+
boolean shouldHavePendingNode = children.isEmpty() && children.isStale();
- Set additions = event.diff.getAdditions();
+ Set additions = diff.getAdditions();
// Check if we should add the pending node
if (shouldHavePendingNode && !hasPendingNode) {
HashSet newAdditions = new HashSet();
@@ -229,7 +249,7 @@ import org.eclipse.jface.viewers.TreePath;
hasPendingNode = true;
}
- Set removals = event.diff.getRemovals();
+ Set removals = diff.getRemovals();
// Check if we should remove the pending node
if (!shouldHavePendingNode && hasPendingNode) {
HashSet newRemovals = new HashSet();
@@ -239,50 +259,75 @@ import org.eclipse.jface.viewers.TreePath;
hasPendingNode = false;
}
if (!additions.isEmpty()) {
- contentProvider.add(treePath, additions);
+ contentProvider.add(element, additions);
}
if (!removals.isEmpty()) {
- contentProvider.remove(treePath, removals, children.isEmpty() && !hasPendingNode);
+ contentProvider.remove(element, removals, children.isEmpty() && !hasPendingNode);
}
updateStale();
}
- public void handleStale(StaleEvent event) {
+ public void handleStale(StaleEvent staleEvent) {
+ TreeViewer viewer = this.contentProvider.getViewer();
+ if (viewer != null) {
+ Control control = viewer.getControl();
+ if (control != null) {
+ if (control.isDisposed()) {
+ // If the widgetry was disposed without notifying the content provider, then
+ // dispose the content provider now and stop processing events.
+ contentProvider.dispose();
+ return;
+ }
+ }
+ }
+
boolean shouldHavePendingNode = children.isEmpty() && children.isStale();
// Check if we should add the pending node
if (shouldHavePendingNode && !hasPendingNode) {
hasPendingNode = shouldHavePendingNode;
- contentProvider.add(treePath, Collections.singleton(contentProvider.getPendingNode()));
+ contentProvider.add(element, Collections.singleton(contentProvider.getPendingNode()));
}
// Check if we should remove the pending node
if (!shouldHavePendingNode && hasPendingNode) {
hasPendingNode = shouldHavePendingNode;
- contentProvider.remove(treePath, Collections.singleton(contentProvider.getPendingNode()), true);
+ contentProvider.remove(element, Collections.singleton(contentProvider.getPendingNode()), true);
}
updateStale();
}
/**
- * @return the element
+ * @return TODO
*/
public Object getElement() {
- return treePath;
+ return element;
}
/**
*
*/
public void prefetch() {
+ TreeViewer viewer = this.contentProvider.getViewer();
+ if (viewer != null) {
+ Control control = viewer.getControl();
+ if (control != null) {
+ if (control.isDisposed()) {
+ // If the widgetry has been disposed, then avoid sending anything
+ // to the viewer.
+ return;
+ }
+ }
+ }
+
Set children = getChildren();
if (!children.isEmpty()) {
- contentProvider.add(treePath, children);
+ contentProvider.add(element, children);
} else {
// We need to remove the + sign, and adding/removing elements won't do the trick
- contentProvider.getViewer().refresh(treePath);
+ contentProvider.getViewer().refresh(element);
}
}
}
diff --git a/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/UnorderedTreeContentProvider.java b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/UnorderedTreeContentProvider.java
new file mode 100644
index 00000000..4a00edb1
--- /dev/null
+++ b/bundles/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/UnorderedTreeContentProvider.java
@@ -0,0 +1,528 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 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
+ * Stefan Xenos, IBM - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jface.internal.databinding.provisional.viewers;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.databinding.observable.Diffs;
+import org.eclipse.core.databinding.observable.set.AbstractObservableSet;
+import org.eclipse.core.databinding.observable.set.IObservableSet;
+import org.eclipse.core.databinding.observable.set.SetDiff;
+import org.eclipse.core.internal.databinding.observable.tree.IUnorderedTreeProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ITreePathContentProvider;
+import org.eclipse.jface.viewers.ITreeViewerListener;
+import org.eclipse.jface.viewers.TreeExpansionEvent;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * TODO: comment
+ * @since 3.3
+ *
+ */
+public class UnorderedTreeContentProvider implements ITreeContentProvider, ITreePathContentProvider {
+
+ private HashMap mapElementToTreeNode = new HashMap();
+ private LinkedList enqueuedPrefetches = new LinkedList();
+ private IParentProvider rootParentProvider = null;
+ private boolean useTreePaths = false;
+
+ class KnownElementsSet extends AbstractObservableSet {
+
+ protected KnownElementsSet() {
+ super();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.internal.databinding.provisional.observable.set.AbstractObservableSet#getWrappedSet()
+ */
+ protected Set getWrappedSet() {
+ return mapElementToTreeNode.keySet();
+ }
+
+ void doFireDiff(Set added, Set removed) {
+ fireSetChange(Diffs.createSetDiff(added, removed));
+ }
+
+ public void fireSetChange(SetDiff diff) {
+ super.fireSetChange(diff);
+ }
+
+ void doFireStale(boolean isStale) {
+ if (isStale) {
+ fireStale();
+ } else {
+ fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, Collections.EMPTY_SET));
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.internal.databinding.provisional.observable.set.IObservableSet#getElementType()
+ */
+ public Object getElementType() {
+ return new Object();
+ }
+ }
+
+ KnownElementsSet elements = new KnownElementsSet();
+
+ private ITreeViewerListener expandListener = new ITreeViewerListener() {
+ public void treeCollapsed(TreeExpansionEvent event) {
+ }
+
+ public void treeExpanded(TreeExpansionEvent event) {
+ }
+ };
+
+ private IUnorderedTreeProvider provider;
+ private Object pendingNode;
+
+ private int avoidViewerUpdates;
+
+ private TreeViewer treeViewer;
+
+ private int staleCount = 0;
+ private boolean useRefresh;
+ private int maxPrefetches = 0;
+
+ /**
+ * Constructs a content provider that will render the given tree in a TreeViewer.
+ *
+ * @param provider IObservableTree that provides the contents of the tree
+ * @param pendingNode element to insert whenever a node is being fetched in the background
+ * @param useRefresh true = notify the viewer of changes by calling refresh(...), false =
+ * notify the viewer of changes by calling add(...) and remove(...). Using false
+ * is more efficient, but may not work with TreeViewer subclasses.
+ */
+ public UnorderedTreeContentProvider(IUnorderedTreeProvider provider,
+ Object pendingNode, boolean useRefresh) {
+ this.provider = provider;
+ this.pendingNode = pendingNode;
+ this.useRefresh = useRefresh;
+ }
+
+ /**
+ * Sets whether this content provider should add/remove elements using
+ * TreePaths (true) or elements (false).
+ *
+ * <p></p>
+ * <p>When using elements:</p>
+ *
+ * <ul>
+ * <li>Cycles are permitted (elements can be their own ancestor)</li>
+ * <li>Addition, removal, and refresh are slightly faster</li>
+ * <li>It is not possible to have more than one content provider per tree</li>
+ * <li>The setRootPath(...) method is ignored</li>
+ * </ul>
+ *
+ * <p></p>
+ * <p>When using TreePaths:</p>
+ *
+ * <ul>
+ * <li>Cycles are not permitted (elements cannot be their own parent)</li>
+ * <li>Addition, removal, and refresh are slightly slower</li>
+ * <li>It is possible to use more than one content provider in the same tree</li>
+ * <li>The setRootPath(...) method can be used to direct the output to a particular
+ * subtree</li>
+ * </ul>
+ *
+ * @param usePaths
+ */
+ public void useTreePaths(boolean usePaths) {
+ this.useTreePaths = usePaths;
+ }
+
+ /**
+ * @param rootParentProvider
+ */
+ public void setRootPath(IParentProvider rootParentProvider) {
+ this.rootParentProvider = rootParentProvider;
+ }
+
+ /**
+ * @param maxPrefetches
+ */
+ public void setMaxPrefetches(int maxPrefetches) {
+ this.maxPrefetches = maxPrefetches;
+ }
+
+ /* package */ IObservableSet createChildSet(Object element) {
+ return provider.createChildSet(element);
+ }
+
+ /* package */ void remove(Object element, Set removals, boolean lastElement) {
+ if (removals.isEmpty()) {
+ return;
+ }
+ if (avoidViewerUpdates == 0) {
+ if (lastElement || useRefresh) {
+ doRefresh(element);
+ } else {
+ if (useTreePaths) {
+ List toRemove = new ArrayList();
+ TreePath[] parents = getParents(element);
+ for (int i = 0; i < parents.length; i++) {
+ TreePath parent = parents[i];
+
+ for (Iterator iter = removals.iterator(); iter.hasNext();) {
+ Object elementToRemove = (Object) iter.next();
+
+ toRemove.add(parent.createChildPath(element).createChildPath(elementToRemove));
+ }
+ }
+
+ treeViewer.remove((TreePath[]) toRemove.toArray(new TreePath[toRemove.size()]));
+ } else {
+ treeViewer.remove(element, removals.toArray());
+ }
+ }
+ for (Iterator iter = removals.iterator(); iter.hasNext();) {
+ Object next = (Object) iter.next();
+
+ TreeNode nextNode = (TreeNode)mapElementToTreeNode.get(next);
+ if (nextNode != null) {
+ nextNode.removeParent(element);
+ removeIfUnused(nextNode);
+ }
+ }
+ }
+ }
+
+ /* package */ void add(Object element, Set additions) {
+ if (additions.isEmpty()) {
+ return;
+ }
+ if (avoidViewerUpdates == 0) {
+ // Handle new parents
+ addParent(element, additions);
+ if (useRefresh) {
+ doRefresh(element);
+ } else {
+ if (useTreePaths) {
+ TreePath[] parents = getParents(element);
+ for (int i = 0; i < parents.length; i++) {
+ TreePath parent = parents[i];
+
+ treeViewer.add(parent.createChildPath(element), additions.toArray());
+ }
+ } else {
+ treeViewer.add(element, additions.toArray());
+ }
+ }
+ }
+ }
+
+ private void doRefresh(Object element) {
+ treeViewer.refresh(element);
+ }
+
+ /**
+ * Ensures that the given set of children have the given parent as
+ * one of their parents.
+ *
+ * @param parent
+ * @param children
+ */
+ private void addParent(Object parent, Set children) {
+ for (Iterator iter = children.iterator(); iter.hasNext();) {
+ Object next = (Object) iter.next();
+
+ TreeNode nextNode = getNode(next);
+ nextNode.addParent(parent);
+ }
+ }
+
+ /**
+ * @return saouesnth
+ */
+ public final Object getPendingNode() {
+ return pendingNode;
+ }
+
+ /**
+ * @param parent
+ * @return aueosnht
+ */
+ public IObservableSet getChildrenSet(Object parent) {
+ IObservableSet result = getNode(parent).getChildrenSet();
+
+ return result;
+ }
+
+ public void dispose() {
+ if (treeViewer != null) {
+ try {
+ avoidViewerUpdates++;
+ enqueuedPrefetches.clear();
+ Object[] keys = mapElementToTreeNode.keySet().toArray();
+
+ for (int i = 0; i < keys.length; i++) {
+ Object key = keys[i];
+
+ TreeNode result = (TreeNode)mapElementToTreeNode.get(key);
+ if (result != null) {
+ result.dispose();
+ }
+ }
+ setViewer(null);
+ } finally {
+ avoidViewerUpdates--;
+ }
+ }
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // This should only ever be called for a single viewer
+ setViewer(viewer);
+
+ if (oldInput != null && newInput != null && oldInput.equals(newInput)) {
+ return;
+ }
+
+ try {
+ avoidViewerUpdates++;
+ TreeNode oldNode = (TreeNode)mapElementToTreeNode.get(oldInput);
+ if (oldNode != null) {
+ removeIfUnused(oldNode);
+ }
+ } finally {
+ avoidViewerUpdates--;
+ }
+ }
+
+ private void removeIfUnused(TreeNode toRemove) {
+ //TreeNode result = (TreeNode)mapElementToTreeNode.get(element);
+ Object element = toRemove.getElement();
+ if (toRemove.getParent() == null) {
+ mapElementToTreeNode.remove(element);
+ elements.doFireDiff(Collections.EMPTY_SET, Collections.singleton(element));
+ toRemove.dispose();
+ }
+ }
+
+ private void setViewer(Viewer viewer) {
+ if (viewer != null && !(viewer instanceof TreeViewer)) {
+ throw new IllegalArgumentException("This content provider can only be used with TreeViewers"); //$NON-NLS-1$
+ }
+ TreeViewer newTreeViewer = (TreeViewer) viewer;
+
+ if (newTreeViewer != treeViewer) {
+ if (treeViewer != null) {
+ treeViewer.removeTreeListener(expandListener);
+ }
+
+ this.treeViewer = newTreeViewer;
+ if (newTreeViewer != null) {
+ newTreeViewer.addTreeListener(expandListener);
+ }
+ }
+ }
+
+ public Object[] getChildren(Object parentElement) {
+ Set result = getNode(parentElement).getChildren();
+
+ addParent(parentElement, result);
+
+ return result.toArray();
+ }
+
+ private TreeNode getNode(Object parentElement) {
+ TreeNode result = (TreeNode)mapElementToTreeNode.get(parentElement);
+ if (result == null) {
+ result = new TreeNode(parentElement, this);
+ mapElementToTreeNode.put(parentElement, result);
+ elements.fireSetChange(Diffs.createSetDiff(Collections.singleton(parentElement),
+ Collections.EMPTY_SET));
+ }
+ return result;
+ }
+
+ public Object getParent(Object element) {
+ Object result = getNode(element).getParent();
+ if (result == null && rootParentProvider != null) {
+ result = rootParentProvider.getParent(element);
+ }
+ return result;
+ }
+
+ public boolean hasChildren(Object element) {
+ return getNode(element).shouldShowPlus();
+ }
+
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ /**
+ * @return aouesnth
+ */
+ public IObservableSet getKnownElements() {
+ return elements;
+ }
+
+ /* package */ void changeStale(int staleDelta) {
+ staleCount += staleDelta;
+ processPrefetches();
+ elements.setStale(staleCount != 0);
+ }
+
+ /**
+ * @return aoueesnth
+ */
+ public TreeViewer getViewer() {
+ return treeViewer;
+ }
+
+ /**
+ * @param element
+ * @return aoeusnth
+ */
+ public boolean isDirty(Object element) {
+ return false;
+ }
+
+ /* package */ void enqueuePrefetch(TreeNode node) {
+ if (maxPrefetches > 0 || maxPrefetches == -1) {
+ if (staleCount == 0) {
+ // Call node.getChildren()... this will cause us to start listening to the
+ // node and will trigger prefetching. Don't call prefetch since this method
+ // is intended to be called inside getters (which will simply return the
+ // fetched nodes) and prefetch() is intended to be called inside an asyncExec,
+ // which will notify the viewer directly of the newly discovered nodes.
+ node.getChildren();
+ } else {
+ enqueuedPrefetches.add(node);
+ while (maxPrefetches >= 0 && enqueuedPrefetches.size() > maxPrefetches) {
+ enqueuedPrefetches.removeFirst();
+ }
+ }
+ }
+ }
+
+ private void processPrefetches() {
+ while (staleCount == 0 && !enqueuedPrefetches.isEmpty()) {
+ TreeNode next = (TreeNode)enqueuedPrefetches.removeLast();
+
+ // Note that we don't remove nodes from the prefetch queue when they are disposed,
+ // so we may encounter disposed nodes at this time.
+ if (!next.isDisposed()) {
+ next.prefetch();
+ }
+ }
+ }
+
+ public Object[] getChildren(TreePath parentPath) {
+ return getChildren(parentPath.getLastSegment());
+ }
+
+ public TreePath[] getParents(Object element) {
+ // Compute all paths that do not contain cycles
+ /**
+ * List of Lists
+ */
+ List parentPaths = computeParents(element, new HashSet());
+
+ /**
+ * List of TreePath
+ */
+ List result = new ArrayList();
+
+ for (Iterator iterator = parentPaths.iterator(); iterator.hasNext();) {
+ List nextPath = (List) iterator.next();
+
+ LinkedList resultPath = new LinkedList();
+ resultPath.addAll(nextPath);
+ Object nextParent = resultPath.isEmpty() ? element : resultPath.getFirst();
+ for(;nextParent != null;) {
+ if (rootParentProvider != null) {
+ nextParent = rootParentProvider.getParent(nextParent);
+ if (nextParent != null) {
+ resultPath.addFirst(nextParent);
+ }
+ } else {
+ nextParent = null;
+ }
+ }
+
+ result.add(new TreePath(resultPath.toArray()));
+ }
+
+ if (result.isEmpty() && rootParentProvider != null) {
+ Object nextParent = rootParentProvider.getParent(element);
+ if (nextParent != null) {
+ LinkedList resultPath = new LinkedList();
+ while (nextParent != null) {
+ resultPath.addFirst(nextParent);
+ nextParent = rootParentProvider.getParent(nextParent);
+ }
+
+ result.add(new TreePath(resultPath.toArray()));
+ }
+
+ }
+
+ return (TreePath[]) result.toArray(new TreePath[result.size()]);
+ }
+
+ /**
+ *
+ * @param node
+ * @param toIgnore
+ * @return a list of Lists, indicating all known paths to the given node
+ */
+ private List computeParents(Object node, HashSet toIgnore) {
+ List result = new ArrayList();
+ boolean containedNode = toIgnore.add(node);
+
+ TreeNode tn = getNode(node);
+
+ HashSet parents = new HashSet();
+ parents.addAll(tn.getParents());
+ parents.removeAll(toIgnore);
+ if (parents.isEmpty()) {
+ ArrayList newPath = new ArrayList();
+ result.add(newPath);
+ } else {
+ for (Iterator iterator = parents.iterator(); iterator.hasNext();) {
+ Object parent = iterator.next();
+
+ List parentPaths = computeParents(parent, toIgnore);
+
+ for (Iterator iterator2 = parentPaths.iterator(); iterator2
+ .hasNext();) {
+ List parentPath = (List) iterator2.next();
+
+ parentPath.add(parent);
+ result.add(parentPath);
+ }
+ }
+ }
+
+ if (containedNode) {
+ toIgnore.remove(node);
+ }
+ return result;
+ }
+
+ public boolean hasChildren(TreePath path) {
+ return hasChildren(path.getLastSegment());
+ }
+}
diff --git a/examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/contentprovider/test/TreeContentProviderTest.java b/examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/contentprovider/test/TreeContentProviderTest.java
index 5f38985d..80193573 100644
--- a/examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/contentprovider/test/TreeContentProviderTest.java
+++ b/examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/contentprovider/test/TreeContentProviderTest.java
@@ -16,8 +16,8 @@ import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.set.UnionSet;
import org.eclipse.core.databinding.observable.set.WritableSet;
import org.eclipse.core.internal.databinding.observable.tree.IUnorderedTreeProvider;
-import org.eclipse.core.internal.databinding.observable.tree.TreePath;
-import org.eclipse.jface.internal.databinding.internal.viewers.UnorderedTreeContentProvider;
+import org.eclipse.jface.databinding.swt.SWTObservables;
+import org.eclipse.jface.internal.databinding.provisional.viewers.UnorderedTreeContentProvider;
import org.eclipse.jface.internal.databinding.provisional.viewers.ViewerLabelProvider;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.layout.LayoutConstants;
@@ -36,40 +36,41 @@ import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
/**
- * Tests UpdatableTreeContentProvider and DirtyIndicationLabelProvider.
- * Creates a tree containing three randomly-generated sets of integers,
- * and one node that contains the union of the other sets.
+ * Tests UpdatableTreeContentProvider and DirtyIndicationLabelProvider. Creates
+ * a tree containing three randomly-generated sets of integers, and one node
+ * that contains the union of the other sets.
*
* @since 3.2
*/
public class TreeContentProviderTest {
-
+
private Shell shell;
private TreeViewer tree;
-
+
// Three randomly-generated sets of doubles
private AsynchronousTestSet set1;
private AsynchronousTestSet set2;
private AsynchronousTestSet set3;
-
+
// The union of the above three sets
private UnionSet union;
private Button randomize;
+
public TreeContentProviderTest() {
-
+
// Create the data model
set1 = new AsynchronousTestSet();
set2 = new AsynchronousTestSet();
set3 = new AsynchronousTestSet();
-
+
// A union of the above sets
- union = new UnionSet(new IObservableSet[] {set1, set2, set3});
-
+ union = new UnionSet(new IObservableSet[] { set1, set2, set3 });
+
// Create shell
shell = new Shell(Display.getCurrent());
-
+
createTree();
-
+
Composite buttonBar = new Composite(shell, SWT.NONE);
{
buttonBar.setLayout(new FillLayout(SWT.HORIZONTAL));
@@ -81,14 +82,17 @@ public class TreeContentProviderTest {
super.widgetSelected(e);
}
});
-
+
GridLayoutFactory.fillDefaults().generateLayout(buttonBar);
}
-
- GridLayoutFactory.fillDefaults().margins(LayoutConstants.getMargins()).generateLayout(shell);
-
+
+ GridLayoutFactory.fillDefaults().margins(LayoutConstants.getMargins())
+ .generateLayout(shell);
+
shell.addDisposeListener(new DisposeListener() {
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
*/
public void widgetDisposed(DisposeEvent e) {
@@ -108,34 +112,42 @@ public class TreeContentProviderTest {
}
private void createTree() {
- // Create the tree provider. This provides the structure of the tree. This tree will
- // have an instance of RootNode as the root (which is really a placeholder), several
- // SimpleNodes as top-level nodes, and sets of randomly generated Doubles below each
+ // Create the tree provider. This provides the structure of the tree.
+ // This tree will
+ // have an instance of RootNode as the root (which is really a
+ // placeholder), several
+ // SimpleNodes as top-level nodes, and sets of randomly generated
+ // Doubles below each
// SimpleNode.
IUnorderedTreeProvider treeProvider = new IUnorderedTreeProvider() {
- public IObservableSet createChildSet(TreePath treePath) {
- // If the parent is the root node, return the union of some randomly-generated
+ public IObservableSet createChildSet(Object element) {
+ // If the parent is the root node, return the union of some
+ // randomly-generated
// nodes and some hardcoded nodes
- if (treePath.getSegmentCount()==0 || treePath.getLastSegment() == tree.getInput()) {
+ if (element == tree.getInput()) {
// Set of hardcoded nodes
WritableSet topElements = new WritableSet();
topElements.add(new SimpleNode("Random Set 1", set1));
topElements.add(new SimpleNode("Random Set 2", set2));
topElements.add(new SimpleNode("Random Set 3", set3));
- topElements.add(new SimpleNode("Union of the other sets", union));
+ topElements.add(new SimpleNode("Union of the other sets",
+ union));
return topElements;
}
-
- // If the parent is a RandomChildrenNode, return a randomly-generated
+
+ // If the parent is a RandomChildrenNode, return a
+ // randomly-generated
// set of Doubles for its children
- Object element = treePath.getLastSegment();
if (element instanceof SimpleNode) {
- // We return a new DelegatingObservableSet in order to prevent the
+ // We return a new DelegatingObservableSet in order to
+ // prevent the
// original from being disposed.
- return Observables.proxyObservableSet(((SimpleNode)element).getChildren());
+ return Observables
+ .proxyObservableSet(((SimpleNode) element)
+ .getChildren());
}
-
- // Otherwise the node is a Double, which will have no children
+
+ // Otherwise the node is a Double, which will have no children
return null;
}
@@ -144,52 +156,58 @@ public class TreeContentProviderTest {
return null;
}
};
-
+
// Label provider for the tree
IViewerLabelProvider labelProvider = new ViewerLabelProvider() {
public void updateLabel(ViewerLabel label, Object element) {
if (element instanceof SimpleNode) {
SimpleNode node = (SimpleNode) element;
-
+
label.setText(node.getNodeName());
}
-
+
if (element instanceof Integer) {
Integer node = (Integer) element;
-
+
label.setText("Integer " + node);
}
}
};
-
+
// Create tree viewer
tree = new TreeViewer(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
-
- // UpdatableTreeContentProvider converts an ITreeProvider into a standard JFace content provider
- UnorderedTreeContentProvider contentProvider = new UnorderedTreeContentProvider(treeProvider,
- "pending...");
-
+
+ // UpdatableTreeContentProvider converts an ITreeProvider into a
+ // standard JFace content provider
+ UnorderedTreeContentProvider contentProvider = new UnorderedTreeContentProvider(
+ treeProvider, "pending...", false);
+
tree.setContentProvider(contentProvider);
tree.setLabelProvider(labelProvider);
-
- // For the ITreeProvider above, it doesn't matter what we select as the input.
+
+ // For the ITreeProvider above, it doesn't matter what we select as the
+ // input.
tree.setInput(new Object());
}
-
+
/**
* @param args
*/
public static void main(String[] args) {
- Display display = Display.getDefault();
- TreeContentProviderTest test = new TreeContentProviderTest();
- Shell s = test.getShell();
- s.pack();
- s.setVisible(true);
-
- while (!s.isDisposed()) {
- if (!display.readAndDispatch())
- display.sleep();
- }
+ final Display display = Display.getDefault();
+ Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
+ public void run() {
+ TreeContentProviderTest test = new TreeContentProviderTest();
+ Shell s = test.getShell();
+ s.pack();
+ s.setVisible(true);
+
+ while (!s.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ }
+ });
display.dispose();
}

Back to the top