### Eclipse Workspace Patch 1.0 #P org.eclipse.jface.databinding Index: src/org/eclipse/jface/databinding/viewers/ObservableSetTreeContentProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ObservableSetTreeContentProvider.java,v retrieving revision 1.3 diff -u -r1.3 ObservableSetTreeContentProvider.java --- src/org/eclipse/jface/databinding/viewers/ObservableSetTreeContentProvider.java 29 Apr 2008 01:44:21 -0000 1.3 +++ src/org/eclipse/jface/databinding/viewers/ObservableSetTreeContentProvider.java 22 Jul 2008 22:53:50 -0000 @@ -7,7 +7,7 @@ * * Contributors: * Matthew Hall - initial API and implementation (bug 207858) - * Matthew Hall - bug 226765 + * Matthew Hall - bugs 226765, 222991 *******************************************************************************/ package org.eclipse.jface.databinding.viewers; @@ -22,6 +22,7 @@ import org.eclipse.core.databinding.observable.set.ISetChangeListener; import org.eclipse.core.databinding.observable.set.SetChangeEvent; import org.eclipse.jface.internal.databinding.viewers.ObservableCollectionTreeContentProvider; +import org.eclipse.jface.internal.databinding.viewers.ViewerElementSet; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; @@ -58,27 +59,44 @@ if (isViewerDisposed()) return; - Set removals = event.diff.getRemovals(); - if (!removals.isEmpty()) { - viewerUpdater.remove(parentElement, removals.toArray()); - for (Iterator iterator = removals.iterator(); iterator - .hasNext();) { - Object child = iterator.next(); - TreeNode childNode = getExistingNode(child); - if (childNode != null) - childNode.removeParent(parentElement); - } + Set localAdditions = event.diff.getAdditions(); + Set localRemovals = event.diff.getRemovals(); + + Set knownElementAdditions = ViewerElementSet + .withComparer(comparer); + knownElementAdditions.addAll(localAdditions); + knownElementAdditions.removeAll(knownElements); + + Set knownElementRemovals = findPendingRemovals(parentElement, + localRemovals); + knownElementRemovals.retainAll(knownElements); + + knownElements.addAll(knownElementAdditions); + if (realizedElements != null) { + realizedElements.removeAll(knownElementRemovals); + } + + for (Iterator iterator = localAdditions.iterator(); iterator + .hasNext();) { + Object child = iterator.next(); + getOrCreateNode(child).addParent(parentElement); + } + + viewerUpdater.add(parentElement, localAdditions.toArray()); + viewerUpdater.remove(parentElement, localRemovals.toArray()); + + for (Iterator iterator = localRemovals.iterator(); iterator + .hasNext();) { + Object child = iterator.next(); + TreeNode childNode = getExistingNode(child); + if (childNode != null) + childNode.removeParent(parentElement); } - Set additions = event.diff.getAdditions(); - if (!additions.isEmpty()) { - for (Iterator iterator = additions.iterator(); iterator - .hasNext();) { - Object child = iterator.next(); - getOrCreateNode(child).addParent(parentElement); - } - viewerUpdater.add(parentElement, additions.toArray()); + if (realizedElements != null) { + realizedElements.addAll(knownElementAdditions); } + knownElements.removeAll(knownElementRemovals); } } @@ -113,10 +131,10 @@ * @param structureAdvisor * an advisor that will be consulted from the implementations of * the {@link #getParent(Object)} and - * {@link #hasChildren(Object)} methods, or null - * if no advisor is available. It is recommended that clients - * pass a non-null advisor if they can provide additional - * structural information about the tree. + * {@link #hasChildren(Object)} methods, or null if + * no advisor is available. It is recommended that clients pass a + * non-null advisor if they can provide additional structural + * information about the tree. */ public ObservableSetTreeContentProvider(IObservableFactory setFactory, TreeStructureAdvisor structureAdvisor) { @@ -159,4 +177,16 @@ public IObservableSet getKnownElements() { return impl.getKnownElements(); } + + /** + * Returns the set of known elements which have been realized in the viewer. + * Clients may track this set in order to perform custom actions on elements + * while they are known to be present in the viewer. + * + * @return the set of known elements which have been realized in the viewer. + * @since 1.3 + */ + public IObservableSet getRealizedElements() { + return impl.getRealizedElements(); + } } \ No newline at end of file Index: src/org/eclipse/jface/databinding/viewers/ObservableListTreeContentProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ObservableListTreeContentProvider.java,v retrieving revision 1.4 diff -u -r1.4 ObservableListTreeContentProvider.java --- src/org/eclipse/jface/databinding/viewers/ObservableListTreeContentProvider.java 29 Apr 2008 01:44:21 -0000 1.4 +++ src/org/eclipse/jface/databinding/viewers/ObservableListTreeContentProvider.java 22 Jul 2008 22:53:50 -0000 @@ -7,7 +7,7 @@ * * Contributors: * Matthew Hall - initial API and implementation (bug 207858) - * Matthew Hall - bug 226765 + * Matthew Hall - bugs 226765, 222991 *******************************************************************************/ package org.eclipse.jface.databinding.viewers; @@ -61,29 +61,59 @@ if (isViewerDisposed()) return; - final Set removals = ViewerElementSet.withComparer(comparer); + // Determine which elements are being added and removed + final Set localKnownElementAdditions = ViewerElementSet + .withComparer(comparer); + final Set localKnownElementRemovals = ViewerElementSet + .withComparer(comparer); event.diff.accept(new ListDiffVisitor() { - public void handleAdd(int index, Object child) { - // adds to known elements if new element - getOrCreateNode(child).addParent(parentElement); + public void handleAdd(int index, Object element) { + localKnownElementAdditions.add(element); + } + + public void handleRemove(int index, Object element) { + localKnownElementRemovals.add(element); + } + + public void handleMove(int oldIndex, int newIndex, + Object element) { + // ignore + } + }); + localKnownElementRemovals.removeAll(event.getObservableList()); + + Set knownElementAdditions = ViewerElementSet + .withComparer(comparer); + knownElementAdditions.addAll(localKnownElementAdditions); + knownElementAdditions.removeAll(knownElements); + + Set knownElementRemovals = findPendingRemovals(parentElement, + localKnownElementRemovals); + knownElementRemovals.retainAll(knownElements); + + knownElements.addAll(knownElementAdditions); + if (realizedElements != null) { + realizedElements.removeAll(knownElementRemovals); + } + + for (Iterator it = localKnownElementAdditions.iterator(); it + .hasNext();) { + getOrCreateNode(it.next()).addParent(parentElement); + } + event.diff.accept(new ListDiffVisitor() { + public void handleAdd(int index, Object child) { viewerUpdater.insert(parentElement, child, index); } public void handleRemove(int index, Object child) { viewerUpdater.remove(parentElement, child, index); - - removals.add(child); } public void handleReplace(int index, Object oldChild, Object newChild) { - getOrCreateNode(newChild).addParent(parentElement); - viewerUpdater.replace(parentElement, oldChild, newChild, index); - - removals.add(oldChild); } public void handleMove(int oldIndex, int newIndex, @@ -93,16 +123,18 @@ } }); - // For each removed element, do not remove node's parent if the - // element is still present elsewhere in the list. - removals.removeAll(event.getObservableList()); - for (Iterator iterator = removals.iterator(); iterator + for (Iterator it = localKnownElementRemovals.iterator(); it .hasNext();) { - TreeNode node = getExistingNode(iterator.next()); - if (node != null) - // removes from known elements if last parent + TreeNode node = getExistingNode(it.next()); + if (node != null) { node.removeParent(parentElement); + } } + + if (realizedElements != null) { + realizedElements.addAll(knownElementAdditions); + } + knownElements.removeAll(knownElementRemovals); } } @@ -137,10 +169,10 @@ * @param structureAdvisor * an advisor that will be consulted from the implementations of * the {@link #getParent(Object)} and - * {@link #hasChildren(Object)} methods, or null - * if no advisor is available. It is recommended that clients - * pass a non-null advisor if they can provide additional - * structural information about the tree. + * {@link #hasChildren(Object)} methods, or null if + * no advisor is available. It is recommended that clients pass a + * non-null advisor if they can provide additional structural + * information about the tree. */ public ObservableListTreeContentProvider(IObservableFactory listFactory, TreeStructureAdvisor structureAdvisor) { @@ -183,4 +215,16 @@ public IObservableSet getKnownElements() { return impl.getKnownElements(); } + + /** + * Returns the set of known elements which have been realized in the viewer. + * Clients may track this set in order to perform custom actions on elements + * while they are known to be present in the viewer. + * + * @return the set of known elements which have been realized in the viewer. + * @since 1.3 + */ + public IObservableSet getRealizedElements() { + return impl.getRealizedElements(); + } } \ No newline at end of file Index: src/org/eclipse/jface/databinding/viewers/ObservableListContentProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ObservableListContentProvider.java,v retrieving revision 1.12 diff -u -r1.12 ObservableListContentProvider.java --- src/org/eclipse/jface/databinding/viewers/ObservableListContentProvider.java 29 Apr 2008 01:44:21 -0000 1.12 +++ src/org/eclipse/jface/databinding/viewers/ObservableListContentProvider.java 22 Jul 2008 22:53:50 -0000 @@ -8,7 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Tom Schindl - bugfix in: 214355 - * Matthew Hall - bugs 215531, 226765 + * Matthew Hall - bugs 215531, 226765, 222991 *******************************************************************************/ package org.eclipse.jface.databinding.viewers; @@ -64,26 +64,44 @@ } public void handleListChange(ListChangeEvent event) { - if (isViewerDisposed()) + if (isViewerDisposed()) { return; - final Set removals = ViewerElementSet.withComparer(comparer); + } + + // Determine which elements were added and removed + final Set knownElementAdditions = ViewerElementSet + .withComparer(comparer); + final Set knownElementRemovals = ViewerElementSet + .withComparer(comparer); + event.diff.accept(new ListDiffVisitor() { + public void handleAdd(int index, Object element) { + knownElementAdditions.add(element); + } + + public void handleRemove(int index, Object element) { + knownElementRemovals.add(element); + } + }); + knownElementAdditions.removeAll(knownElements); + knownElementRemovals.removeAll(event.getObservableList()); + + knownElements.addAll(knownElementAdditions); + if (realizedElements != null) { + realizedElements.removeAll(knownElementRemovals); + } event.diff.accept(new ListDiffVisitor() { public void handleAdd(int index, Object element) { - knownElements.add(element); viewerUpdater.insert(element, index); } public void handleRemove(int index, Object element) { viewerUpdater.remove(element, index); - removals.add(element); } public void handleReplace(int index, Object oldElement, Object newElement) { - knownElements.add(newElement); viewerUpdater.replace(oldElement, newElement, index); - removals.add(oldElement); } public void handleMove(int oldIndex, int newIndex, @@ -92,10 +110,10 @@ } }); - // For each removed element, do not remove from known elements if - // the element is still present elsewhere in the list. - removals.removeAll(event.getObservableList()); - knownElements.removeAll(removals); + if (realizedElements != null) { + realizedElements.addAll(knownElementAdditions); + } + knownElements.removeAll(knownElementRemovals); } } @@ -130,4 +148,16 @@ public IObservableSet getKnownElements() { return impl.getKnownElements(); } + + /** + * Returns the set of known elements which have been realized in the viewer. + * Clients may track this set in order to perform custom actions on elements + * while they are known to be present in the viewer. + * + * @return the set of known elements which have been realized in the viewer. + * @since 1.3 + */ + public IObservableSet getRealizedElements() { + return impl.getRealizedElements(); + } } Index: src/org/eclipse/jface/databinding/viewers/ObservableSetContentProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ObservableSetContentProvider.java,v retrieving revision 1.14 diff -u -r1.14 ObservableSetContentProvider.java --- src/org/eclipse/jface/databinding/viewers/ObservableSetContentProvider.java 29 Apr 2008 01:44:21 -0000 1.14 +++ src/org/eclipse/jface/databinding/viewers/ObservableSetContentProvider.java 22 Jul 2008 22:53:50 -0000 @@ -8,7 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Brad Reynolds - bug 116920 - * Matthew Hall - bugs 215531, 226765 + * Matthew Hall - bugs 215531, 226765, 222991 *******************************************************************************/ package org.eclipse.jface.databinding.viewers; @@ -63,12 +63,16 @@ return; Set removals = event.diff.getRemovals(); - viewerUpdater.remove(removals.toArray()); - knownElements.removeAll(removals); - Set additions = event.diff.getAdditions(); + knownElements.addAll(additions); + realizedElements.removeAll(removals); + + viewerUpdater.remove(removals.toArray()); viewerUpdater.add(additions.toArray()); + + realizedElements.addAll(additions); + knownElements.removeAll(removals); } } @@ -103,4 +107,16 @@ public IObservableSet getKnownElements() { return impl.getKnownElements(); } + + /** + * Returns the set of known elements which have been realized in the viewer. + * Clients may track this set in order to perform custom actions on elements + * while they are known to be present in the viewer. + * + * @return the set of known elements which have been realized in the viewer. + * @since 1.3 + */ + public IObservableSet getRealizedElements() { + return impl.getRealizedElements(); + } } Index: src/org/eclipse/jface/internal/databinding/viewers/ObservableCollectionTreeContentProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/viewers/ObservableCollectionTreeContentProvider.java,v retrieving revision 1.6 diff -u -r1.6 ObservableCollectionTreeContentProvider.java --- src/org/eclipse/jface/internal/databinding/viewers/ObservableCollectionTreeContentProvider.java 2 Jul 2008 18:00:42 -0000 1.6 +++ src/org/eclipse/jface/internal/databinding/viewers/ObservableCollectionTreeContentProvider.java 22 Jul 2008 22:53:50 -0000 @@ -7,11 +7,13 @@ * * Contributors: * Matthew Hall - initial API and implementation (bug 207858) - * Matthew Hall - bugs 226765, 239015 + * Matthew Hall - bugs 226765, 239015, 222991 ******************************************************************************/ package org.eclipse.jface.internal.databinding.viewers; +import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -49,21 +51,40 @@ ITreeContentProvider { private Realm realm; + private Display display; + private IObservableValue viewerObservable; /** + * Element comparer used by the viewer (may be null). + */ + protected IElementComparer comparer; + + private IObservableFactory elementSetFactory; + + /** * Interfaces for sending updates to the viewer. */ protected TreeViewerUpdater viewerUpdater; /** - * Element comparer used by the viewer (may be null). + * Observable set of all elements known to the content provider. Subclasses + * must add new elements to this set before adding them to the + * viewer, and must remove old elements from this set after removing + * them from the viewer. */ - protected IElementComparer comparer; - - private IObservableSet knownElements; + protected IObservableSet knownElements; private IObservableSet unmodifiableKnownElements; + /** + * Observable set of known elements which have been realized in the viewer. + * Subclasses must add new elements to this set after adding them to + * the viewer, and must remove old elements from this set before + * removing them from the viewer. + */ + protected IObservableSet realizedElements; + private IObservableSet unmodifiableRealizedElements; + private IObservableFactory /* */collectionFactory; private Map /* */elementNodes; @@ -83,21 +104,19 @@ IObservableFactory collectionFactory, TreeStructureAdvisor structureAdvisor) { this.structureAdvisor = structureAdvisor; - realm = SWTObservables.getRealm(Display.getDefault()); + display = Display.getDefault(); + realm = SWTObservables.getRealm(display); viewerObservable = new WritableValue(realm); viewerUpdater = null; - // Known elements is a detail set of viewerObservable, so that when we - // get the viewer instance we can swap in a set that uses its - // IElementComparer, if any. - IObservableFactory knownElementsFactory = new IObservableFactory() { + elementSetFactory = new IObservableFactory() { public IObservable createObservable(Object target) { return ObservableViewerElementSet.withComparer(realm, null, getElementComparer((Viewer) target)); } }; knownElements = MasterDetailObservables.detailSet(viewerObservable, - knownElementsFactory, null); + elementSetFactory, null); unmodifiableKnownElements = Observables .unmodifiableObservableSet(knownElements); @@ -163,12 +182,39 @@ } private Object[] getChildren(Object element, boolean input) { - Object[] children = getOrCreateNode(element, input).getChildren(); + TreeNode node = getOrCreateNode(element, input); + Object[] children = node.getChildren().toArray(); for (int i = 0; i < children.length; i++) getOrCreateNode(children[i], false).addParent(element); + knownElements.addAll(node.getChildren()); + asyncUpdateRealizedElements(); return children; } + boolean asyncUpdatePending; + Runnable asyncUpdateRunnable; + + private void asyncUpdateRealizedElements() { + if (realizedElements == null) + return; + if (asyncUpdatePending) + return; + if (!realizedElements.equals(knownElements)) { + if (asyncUpdateRunnable == null) { + asyncUpdateRunnable = new Runnable() { + public void run() { + asyncUpdatePending = false; + if (realizedElements != null) { + realizedElements.addAll(knownElements); + } + } + }; + } + asyncUpdatePending = true; + display.asyncExec(asyncUpdateRunnable); + } + } + public boolean hasChildren(Object element) { if (structureAdvisor != null) { Boolean hasChildren = structureAdvisor.hasChildren(element); @@ -228,6 +274,7 @@ knownElements = null; unmodifiableKnownElements = null; collectionFactory = null; + asyncUpdateRunnable = null; } /** @@ -244,6 +291,62 @@ } /** + * Returns the set of known elements which have been realized in the viewer. + * Clients may track this set in order to perform custom actions on elements + * while they are known to be present in the viewer. + * + * @return the set of known elements which have been realized in the viewer. + * @since 1.3 + */ + public IObservableSet getRealizedElements() { + if (realizedElements == null) { + realizedElements = MasterDetailObservables.detailSet( + viewerObservable, elementSetFactory, null); + unmodifiableRealizedElements = Observables + .unmodifiableObservableSet(realizedElements); + asyncUpdateRealizedElements(); + } + return unmodifiableRealizedElements; + } + + /** + * Returns the set of all elements that would be removed from the known + * elements set if the given elements were removed as children of the given + * parent element. + * + * @param parent + * the parent element of the elements being removed + * @param elementsToBeRemoved + * the elements being removed + * @return the set of all elements that would be removed from the known + * elements set + */ + protected Set findPendingRemovals(Object parent, + Collection elementsToBeRemoved) { + Set result = ViewerElementSet.withComparer(comparer); + Set parents = ViewerElementSet.withComparer(comparer); + parents.add(parent); + accumulatePendingRemovals(result, parents, elementsToBeRemoved); + return result; + } + + private void accumulatePendingRemovals(Set removals, Set parents, + Collection elementsToRemove) { + for (Iterator it = elementsToRemove.iterator(); it.hasNext();) { + Object element = it.next(); + TreeNode node = getExistingNode(element); + if (node != null) { + if (parents.containsAll(node.getParents())) { + removals.add(element); + parents.add(element); + Collection children = node.getChildren(); + accumulatePendingRemovals(removals, parents, children); + } + } + } + } + + /** * Returns a listener which, when a collection change event is received, * updates the tree viewer through the {@link #viewerUpdater} field, and * maintains the adds and removes parents from the appropriate tree nodes. @@ -280,6 +383,12 @@ protected abstract void removeCollectionChangeListener( IObservableCollection collection, IObservablesListener listener); + protected boolean equal(Object left, Object right) { + if (comparer == null) + return Util.equals(left, right); + return comparer.equals(left, right); + } + protected final class TreeNode { private Object element; @@ -299,12 +408,6 @@ return element; } - private boolean equal(Object left, Object right) { - if (comparer == null) - return Util.equals(left, right); - return comparer.equals(left, right); - } - public void addParent(Object newParent) { if (parent == null) { parent = newParent; @@ -318,22 +421,20 @@ } public void removeParent(Object oldParent) { - if (parentSet != null) + if (parentSet != null) { parentSet.remove(oldParent); + if (parentSet.isEmpty()) + parentSet = null; + } if (equal(parent, oldParent)) { - if (parentSet == null || parentSet.isEmpty()) { + if (parentSet == null) { parent = null; } else { - Iterator iterator = parentSet.iterator(); - parent = iterator.next(); - iterator.remove(); + parent = parentSet.iterator().next(); } } - if (parentSet != null && parentSet.isEmpty()) - parentSet = null; - if (parent == null) { dispose(); } @@ -343,6 +444,14 @@ return parent; } + public Set getParents() { + if (parentSet != null) + return parentSet; + if (parent != null) + return Collections.singleton(parent); + return Collections.EMPTY_SET; + } + private void initChildren() { if (children == null) { children = (IObservableCollection) collectionFactory @@ -365,15 +474,14 @@ return !children.isEmpty(); } - Object[] getChildren() { + public Collection getChildren() { initChildren(); - return children.toArray(); + return children; } private void dispose() { if (element != null) { elementNodes.remove(element); - knownElements.remove(element); } if (children != null) { for (Iterator iterator = children.iterator(); iterator Index: src/org/eclipse/jface/internal/databinding/viewers/ObservableCollectionContentProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/viewers/ObservableCollectionContentProvider.java,v retrieving revision 1.3 diff -u -r1.3 ObservableCollectionContentProvider.java --- src/org/eclipse/jface/internal/databinding/viewers/ObservableCollectionContentProvider.java 29 Apr 2008 01:44:21 -0000 1.3 +++ src/org/eclipse/jface/internal/databinding/viewers/ObservableCollectionContentProvider.java 22 Jul 2008 22:53:50 -0000 @@ -7,7 +7,7 @@ * * Contributors: * Matthew Hall - initial API and implementation (bug 215531) - * Matthew Hall - bug 226765 + * Matthew Hall - bugs 226765, 222991 ******************************************************************************/ package org.eclipse.jface.internal.databinding.viewers; @@ -15,7 +15,6 @@ import org.eclipse.core.databinding.observable.IObservable; import org.eclipse.core.databinding.observable.IObservableCollection; import org.eclipse.core.databinding.observable.Observables; -import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory; import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables; import org.eclipse.core.databinding.observable.set.IObservableSet; @@ -39,6 +38,8 @@ */ public abstract class ObservableCollectionContentProvider implements IStructuredContentProvider { + private Display display; + private IObservableValue viewerObservable; /** @@ -46,6 +47,8 @@ */ protected IElementComparer comparer; + private IObservableFactory elementSetFactory; + /** * Interface for sending updates to the viewer. */ @@ -58,32 +61,39 @@ * them from the viewer. */ protected IObservableSet knownElements; - private IObservableSet unmodifiableKnownElements; + + /** + * Observable set of known elements which have been realized in the viewer. + * Subclasses must add new elements to this set after adding them to + * the viewer, and must remove old elements from this set before + * removing them from the viewer. + */ + protected IObservableSet realizedElements; + private IObservableSet unmodifiableRealizedElements; + private IObservableCollection observableCollection; /** * Constructs an ObservableCollectionContentProvider */ protected ObservableCollectionContentProvider() { - final Realm realm = SWTObservables.getRealm(Display.getDefault()); - viewerObservable = new WritableValue(realm); + display = Display.getDefault(); + viewerObservable = new WritableValue(SWTObservables.getRealm(display)); viewerUpdater = null; - // Known elements is a detail set of viewerObservable, so that when we - // get the viewer instance we can swap in a set that uses its - // IElementComparer, if any. - IObservableFactory knownElementsFactory = new IObservableFactory() { + elementSetFactory = new IObservableFactory() { public IObservable createObservable(Object target) { IElementComparer comparer = null; if (target instanceof StructuredViewer) comparer = ((StructuredViewer) target).getComparer(); - return ObservableViewerElementSet.withComparer(realm, null, - comparer); + return ObservableViewerElementSet.withComparer(SWTObservables + .getRealm(display), null, comparer); } }; + knownElements = MasterDetailObservables.detailSet(viewerObservable, - knownElementsFactory, null); + elementSetFactory, null); unmodifiableKnownElements = Observables .unmodifiableObservableSet(knownElements); @@ -93,9 +103,28 @@ public Object[] getElements(Object inputElement) { if (observableCollection == null) return new Object[0]; + + if (realizedElements != null) { + if (!realizedElements.equals(knownElements)) { + asyncUpdateRealizedElements(); + } + } + return observableCollection.toArray(); } + private void asyncUpdateRealizedElements() { + if (realizedElements == null) + return; + display.asyncExec(new Runnable() { + public void run() { + if (realizedElements != null) { + realizedElements.addAll(knownElements); + } + } + }); + } + public void dispose() { if (observableCollection != null) removeCollectionChangeListener(observableCollection); @@ -108,6 +137,9 @@ viewerUpdater = null; knownElements = null; unmodifiableKnownElements = null; + realizedElements = null; + unmodifiableRealizedElements = null; + display = null; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { @@ -203,4 +235,23 @@ public IObservableSet getKnownElements() { return unmodifiableKnownElements; } -} + + /** + * Returns the set of known elements which have been realized in the viewer. + * Clients may track this set in order to perform custom actions on elements + * while they are known to be present in the viewer. + * + * @return the set of known elements which have been realized in the viewer. + * @since 1.3 + */ + public IObservableSet getRealizedElements() { + if (realizedElements == null) { + realizedElements = MasterDetailObservables.detailSet( + viewerObservable, elementSetFactory, null); + unmodifiableRealizedElements = Observables + .unmodifiableObservableSet(realizedElements); + asyncUpdateRealizedElements(); + } + return unmodifiableRealizedElements; + } +} \ No newline at end of file