diff options
author | Kevin Barnes | 2006-01-16 22:37:09 +0000 |
---|---|---|
committer | Kevin Barnes | 2006-01-16 22:37:09 +0000 |
commit | fc8b289edff5ec9495bf3b1f0c6e5ec32058fb23 (patch) | |
tree | 777b38600f097dfd48dd108929ab89ef10f4d039 /org.eclipse.debug.ui | |
parent | e0b22608e971b53849f383723a9572bb2d5c06ad (diff) | |
download | eclipse.platform.debug-fc8b289edff5ec9495bf3b1f0c6e5ec32058fb23.tar.gz eclipse.platform.debug-fc8b289edff5ec9495bf3b1f0c6e5ec32058fb23.tar.xz eclipse.platform.debug-fc8b289edff5ec9495bf3b1f0c6e5ec32058fb23.zip |
https://bugs.eclipse.org/bugs/show_bug.cgi?id=123163
Diffstat (limited to 'org.eclipse.debug.ui')
10 files changed, 903 insertions, 1110 deletions
diff --git a/org.eclipse.debug.ui/.options b/org.eclipse.debug.ui/.options deleted file mode 100644 index a2688151a..000000000 --- a/org.eclipse.debug.ui/.options +++ /dev/null @@ -1,2 +0,0 @@ -org.eclipse.debug.ui/debug = false -org.eclipse.debug.ui/debug/viewer_cache_debug = false diff --git a/org.eclipse.debug.ui/META-INF/MANIFEST.MF b/org.eclipse.debug.ui/META-INF/MANIFEST.MF index 550c37d6c..3a6a3b5fd 100644 --- a/org.eclipse.debug.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.debug.ui/META-INF/MANIFEST.MF @@ -11,8 +11,6 @@ Export-Package: org.eclipse.debug.internal.ui;x-internal:=true, org.eclipse.debug.internal.ui.actions.breakpointGroups;x-internal:=true, org.eclipse.debug.internal.ui.actions.breakpoints, org.eclipse.debug.internal.ui.actions.context;x-internal:=true, - org.eclipse.debug.internal.ui.actions.expressions, - org.eclipse.debug.internal.ui.actions.variables, org.eclipse.debug.internal.ui.contexts;x-internal:=true, org.eclipse.debug.internal.ui.elements.adapters;x-internal:=true, org.eclipse.debug.internal.ui.importexport.breakpoints;x-internal:=true, @@ -51,4 +49,3 @@ Require-Bundle: org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)", org.eclipse.ui.editors;bundle-version="[3.2.0,4.0.0)", org.eclipse.core.runtime;bundle-version="[3.1.0,4.0.0)" Eclipse-LazyStart: true -Bundle-ClassPath: . diff --git a/org.eclipse.debug.ui/build.properties b/org.eclipse.debug.ui/build.properties index e17542238..10a4ee194 100644 --- a/org.eclipse.debug.ui/build.properties +++ b/org.eclipse.debug.ui/build.properties @@ -13,8 +13,7 @@ bin.includes = icons/,\ plugin.properties,\ .,\ about.html,\ - META-INF/,\ - .options + META-INF/ source.. = ui/ src.includes = about.html,\ diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java index aac2cca72..2207d546b 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java @@ -22,7 +22,6 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.util.Assert; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.ViewerSorter; @@ -36,11 +35,8 @@ import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swt.widgets.Widget; @@ -64,969 +60,912 @@ import org.eclipse.ui.progress.WorkbenchJob; * * @since 3.2 */ -public class AsynchronousTreeViewer extends AsynchronousViewer implements Listener { - - private static final Rectangle NOT_VISIBLE = new Rectangle(0, 0, 0, 0); - - /** - * A map of widget to parent widgets used to avoid requirement for parent - * access in UI thread. Currently used by update objects to detect/cancel - * updates on updates of children. - */ - private Map fItemToParentItem = new HashMap(); - - private AsynchronousTreeViewerContentManager fContentManager = new AsynchronousTreeViewerContentManager(); - - /** - * The tree - */ - private Tree fTree; - - /** - * Collection of tree paths to be expanded. A path is removed from the - * collection when it is expanded. The entire list is cleared when the input - * to the viewer changes. - */ - private List fPendingExpansion = new ArrayList(); - - /** - * Creates an asynchronous tree viewer on a newly-created tree control under - * the given parent. The tree control is created using the SWT style bits - * <code>MULTI, H_SCROLL, V_SCROLL,</code> and <code>BORDER</code>. The - * viewer has no input, no content provider, a default label provider, no - * sorter, and no filters. - * - * @param parent - * the parent control - */ - public AsynchronousTreeViewer(Composite parent) { - this(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.VIRTUAL); - } - - /** - * Creates an asynchronous tree viewer on a newly-created tree control under - * the given parent. The tree control is created using the given SWT style - * bits. The viewer has no input. - * - * @param parent - * the parent control - * @param style - * the SWT style bits used to create the tree. - */ - public AsynchronousTreeViewer(Composite parent, int style) { - this(new Tree(parent, style)); - } - - /** - * Creates an asynchronous tree viewer on the given tree control. The viewer - * has no input, no content provider, a default label provider, no sorter, - * and no filters. - * - * @param tree - * the tree control - */ - public AsynchronousTreeViewer(Tree tree) { - super(); - Assert.isTrue((tree.getStyle() & SWT.VIRTUAL) != 0); - - fTree = tree; - hookControl(fTree); - setUseHashlookup(false); - - tree.addTreeListener(new TreeListener() { - public void treeExpanded(TreeEvent e) { - ((TreeItem) e.item).setExpanded(true); - internalRefresh(e.item.getData(), e.item); - } - - public void treeCollapsed(TreeEvent e) { - } - }); - - tree.addMouseListener(new MouseListener() { - public void mouseUp(MouseEvent e) { - } - - public void mouseDown(MouseEvent e) { - } - - public void mouseDoubleClick(MouseEvent e) { - TreeItem item = ((Tree) e.widget).getItem(new Point(e.x, e.y)); - if (item != null) { - if (item.getExpanded()) { - item.setExpanded(false); - } else { - item.setExpanded(true); - internalRefresh(item.getData(), item); - } - } - } - }); - tree.addListener(SWT.SetData, this); - } - - /** - * Returns the tree control for this viewer. - * - * @return the tree control for this viewer - */ - public Tree getTree() { - return fTree; - } +public class AsynchronousTreeViewer extends AsynchronousViewer { + + /** + * A map of widget to parent widgets used to avoid requirement for parent + * access in UI thread. Currently used by update objects to detect/cancel + * updates on updates of children. + */ + private Map fItemToParentItem = new HashMap(); + + /** + * The tree + */ + private Tree fTree; + + /** + * Collection of tree paths to be expanded. A path is removed from the + * collection when it is expanded. The entire list is cleared when the + * input to the viewer changes. + */ + private List fPendingExpansion = new ArrayList(); + + /** + * Creates an asynchronous tree viewer on a newly-created tree control under + * the given parent. The tree control is created using the SWT style bits + * <code>MULTI, H_SCROLL, V_SCROLL,</code> and <code>BORDER</code>. The + * viewer has no input, no content provider, a default label provider, no + * sorter, and no filters. + * + * @param parent the parent control + */ + public AsynchronousTreeViewer(Composite parent) { + this(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + } + + /** + * Creates an asynchronous tree viewer on a newly-created tree control under + * the given parent. The tree control is created using the given SWT style + * bits. The viewer has no input. + * + * @param parent the parent control + * @param style the SWT style bits used to create the tree. + */ + public AsynchronousTreeViewer(Composite parent, int style) { + this(new Tree(parent, style)); + } + + /** + * Creates an asynchronous tree viewer on the given tree control. The viewer + * has no input, no content provider, a default label provider, no sorter, + * and no filters. + * + * @param tree the tree control + */ + public AsynchronousTreeViewer(Tree tree) { + super(); + fTree = tree; + hookControl(fTree); + setUseHashlookup(false); + tree.addTreeListener(new TreeListener() { + public void treeExpanded(TreeEvent e) { + ((TreeItem) e.item).setExpanded(true); + internalRefresh(e.item.getData(), e.item); + } - /** - * Updates whether the given element has children. - * - * @param element - * element to update - * @param widget - * widget associated with the element in this viewer's tree - */ - protected void updateHasChildren(Object element, Widget widget) { - IAsynchronousTreeContentAdapter adapter = getTreeContentAdapter(element); - if (adapter != null) { - IContainerRequestMonitor update = new ContainerRequestMonitor(widget, this); - schedule(update); - adapter.isContainer(element, getPresentationContext(), update); - } - } + public void treeCollapsed(TreeEvent e) { + } + }); + tree.addMouseListener(new MouseListener() { - /** - * Updates the children of the given element. - * - * @param parent - * element of which to update children - * @param widget - * widget associated with the element in this viewer's tree - */ - protected void updateChildren(Object parent, Widget widget) { - IAsynchronousTreeContentAdapter adapter = getTreeContentAdapter(parent); - if (adapter != null) { - IChildrenRequestMonitor update = new ChildrenRequestMonitor(widget, this); - schedule(update); - adapter.retrieveChildren(parent, getPresentationContext(), update); - } - } + public void mouseUp(MouseEvent e) { + } - /** - * Returns the tree element adapter for the given element or - * <code>null</code> if none. - * - * @param element - * element to retrieve adapter for - * @return presentation adapter or <code>null</code> - */ - protected IAsynchronousTreeContentAdapter getTreeContentAdapter(Object element) { - IAsynchronousTreeContentAdapter adapter = null; - if (element instanceof IAsynchronousTreeContentAdapter) { - adapter = (IAsynchronousTreeContentAdapter) element; - } else if (element instanceof IAdaptable) { - IAdaptable adaptable = (IAdaptable) element; - adapter = (IAsynchronousTreeContentAdapter) adaptable.getAdapter(IAsynchronousTreeContentAdapter.class); - } - return adapter; - } + public void mouseDown(MouseEvent e) { + } - /** - * Expands all elements in the given tree selection. - * - * @param selection - */ - public synchronized void expand(ISelection selection) { - if (selection instanceof TreeSelection) { + public void mouseDoubleClick(MouseEvent e) { + TreeItem item = ((Tree) e.widget).getItem(new Point(e.x, e.y)); + if (item != null) { + if (item.getExpanded()) { + item.setExpanded(false); + } else { + item.setExpanded(true); + internalRefresh(item.getData(), item); + } + } + } + }); + } + + /** + * Returns the tree control for this viewer. + * + * @return the tree control for this viewer + */ + public Tree getTree() { + return fTree; + } + + /** + * Updates whether the given element has children. + * + * @param element element to update + * @param widget widget associated with the element in this viewer's tree + */ + protected void updateHasChildren(Object element, Widget widget) { + IAsynchronousTreeContentAdapter adapter = getTreeContentAdapter(element); + if (adapter != null) { + IContainerRequestMonitor update = new ContainerRequestMonitor(widget, this); + schedule(update); + adapter.isContainer(element, getPresentationContext(), update); + } + } + + /** + * Updates the children of the given element. + * + * @param parent element of which to update children + * @param widget widget associated with the element in this viewer's tree + */ + protected void updateChildren(Object parent, Widget widget) { + IAsynchronousTreeContentAdapter adapter = getTreeContentAdapter(parent); + if (adapter != null) { + IChildrenRequestMonitor update = new ChildrenRequestMonitor(widget, this); + schedule(update); + adapter.retrieveChildren(parent, getPresentationContext(), update); + } + } + + /** + * Returns the tree element adapter for the given element or + * <code>null</code> if none. + * + * @param element element to retrieve adapter for + * @return presentation adapter or <code>null</code> + */ + protected IAsynchronousTreeContentAdapter getTreeContentAdapter(Object element) { + IAsynchronousTreeContentAdapter adapter = null; + if (element instanceof IAsynchronousTreeContentAdapter) { + adapter = (IAsynchronousTreeContentAdapter) element; + } else if (element instanceof IAdaptable) { + IAdaptable adaptable = (IAdaptable) element; + adapter = (IAsynchronousTreeContentAdapter) adaptable.getAdapter(IAsynchronousTreeContentAdapter.class); + } + return adapter; + } + + /** + * Expands all elements in the given tree selection. + * + * @param selection + */ + public synchronized void expand(ISelection selection) { + if (selection instanceof TreeSelection) { TreePath[] paths = ((TreeSelection) selection).getPaths(); for (int i = 0; i < paths.length; i++) { fPendingExpansion.add(paths[i]); } - if (getControl().getDisplay().getThread() == Thread.currentThread()) { - attemptExpansion(); - } else { - WorkbenchJob job = new WorkbenchJob("attemptExpansion") { //$NON-NLS-1$ - public IStatus runInUIThread(IProgressMonitor monitor) { - attemptExpansion(); - return Status.OK_STATUS; - } + if (getControl().getDisplay().getThread() == Thread.currentThread()) { + attemptExpansion(); + } else { + WorkbenchJob job = new WorkbenchJob("attemptExpansion") { //$NON-NLS-1$ + public IStatus runInUIThread(IProgressMonitor monitor) { + attemptExpansion(); + return Status.OK_STATUS; + } - }; - job.setSystem(true); - job.schedule(); - } - } - } + }; + job.setSystem(true); + job.schedule(); + } + } + } - /** - * Attempts to expand all pending expansions. - */ - synchronized void attemptExpansion() { - if (fPendingExpansion != null) { + /** + * Attempts to expand all pending expansions. + */ + synchronized void attemptExpansion() { + if (fPendingExpansion != null) { for (Iterator i = fPendingExpansion.iterator(); i.hasNext();) { TreePath path = (TreePath) i.next(); if (attemptExpansion(path)) { i.remove(); } } - } - } - - /** - * Attempts to expand the given tree path and returns whether the expansion - * was completed. - * - * @param path path to expand - * @return whether the expansion was completed - */ - synchronized boolean attemptExpansion(TreePath path) { - int segmentCount = path.getSegmentCount(); - for (int j = segmentCount - 1; j >= 0; j--) { - Object element = path.getSegment(j); - Widget[] treeItems = getWidgets(element); - if (treeItems != null) { - for (int k = 0; k < treeItems.length; k++) { - if (treeItems[k] instanceof TreeItem) { - TreeItem treeItem = (TreeItem) treeItems[k]; - TreePath treePath = getTreePath(treeItem); - if (path.startsWith(treePath)) { - if (!treeItem.isDisposed() && !treeItem.getExpanded() && treeItem.getItemCount() > 0) { - update(element); - updateChildren(element, treeItem); - expand(treeItem); - if (path.getSegmentCount() == treePath.getSegmentCount()) { - return true; - } - return false; - } - } - } - } - } - } - return false; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.Viewer#getControl() - */ - public Control getControl() { - return fTree; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.StructuredViewer#unmapAllElements() - */ - protected synchronized void unmapAllElements() { - super.unmapAllElements(); - fItemToParentItem.clear(); - fContentManager.clearAll(); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, - * java.lang.Object) - */ - synchronized protected void inputChanged(Object input, Object oldInput) { + } + } + + /** + * Attempts to expand the given tree path and returns whether the expansion + * was completed. + * + * @param path path to exapand + * @return whether the expansion was completed + */ + synchronized boolean attemptExpansion(TreePath path) { + int segmentCount = path.getSegmentCount(); + for (int j = segmentCount - 1; j >= 0; j--) { + Object element = path.getSegment(j); + Widget[] treeItems = getWidgets(element); + if (treeItems != null) { + for (int k = 0; k < treeItems.length; k++) { + if (treeItems[k] instanceof TreeItem) { + TreeItem treeItem = (TreeItem) treeItems[k]; + TreePath treePath = getTreePath(treeItem); + if (path.startsWith(treePath)) { + if (!treeItem.getExpanded() && treeItem.getItemCount() > 0) { + update(element); + updateChildren(element, treeItem); + expand(treeItem); + if (path.getSegmentCount() == treePath.getSegmentCount()) { + return true; + } + return false; + } + } + } + } + } + } + return false; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.Viewer#getControl() + */ + public Control getControl() { + return fTree; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.StructuredViewer#unmapAllElements() + */ + protected synchronized void unmapAllElements() { + super.unmapAllElements(); + fItemToParentItem.clear(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, + * java.lang.Object) + */ + synchronized protected void inputChanged(Object input, Object oldInput) { fPendingExpansion.clear(); - super.inputChanged(input, oldInput); - map(input, fTree); - refresh(); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#map(java.lang.Object, - * org.eclipse.swt.widgets.Widget) - */ - protected void map(Object element, Widget item) { - super.map(element, item); - if (item instanceof TreeItem) { - TreeItem treeItem = (TreeItem) item; - TreeItem parentItem = treeItem.getParentItem(); - if (parentItem != null) { - fItemToParentItem.put(treeItem, parentItem); - } - } - } - - /** - * Returns all paths to the given element or <code>null</code> if none. - * - * @param element - * @return paths to the given element or <code>null</code> - */ - public synchronized TreePath[] getTreePaths(Object element) { - Widget[] widgets = getWidgets(element); - if (widgets == null) { - return null; - } - TreePath[] paths = new TreePath[widgets.length]; - for (int i = 0; i < widgets.length; i++) { - List path = new ArrayList(); - path.add(element); - Widget widget = widgets[i]; - TreeItem parent = null; - if (widget instanceof TreeItem) { - TreeItem treeItem = (TreeItem) widget; - parent = getParentItem(treeItem); - } - while (parent != null) { - Object data = getElement(parent); - if (data == null) { - // if the parent is unmapped while attempting selection - return null; - } - path.add(0, data); - parent = getParentItem(parent); - } - if (!path.get(0).equals(getInput())) { - path.add(0, getInput()); - } - paths[i] = new TreePath(path.toArray()); - if (widget instanceof TreeItem) { - paths[i].setTreeItem((TreeItem) widget); - } - } - return paths; - } - - /** - * Constructs and returns a tree path for the given item. Must be called - * from the UI thread. - * - * @param item - * item to constuct a path for - * @return tree path for the item - */ - protected synchronized TreePath getTreePath(TreeItem item) { - TreeItem parent = item; - List path = new ArrayList(); - while (parent != null && !parent.isDisposed()) { - Object parentElement = parent.getData(); - Assert.isNotNull(parentElement); - path.add(0, parentElement); - parent = parent.getParentItem(); - } - path.add(0, fTree.getData()); - return new TreePath(path.toArray()); - } - - /** - * Called by <code>ContainerRequestMonitor</code> after it is determined - * if the widget contains children. - * - * @param widget - * @param containsChildren - */ - synchronized void setIsContainer(Widget widget, boolean containsChildren) { - TreeItem[] prevChildren = getItems(widget); - - if (containsChildren) { - if (prevChildren.length == 0) { - setItemCount(widget, 1); - if (widget instanceof Tree) { - updateChildren(widget.getData(), widget); - } else { - TreeItem treeItem = (TreeItem) widget; - if (treeItem.getExpanded()) { - updateChildren(widget.getData(), widget); - } - } - } else { - if (widget instanceof Tree || ((TreeItem) widget).getExpanded()) { - // if expanded, update the children - updateChildren(widget.getData(), widget); - } - } - } else { - for (int i = 0; i < prevChildren.length; i++) { - TreeItem item = prevChildren[i]; - Object element = getElement(item); - unmap(element, item); - } - setItemCount(widget, 0); - } - - attemptExpansion(); - attemptSelection(true); - } - - /** - * Adds a child at end of parent. - * - * @param parent - * @param child - */ - synchronized void add(Widget parentWidget, Object child) { - Object[] children = filter(new Object[] { child }); - if (children.length == 0) { - return; // added element was filtered out. - } - - //TODO sort??? + super.inputChanged(input, oldInput); + map(input, fTree); + refresh(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#map(java.lang.Object, + * org.eclipse.swt.widgets.Widget) + */ + protected void map(Object element, Widget item) { + super.map(element, item); + if (item instanceof TreeItem) { + TreeItem treeItem = (TreeItem) item; + TreeItem parentItem = treeItem.getParentItem(); + if (parentItem != null) { + fItemToParentItem.put(treeItem, parentItem); + } + } + } + + /** + * Returns all paths to the given element or <code>null</code> if none. + * + * @param element + * @return paths to the given element or <code>null</code> + */ + public synchronized TreePath[] getTreePaths(Object element) { + Widget[] widgets = getWidgets(element); + if (widgets == null) { + return null; + } + TreePath[] paths = new TreePath[widgets.length]; + for (int i = 0; i < widgets.length; i++) { + List path = new ArrayList(); + path.add(element); + Widget widget = widgets[i]; + TreeItem parent = null; + if (widget instanceof TreeItem) { + TreeItem treeItem = (TreeItem) widget; + parent = getParentItem(treeItem); + } + while (parent != null) { + Object data = getElement(parent); + if (data == null) { + // if the parent is unmapped while attempting selection + return null; + } + path.add(0, data); + parent = getParentItem(parent); + } + if (!path.get(0).equals(getInput())) { + path.add(0, getInput()); + } + paths[i] = new TreePath(path.toArray()); + if (widget instanceof TreeItem) { + paths[i].setTreeItem((TreeItem) widget); + } + } + return paths; + } + + /** + * Constructs and returns a tree path for the given item. Must be called + * from the UI thread. + * + * @param item item to constuct a path for + * @return tree path for the item + */ + protected synchronized TreePath getTreePath(TreeItem item) { + TreeItem parent = item; + List path = new ArrayList(); + while (parent != null) { + path.add(0, parent.getData()); + parent = parent.getParentItem(); + } + path.add(0, fTree.getData()); + return new TreePath(path.toArray()); + } + + /** + * Called by <code>ContainerRequestMonitor</code> after it is determined + * if the widget contains children. + * + * @param widget + * @param containsChildren + */ + synchronized void setIsContainer(Widget widget, boolean containsChildren) { + TreeItem[] prevChildren = null; + if (widget instanceof Tree) { + Tree tree = (Tree) widget; + prevChildren = tree.getItems(); + } else { + prevChildren = ((TreeItem) widget).getItems(); + } + if (containsChildren) { + if (prevChildren.length == 0) { + if (widget instanceof Tree) { + // update root elements in the tree + updateChildren(widget.getData(), widget); + } else { + // insert new dummy node to add + + newTreeItem(widget, 0); + if (((TreeItem) widget).getExpanded()) { + updateChildren(widget.getData(), widget); + } + } + } else { + if (widget instanceof Tree || ((TreeItem) widget).getExpanded()) { + // if expanded, update the children + updateChildren(widget.getData(), widget); + } + } + } else if (prevChildren.length > 0) { + // dispose previous children + for (int i = 0; i < prevChildren.length; i++) { + TreeItem prevChild = prevChildren[i]; + unmap(prevChild.getData(), prevChild); + prevChild.dispose(); + } + } + attemptExpansion(); + } + + /** + * Adds a child at end of parent. + * + * @param parent + * @param child + */ + synchronized void add(Widget parent, Object child) { + // refresh vs. add if not expanded + boolean expanded = true; + if (parent instanceof TreeItem) { + expanded = ((TreeItem)parent).getExpanded(); + } + if (expanded) { + Object[] objects = filter(new Object[]{child}); + if (objects.length == 1) { + child = objects[0]; + TreeItem item = newTreeItem(parent); + map(child, item); + internalRefresh(child, item); + } + } else { + internalRefresh(parent.getData(), parent); + } + attemptExpansion(); + attemptSelection(false); + } + + /** + * Called by <code>ChildrenRequestMonitor</code> after children have been + * retrieved. + * + * @param widget + * @param newChildren + */ + synchronized void setChildren(final Widget widget, final List newChildren) { + preservingSelection(new Runnable() { - fContentManager.addChildElement(parentWidget, child); - int childCount = fContentManager.getChildCount(parentWidget); - setItemCount(parentWidget, childCount); + public void run() { + // apply filters + Object[] children = filter(newChildren.toArray()); - attemptExpansion(); - attemptSelection(false); - } + // sort filtered children + ViewerSorter viewerSorter = getSorter(); + if (viewerSorter != null) { + viewerSorter.sort(AsynchronousTreeViewer.this, children); + } - /** - * Called by <code>ChildrenRequestMonitor</code> after children have been - * retrieved. - * - * @param widget - * @param newChildren - */ - synchronized void setChildren(final Widget widget, final List newChildren) { - // apply filters - final Object[] children = filter(newChildren.toArray()); - - // sort filtered children - ViewerSorter viewerSorter = getSorter(); - if (viewerSorter != null) { - viewerSorter.sort(AsynchronousTreeViewer.this, children); - } + // update tree + TreeItem[] prevItems = null; + if (widget instanceof Tree) { + Tree tree = (Tree) widget; + prevItems = tree.getItems(); + } else { + prevItems = ((TreeItem) widget).getItems(); + } - // update parent to children map - fContentManager.setChildElements(widget, children); - - preservingSelection(new Runnable() { - public void run() { - //unmap all old children - TreeItem[] currentChildItems = getItems(widget); - for (int i = 0; i < currentChildItems.length; i++) { - TreeItem item = currentChildItems[i]; - if (!item.isDisposed()) { - Object oldElement = item.getData(); - if (oldElement != null) { - unmap(oldElement, item); - } - } - } - - //map new children - for (int i = 0; i < currentChildItems.length; i++) { - TreeItem item = currentChildItems[i]; - if (i >= children.length) { - item.dispose(); - } else if (isVisible(item)) { - map(children[i], item); - internalRefresh(children[i], item); + int index = 0; + for (; index < children.length; index++) { + Object kid = children[index]; + TreeItem item = null; + if (index < prevItems.length) { + item = prevItems[index]; + Object oldData = item.getData(); + if (kid.equals(oldData)) { + if (kid != oldData) { + // if equal but not identical, remap the element + remap(kid, item); + } + } else { + unmap(oldData, item); + map(kid, item); + } } else { - clear(item); + item = newTreeItem(widget, index); + map(kid, item); } + internalRefresh(kid, item); + } + // remove left over old items + while (index < prevItems.length) { + TreeItem oldItem = prevItems[index]; + unmap(oldItem.getData(), oldItem); + oldItem.dispose(); + index++; } - - //set item count - setItemCount(widget, children.length); } - }); - - attemptExpansion(); - attemptSelection(true); - } - - protected void doUpdateItem(Widget item, Object element, boolean fullMap) { - super.doUpdateItem(item, element, fullMap); - updateHasChildren(element, item); - } - - private void setItemCount(Widget widget, int itemCount) { - if (widget == fTree) { - fTree.setItemCount(itemCount); - } else { - ((TreeItem) widget).setItemCount(itemCount); - } - } - - private TreeItem[] getItems(Widget widget) { - if (widget instanceof TreeItem) { - return ((TreeItem) widget).getItems(); - } else { - return fTree.getItems(); - } - } - - public synchronized void handleEvent(final Event event) { - preservingSelection(new Runnable() { - public void run() { - TreeItem item = (TreeItem) event.item; - Widget parentItem = item.getParentItem(); - int index = 0; - if (parentItem != null) { - index = ((TreeItem) parentItem).indexOf(item); - } else { - parentItem = fTree; - index = fTree.indexOf(item); - } - - Object element = fContentManager.getChildElement(parentItem, index); - if (element != null) { - map(element, item); - internalRefresh(element, true); - } - } - }); - attemptExpansion(); - attemptSelection(false); - } - - /** - * Expands the given tree item and all of its parents. Does *not* update - * elements or retrieve children. - * - * @param child - * item to expand - */ - private void expand(TreeItem child) { - if (!child.getExpanded()) { - child.setExpanded(true); - - TreeItem parent = child.getParentItem(); - if (parent != null) { - expand(parent); - } - } - } + }); - /** - * Unmaps the given item, and unmaps and disposes of all children of that - * item. Does not dispose of the given item. - * - * @param kid - * @param oldItem - */ - protected synchronized void unmap(Object element, Widget widget) { - TreeItem[] selection = fTree.getSelection(); - if (selection.length == 1 && isChild(widget, selection[0])) { - setSelection(null); - } - - TreeItem[] items = getItems(widget); - for (int i = 0; i < items.length; i++) { - TreeItem childItem = items[i]; - Object childElement = getElement(childItem); - if (childElement != null) { - unmap(childElement, childItem); + attemptExpansion(); + attemptSelection(true); + } + + /** + * Expands the given tree item and all of its parents. Does *not* update + * elements or retrieve children. + * + * @param child item to expand + */ + private void expand(TreeItem child) { + if (!child.getExpanded()) { + child.setExpanded(true); + + TreeItem parent = child.getParentItem(); + if (parent != null) { + expand(parent); } } - - super.unmap(element, widget); - - fItemToParentItem.remove(widget); - fContentManager.remove(widget); - } - - private void clear(Widget widget) { - if (widget instanceof TreeItem) { - TreeItem item = (TreeItem) widget; - TreeItem parentItem = item.getParentItem(); - if (parentItem != null) { - int index = parentItem.indexOf(item); - parentItem.clear(index, true); - } else { - int index = fTree.indexOf(item); - fTree.clear(index, true); - } - } - } - - private boolean isVisible(TreeItem item) { - Rectangle itemBounds = item.getBounds(); - return !NOT_VISIBLE.equals(itemBounds); - } - - private boolean isChild(Widget parent, TreeItem child) { - if (child == null) { - return false; - } else if (parent == child) { - return true; - } - return isChild(parent, child.getParentItem()); - } - - /** - * Returns the parent item for an item or <code>null</code> if none. - * - * @param item - * item for which parent is requested - * @return parent item or <code>null</code> - */ - protected synchronized TreeItem getParentItem(TreeItem item) { - return (TreeItem) fItemToParentItem.get(item); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object) - */ - protected Widget doFindInputItem(Object element) { - if (element.equals(getInput())) { - return fTree; - } - return null; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object) - */ - protected Widget doFindItem(Object element) { - Widget[] widgets = getWidgets(element); - if (widgets != null && widgets.length > 0) { - return widgets[0]; - } - return null; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.internal.ui.viewers.AsynchronousViewer#newSelectionFromWidget() - */ - protected ISelection newSelectionFromWidget() { - Control control = getControl(); - if (control == null || control.isDisposed()) { - return StructuredSelection.EMPTY; - } - List list = getSelectionFromWidget(); - return new TreeSelection((TreePath[]) list.toArray()); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget() - */ - protected synchronized List getSelectionFromWidget() { - TreeItem[] selection = fTree.getSelection(); - TreePath[] paths = new TreePath[selection.length]; - for (int i = 0; i < selection.length; i++) { - paths[i] = getTreePath(selection[i]); - } - return Arrays.asList(paths); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#internalRefresh(java.lang.Object, - * org.eclipse.swt.widgets.Widget) - */ - protected synchronized void internalRefresh(Object element, Widget item) { - super.internalRefresh(element, item); - updateHasChildren(element, item); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object) - */ - public void reveal(Object element) { - Widget[] widgets = getWidgets(element); - if (widgets != null && widgets.length > 0) { - // TODO: only reveals the first occurrence - should we reveal all? - TreeItem item = (TreeItem) widgets[0]; - Tree tree = (Tree) getControl(); - tree.showItem(item); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#doAttemptSelectionToWidget(org.eclipse.jface.viewers.ISelection, - * boolean) - */ - protected synchronized ISelection doAttemptSelectionToWidget(ISelection selection, boolean reveal) { - List remaining = new ArrayList(); - if (!selection.isEmpty()) { - List toSelect = new ArrayList(); - List theElements = new ArrayList(); - TreeSelection treeSelection = (TreeSelection) selection; - TreePath[] paths = treeSelection.getPaths(); - for (int i = 0; i < paths.length; i++) { - TreePath path = paths[i]; - if (path == null) { - continue; - } - TreePath[] treePaths = getTreePaths(path.getLastSegment()); - boolean selected = false; - if (treePaths != null) { - for (int j = 0; j < treePaths.length; j++) { - TreePath existingPath = treePaths[j]; - if (existingPath.equals(path)) { - TreeItem treeItem = existingPath.getTreeItem(); - if (!treeItem.isDisposed()) { - toSelect.add(treeItem); - theElements.add(path.getLastSegment()); - selected = true; - break; - } - } - } - } - if (!selected) { - remaining.add(path); - } - } - if (!toSelect.isEmpty()) { - final TreeItem[] items = (TreeItem[]) toSelect.toArray(new TreeItem[toSelect.size()]); - // TODO: hack to ensure selection contains 'selected' element - // instead of 'equivalent' element. Handles synch problems - // between - // set selection & refresh - for (int i = 0; i < items.length; i++) { - TreeItem item = items[i]; - Object element = theElements.get(i); - if (!item.isDisposed() && item.getData() != element) { - remap(element, item); - } - } - fTree.setSelection(items); - if (reveal) { - fTree.showItem(items[0]); - } - } - } else { - fTree.setSelection(new TreeItem[0]); - } - return new TreeSelection((TreePath[]) remaining.toArray(new TreePath[remaining.size()])); - } - - /** - * Collapses all items in the tree. - */ - public void collapseAll() { - TreeItem[] items = fTree.getItems(); - for (int i = 0; i < items.length; i++) { - TreeItem item = items[i]; - if (item.getExpanded()) - collapse(item); - } - } - - /** - * Collaspes the given item and all of its children items. - * - * @param item - * item to collapose recursively - */ - protected void collapse(TreeItem item) { - TreeItem[] items = item.getItems(); - for (int i = 0; i < items.length; i++) { - TreeItem child = items[i]; - if (child.getExpanded()) { - collapse(child); - } - } - item.setExpanded(false); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#setColor(org.eclipse.swt.widgets.Widget, - * org.eclipse.swt.graphics.RGB, org.eclipse.swt.graphics.RGB) - */ - void setColors(Widget widget, RGB[] foregrounds, RGB[] backgrounds) { - if (widget instanceof TreeItem) { - TreeItem item = (TreeItem) widget; - Color[] fgs = getColor(foregrounds); - Color[] bgs = getColor(backgrounds); - for (int i = 0; i < bgs.length; i++) { - item.setForeground(i, fgs[i]); - item.setBackground(i, bgs[i]); - } - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#setFont(org.eclipse.swt.widgets.Widget, - * org.eclipse.swt.graphics.FontData) - */ - void setFonts(Widget widget, FontData[] fontData) { - if (widget instanceof TreeItem) { - TreeItem item = (TreeItem) widget; - Font[] fonts = getFonts(fontData); - for (int i = 0; i < fonts.length; i++) { - item.setFont(i, fonts[i]); - } - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#getParent(org.eclipse.swt.widgets.Widget) - */ - protected Widget getParent(Widget widget) { - return (Widget) fItemToParentItem.get(widget); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#acceptsSelection(org.eclipse.jface.viewers.ISelection) - */ - protected boolean acceptsSelection(ISelection selection) { - return selection instanceof TreeSelection; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#getEmptySelection() - */ - protected ISelection getEmptySelection() { - return new TreeSelection(new TreePath[0]); - } - - /** - * Adds the item specified by the given tree path to this tree. Can be - * called in a non-UI thread. - * - * @param treePath - */ - public synchronized void add(TreePath treePath) { - int parentIndex = treePath.getSegmentCount() - 2; - if (parentIndex >= 0) { - // find the paths to the parent, if it's present - Object parent = treePath.getSegment(parentIndex); - TreePath[] paths = getTreePaths(parent); - if (paths != null) { - // find the right path - for (int i = 0; i < paths.length; i++) { - TreePath path = paths[i]; - if (treePath.startsWith(path)) { - Widget widget = path.getTreeItem(); - if (widget == null) { - widget = getTree(); - } - AddRequestMonitor addRequest = new AddRequestMonitor(widget, treePath, this); - schedule(addRequest); - addRequest.done(); - return; - } - } - } - // refresh the leaf parent, if any - for (int i = parentIndex - 1; i >= 0; i++) { - parent = treePath.getSegment(i); - paths = getTreePaths(parent); - if (paths != null) { - for (int j = 0; j < paths.length; j++) { - TreePath path = paths[j]; - if (treePath.startsWith(path)) { - Widget widget = path.getTreeItem(); - if (widget == null) { - widget = getTree(); - } - internalRefresh(parent, widget); - return; - } - } - } - } - } - } + } + + /** + * Creates a new tree item as a child of the given widget at the specified + * index. + * + * @param parent parent widget - a Tree or TreeItem + * @param index index at which to create new child + * @return tree item + */ + protected TreeItem newTreeItem(Widget parent, int index) { + if (parent instanceof Tree) { + return new TreeItem((Tree) parent, SWT.NONE, index); + } + return new TreeItem((TreeItem) parent, SWT.NONE, index); + } + + /** + * Creates a new tree item as a child of the given widget as last. + * + * @param parent parent widget - a Tree or TreeItem + * @return tree item + */ + protected TreeItem newTreeItem(Widget parent) { + if (parent instanceof Tree) { + return new TreeItem((Tree) parent, SWT.NONE); + } + return new TreeItem((TreeItem) parent, SWT.NONE); + } + + /** + * Unmaps the given item, and unmaps and disposes of all children of that + * item. Does not dispose of the given item. + * + * @param kid + * @param oldItem + */ + protected synchronized void unmap(Object kid, Widget widget) { + if (kid == null) { + // when unmapping a dummy item + return; + } + + TreeItem[] selection = fTree.getSelection(); + if (selection.length == 1 && isChild(widget, selection[0])) { + setSelection(null); + } + + super.unmap(kid, widget); + fItemToParentItem.remove(widget); + if (widget instanceof TreeItem) { + TreeItem item = (TreeItem) widget; + TreeItem[] children = item.getItems(); + for (int i = 0; i < children.length; i++) { + TreeItem child = children[i]; + unmap(child.getData(), child); + child.dispose(); + } + } + } - /** - * Removes the item specified in the given tree path from this tree. Can be - * called in a non-UI thread. - * - * @param treePath - */ - public synchronized void remove(TreePath treePath) { + private boolean isChild(Widget parent, TreeItem child) { + if (child==null) { + return false; + } else if (parent == child) { + return true; + } + return isChild(parent, child.getParentItem()); + } + + /** + * Returns the parent item for an item or <code>null</code> if none. + * + * @param item item for which parent is requested + * @return parent item or <code>null</code> + */ + protected synchronized TreeItem getParentItem(TreeItem item) { + return (TreeItem) fItemToParentItem.get(item); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object) + */ + protected Widget doFindInputItem(Object element) { + if (element.equals(getInput())) { + return fTree; + } + return null; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object) + */ + protected Widget doFindItem(Object element) { + Widget[] widgets = getWidgets(element); + if (widgets != null && widgets.length > 0) { + return widgets[0]; + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.viewers.AsynchronousViewer#newSelectionFromWidget() + */ + protected ISelection newSelectionFromWidget() { + Control control = getControl(); + if (control == null || control.isDisposed()) { + return StructuredSelection.EMPTY; + } + List list = getSelectionFromWidget(); + return new TreeSelection((TreePath[]) list.toArray()); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget() + */ + protected synchronized List getSelectionFromWidget() { + TreeItem[] selection = fTree.getSelection(); + TreePath[] paths = new TreePath[selection.length]; + for (int i = 0; i < selection.length; i++) { + paths[i] = getTreePath(selection[i]); + } + return Arrays.asList(paths); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#internalRefresh(java.lang.Object, + * org.eclipse.swt.widgets.Widget) + */ + protected synchronized void internalRefresh(Object element, Widget item) { + super.internalRefresh(element, item); + updateHasChildren(element, item); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object) + */ + public void reveal(Object element) { + Widget[] widgets = getWidgets(element); + if (widgets != null && widgets.length > 0) { + // TODO: only reveals the first occurrence - should we reveal all? + TreeItem item = (TreeItem) widgets[0]; + Tree tree = (Tree) getControl(); + tree.showItem(item); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#doAttemptSelectionToWidget(org.eclipse.jface.viewers.ISelection, + * boolean) + */ + protected synchronized ISelection doAttemptSelectionToWidget(ISelection selection, boolean reveal) { + List remaining = new ArrayList(); + if (!selection.isEmpty()) { + List toSelect = new ArrayList(); + List theElements = new ArrayList(); + TreeSelection treeSelection = (TreeSelection) selection; + TreePath[] paths = treeSelection.getPaths(); + for (int i = 0; i < paths.length; i++) { + TreePath path = paths[i]; + if (path == null) { + continue; + } + TreePath[] treePaths = getTreePaths(path.getLastSegment()); + boolean selected = false; + if (treePaths != null) { + for (int j = 0; j < treePaths.length; j++) { + TreePath existingPath = treePaths[j]; + if (existingPath.equals(path)) { + TreeItem treeItem = existingPath.getTreeItem(); + toSelect.add(treeItem); + theElements.add(path.getLastSegment()); + selected = true; + break; + } + } + } + if (!selected) { + remaining.add(path); + } + } + if (!toSelect.isEmpty()) { + final TreeItem[] items = (TreeItem[]) toSelect.toArray(new TreeItem[toSelect.size()]); + // TODO: hack to ensure selection contains 'selected' element + // instead of 'equivalent' element. Handles synch problems + // between + // set selection & refresh + for (int i = 0; i < items.length; i++) { + TreeItem item = items[i]; + Object element = theElements.get(i); + if (item.getData() != element) { + remap(element, item); + } + } + fTree.setSelection(items); + if (reveal) { + fTree.showItem(items[0]); + } + } + } else { + fTree.setSelection(new TreeItem[0]); + } + return new TreeSelection((TreePath[]) remaining.toArray(new TreePath[remaining.size()])); + } + + /** + * Collapses all items in the tree. + */ + public void collapseAll() { + TreeItem[] items = fTree.getItems(); + for (int i = 0; i < items.length; i++) { + TreeItem item = items[i]; + if (item.getExpanded()) + collapse(item); + } + } + + /** + * Collaspes the given item and all of its children items. + * + * @param item item to collapose recursively + */ + protected void collapse(TreeItem item) { + TreeItem[] items = item.getItems(); + for (int i = 0; i < items.length; i++) { + TreeItem child = items[i]; + if (child.getExpanded()) { + collapse(child); + } + } + item.setExpanded(false); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#setColor(org.eclipse.swt.widgets.Widget, + * org.eclipse.swt.graphics.RGB, org.eclipse.swt.graphics.RGB) + */ + void setColors(Widget widget, RGB[] foregrounds, RGB[] backgrounds) { + if (widget instanceof TreeItem) { + TreeItem item = (TreeItem) widget; + Color[] fgs = getColor(foregrounds); + Color[] bgs = getColor(backgrounds); + for (int i = 0; i < bgs.length; i++) { + item.setForeground(i, fgs[i]); + item.setBackground(i, bgs[i]); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#setFont(org.eclipse.swt.widgets.Widget, + * org.eclipse.swt.graphics.FontData) + */ + void setFonts(Widget widget, FontData[] fontData) { + if (widget instanceof TreeItem) { + TreeItem item = (TreeItem) widget; + Font[] fonts = getFonts(fontData); + for (int i = 0; i < fonts.length; i++) { + item.setFont(i, fonts[i]); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#getParent(org.eclipse.swt.widgets.Widget) + */ + protected Widget getParent(Widget widget) { + return (Widget) fItemToParentItem.get(widget); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#acceptsSelection(org.eclipse.jface.viewers.ISelection) + */ + protected boolean acceptsSelection(ISelection selection) { + return selection instanceof TreeSelection; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.debug.ui.viewers.AsynchronousViewer#getEmptySelection() + */ + protected ISelection getEmptySelection() { + return new TreeSelection(new TreePath[0]); + } + + /** + * Adds the item specified by the given tree path to this tree. + * Can be called in a non-UI thread. + * + * @param treePath + */ + public synchronized void add(TreePath treePath) { + int parentIndex = treePath.getSegmentCount() - 2; + if (parentIndex >= 0) { + // find the paths to the parent, if it's present + Object parent = treePath.getSegment(parentIndex); + TreePath[] paths = getTreePaths(parent); + if (paths != null) { + // find the right path + for (int i = 0; i < paths.length; i++) { + TreePath path = paths[i]; + if (treePath.startsWith(path)) { + Widget widget = path.getTreeItem(); + if (widget == null) { + widget = getTree(); + } + AddRequestMonitor addRequest = new AddRequestMonitor(widget, treePath, this); + schedule(addRequest); + addRequest.done(); + return; + } + } + } + // refresh the leaf parent, if any + for (int i = parentIndex -1; i >= 0; i++) { + parent = treePath.getSegment(i); + paths = getTreePaths(parent); + if (paths != null) { + for (int j = 0; j < paths.length; j++) { + TreePath path = paths[j]; + if (treePath.startsWith(path)) { + Widget widget = path.getTreeItem(); + if (widget == null) { + widget = getTree(); + } + internalRefresh(parent, widget); + return; + } + } + } + } + } + } + + + /** + * Removes the item specified in the given tree path from this tree. + * Can be called in a non-UI thread. + * + * @param treePath + */ + public synchronized void remove(TreePath treePath) { for (Iterator i = fPendingExpansion.iterator(); i.hasNext();) { TreePath expansionPath = (TreePath) i.next(); if (expansionPath.startsWith(treePath)) { i.remove(); } } - if (treePath.getSegmentCount() > 1) { - // find the paths to the element, if it's present - Object element = treePath.getLastSegment(); - TreePath[] paths = getTreePaths(element); - if (paths != null) { - // find the right path - for (int i = 0; i < paths.length; i++) { - TreePath path = paths[i]; - if (treePath.equals(path)) { - TreeItem item = path.getTreeItem(); - RemoveRequestMonitor request = new RemoveRequestMonitor(item, treePath, this); - schedule(request); - request.done(); - return; - } - } - } - // refresh the parent, if present - if (treePath.getSegmentCount() >= 2) { - element = treePath.getSegment(treePath.getSegmentCount() - 2); - paths = getTreePaths(element); - if (paths != null) { - // find the right path - for (int i = 0; i < paths.length; i++) { - TreePath path = paths[i]; - if (treePath.startsWith(path)) { - Widget widget = path.getTreeItem(); - if (widget == null) { - widget = getTree(); - } - internalRefresh(element, widget); - return; - } - } - } - } - } - } - - synchronized void remove(final Widget widget) { - preservingSelection(new Runnable() { - public void run() { - if (!(widget instanceof TreeItem)) { - return; - } - - fContentManager.remove(widget); - - TreeItem item = (TreeItem) widget; - Widget parentWidget = item.getParentItem(); - if (parentWidget == null) - parentWidget = fTree; + if (treePath.getSegmentCount() > 1) { + // find the paths to the element, if it's present + Object element = treePath.getLastSegment(); + TreePath[] paths = getTreePaths(element); + if (paths != null) { + // find the right path + for (int i = 0; i < paths.length; i++) { + TreePath path = paths[i]; + if (treePath.equals(path)) { + TreeItem item = path.getTreeItem(); + RemoveRequestMonitor request = new RemoveRequestMonitor(item, treePath, this); + schedule(request); + request.done(); + return; + } + } + } + // refresh the parent, if present + if (treePath.getSegmentCount() >= 2) { + element = treePath.getSegment(treePath.getSegmentCount() - 2); + paths = getTreePaths(element); + if (paths != null) { + // find the right path + for (int i = 0; i < paths.length; i++) { + TreePath path = paths[i]; + if (treePath.startsWith(path)) { + Widget widget = path.getTreeItem(); + if (widget == null) { + widget = getTree(); + } + internalRefresh(element, widget); + return; + } + } + } + } + } + } - Object element = getElement(widget); - if (element != null) - unmap(element, widget); - - item.dispose(); - setItemCount(parentWidget, fContentManager.getChildCount(parentWidget)); - } - }); - } + synchronized void remove(final Widget widget) { + preservingSelection(new Runnable() { + public void run() { + Object element = widget.getData(); + unmap(element, widget); + widget.dispose(); + } + }); + } + + void setLabels(Widget widget, String[] text, ImageDescriptor[] image) { + if (widget instanceof TreeItem) { + TreeItem item = (TreeItem) widget; + item.setText(text); + item.setImage(getImages(image)); + } + } - synchronized void setLabels(Widget widget, String[] text, ImageDescriptor[] image) { - if (widget instanceof TreeItem) { - TreeItem item = (TreeItem) widget; - if (!item.isDisposed()) { - item.setText(text); - item.setImage(getImages(image)); - } - } - } } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewerContentManager.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewerContentManager.java deleted file mode 100644 index fda668fe3..000000000 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewerContentManager.java +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2005 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.debug.internal.ui.viewers; - -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.swt.widgets.Widget; - -public class AsynchronousTreeViewerContentManager { - - private static final Object[] EMPTY = new Object[0]; - private Map fWidgetToChildElements = new HashMap(); - - public void clearAll() { - fWidgetToChildElements.clear(); - } - - public Object[] getChildElements(Widget parentWidget) { - Object[] childElements = (Object[]) fWidgetToChildElements.get(parentWidget); - if (childElements == null) - childElements = EMPTY; - return childElements; - } - - public void addChildElement(Widget parentWidget, Object child) { - Object[] originalChildren = getChildElements(parentWidget); - Object[] newChildren = new Object[originalChildren.length + 1]; - System.arraycopy(originalChildren, 0, newChildren, 0, originalChildren.length); - newChildren[originalChildren.length] = child; - fWidgetToChildElements.put(parentWidget, newChildren); - } - - public int getChildCount(Widget parentWidget) { - return getChildElements(parentWidget).length; - } - - public void setChildElements(Widget parentWidget, Object[] children) { - fWidgetToChildElements.put(parentWidget, children); - } - - public Object getChildElement(Widget parentWidget, int index) { - Object[] childElements = getChildElements(parentWidget); - if (index < childElements.length) - return childElements[index]; - else - return null; - } - - public void remove(Widget widget) { - if (widget instanceof TreeItem) { - TreeItem treeItem = (TreeItem) widget; - removeChildren(treeItem); - - Object data = treeItem.getData(); - if (data != null) { - Widget parentWidget = treeItem.getParentItem(); - if (parentWidget == null) - parentWidget = treeItem.getParent(); - - removeFromParent(parentWidget, data); - } - } else { - fWidgetToChildElements.clear(); - } - } - - private void removeFromParent(Widget parentWidget, Object data) { - Object[] childElements = getChildElements(parentWidget); - for (int i = 0; i < childElements.length; i++) { - Object object = childElements[i]; - if (data.equals(object)) { - Object[] newChildren = new Object[childElements.length - 1]; - System.arraycopy(childElements, 0, newChildren, 0, i); - System.arraycopy(childElements, i + 1, newChildren, i, newChildren.length - i); - fWidgetToChildElements.put(parentWidget, newChildren); - return; - } - } - } - - private void removeChildren(TreeItem item) { - TreeItem[] items = item.getItems(); - for (int i = 0; i < items.length; i++) { - removeChildren(items[i]); - } - - fWidgetToChildElements.remove(item); - } -} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousViewer.java index c6a9246aa..f2e48b95b 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousViewer.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousViewer.java @@ -63,8 +63,6 @@ import org.eclipse.ui.progress.WorkbenchJob; */ public abstract class AsynchronousViewer extends StructuredViewer { - public static boolean DEBUG_CACHE; - /** * A map of elements to associated tree items or tree */ @@ -346,11 +344,6 @@ public abstract class AsynchronousViewer extends StructuredViewer { fElementsToWidgets.clear(); fWidgetsToElements.clear(); disposeAllModelProxies(); - if (DEBUG_CACHE) { - System.out.println("unmapped all elements"); //$NON-NLS-1$ - System.out.println("\tfWidgetsToElements.size() " + fWidgetsToElements.size()); //$NON-NLS-1$ - System.out.println("\tfElementsToWidgets.size() " + fElementsToWidgets.size()); //$NON-NLS-1$ - } } /** @@ -397,13 +390,7 @@ public abstract class AsynchronousViewer extends StructuredViewer { fElementsToWidgets.put(element, items); } installModelProxy(element); - - if (DEBUG_CACHE) { - System.out.println("mapped " + element + " to " + item + "(hashcode: " + item.hashCode()+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - System.out.println("\tfWidgetsToElements.size() " + fWidgetsToElements.size()); //$NON-NLS-1$ - System.out.println("\tfElementsToWidgets.size() " + fElementsToWidgets.size()); //$NON-NLS-1$ - } - } + } /** * Updates the cached information that maps the given element to the @@ -415,23 +402,9 @@ public abstract class AsynchronousViewer extends StructuredViewer { */ protected void remap(Object element, Widget item) { item.setData(element); - installModelProxy(element); fWidgetsToElements.put(item, element); - Widget[] widgets = (Widget[]) fElementsToWidgets.remove(element); - if (widgets == null) { - fElementsToWidgets.put(element, new Widget[] {item}); - } else { - Widget[] newArray = new Widget[widgets.length + 1]; - System.arraycopy(widgets, 0, newArray, 0, widgets.length); - newArray[widgets.length] = item; - fElementsToWidgets.put(element, newArray); - } - - if (DEBUG_CACHE) { - System.out.println("remapped " + element + " to " + item + "(hashcode: " + item.hashCode()+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - System.out.println("\tfWidgetsToElements.size() " + fWidgetsToElements.size()); //$NON-NLS-1$ - System.out.println("\tfElementsToWidgets.size() " + fElementsToWidgets.size()); //$NON-NLS-1$ - } + Object widgets = fElementsToWidgets.remove(element); + fElementsToWidgets.put(element, widgets); } public IUpdatePolicy createUpdatePolicy() { @@ -505,8 +478,9 @@ public abstract class AsynchronousViewer extends StructuredViewer { if (kid == null) { // when unmapping a dummy item return; - } + } Widget[] widgets = getWidgets(kid); + fWidgetsToElements.remove(widget); if (widgets != null) { for (int i = 0; i < widgets.length; i++) { Widget item = widgets[i]; @@ -526,14 +500,6 @@ public abstract class AsynchronousViewer extends StructuredViewer { } } } - - fWidgetsToElements.remove(widget); - - if (DEBUG_CACHE) { - System.out.println("unmapped " + kid + " to " + widget + "(hashcode: " + widget.hashCode()+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - System.out.println("\tfWidgetsToElements.size() " + fWidgetsToElements.size()); //$NON-NLS-1$ - System.out.println("\tfElementsToWidgets.size() " + fElementsToWidgets.size()); //$NON-NLS-1$ - } } Image[] getImages(ImageDescriptor[] descriptors) { @@ -703,9 +669,7 @@ public abstract class AsynchronousViewer extends StructuredViewer { if (!force && !overrideSelection(fCurrentSelection, selection)) { return; } - fPendingSelection = selection; - if (getControl().getDisplay().getThread() == Thread.currentThread()) { attemptSelection(reveal); } else { @@ -819,25 +783,21 @@ public abstract class AsynchronousViewer extends StructuredViewer { * * @param reveal whether to reveal the selection */ - protected void attemptSelection(boolean reveal) { - if (fPendingSelection != null && !fPendingSelection.isEmpty()) { - ISelection currentSelection = null; - - synchronized (this) { - ISelection remaining = doAttemptSelectionToWidget(fPendingSelection, reveal); - - if (!fPendingSelection.equals(remaining) || (fPendingSelection.isEmpty() && fPendingSelection.equals(remaining))) { - fPendingSelection = remaining; - currentSelection = newSelectionFromWidget(); - if (isSuppressEqualSelections() && currentSelection.equals(fCurrentSelection)) { - return; - } - } - } - - if (currentSelection != null) { - updateSelection(currentSelection); - } + protected synchronized void attemptSelection(boolean reveal) { + if (fPendingSelection != null) { + ISelection remaining = doAttemptSelectionToWidget(fPendingSelection, reveal); + if (!fPendingSelection.equals(remaining) || + (fPendingSelection.isEmpty() && fPendingSelection.equals(remaining))) { + fPendingSelection = remaining; + if (fPendingSelection.isEmpty()) { + fPendingSelection = null; + } + ISelection currentSelection = newSelectionFromWidget(); + if (isSuppressEqualSelections() && currentSelection.equals(fCurrentSelection)) { + return; + } + updateSelection(currentSelection); + } } } @@ -845,11 +805,11 @@ public abstract class AsynchronousViewer extends StructuredViewer { * Controls whether selection change notification is sent even when * successive selections are equal. * - * TODO: what we really want is to fire selection change on ACTIVATE model - * change, even when selection is the same. + * TODO: what we really want is to fire selection change on ACTIVATE + * model change, even when selection is the same. * * @return whether to suppress change notification for equal successive - * selections + * selections */ protected boolean isSuppressEqualSelections() { return true; @@ -911,7 +871,7 @@ public abstract class AsynchronousViewer extends StructuredViewer { * @see org.eclipse.jface.viewers.StructuredViewer#preservingSelection(java.lang.Runnable) */ protected synchronized void preservingSelection(Runnable updateCode) { - if (fPendingSelection == null || fPendingSelection.isEmpty()) { + if (fPendingSelection == null) { ISelection oldSelection = null; try { // preserve selection diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java index a0a40589a..4d7a9a694 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java @@ -61,7 +61,7 @@ public class ThreadEventHandler extends DebugEventHandler { IThread thread = (IThread) event.getSource(); if (event.isEvaluation()) { ModelDelta delta = buildRootDelta(); - ModelDelta node = addPathToThread(delta, thread); + ModelDelta node = addPathToThraed(delta, thread); try { IStackFrame frame = thread.getTopStackFrame(); if (frame != null) { @@ -121,14 +121,14 @@ public class ThreadEventHandler extends DebugEventHandler { return new ModelDelta(DebugPlugin.getDefault().getLaunchManager(), IModelDelta.NOCHANGE); } - private ModelDelta addPathToThread(ModelDelta delta, IThread thread) { + private ModelDelta addPathToThraed(ModelDelta delta, IThread thread) { delta = delta.addNode(thread.getLaunch(), IModelDelta.NOCHANGE); - return delta.addNode(thread.getDebugTarget(), IModelDelta.EXPAND); + return delta.addNode(thread.getDebugTarget(), IModelDelta.NOCHANGE); } private void fireDeltaAndClearTopFrame(IThread thread, int flags) { ModelDelta delta = buildRootDelta(); - ModelDelta node = addPathToThread(delta, thread); + ModelDelta node = addPathToThraed(delta, thread); node.addNode(thread, flags); synchronized (this) { fLastTopFrame.remove(thread); @@ -138,7 +138,7 @@ public class ThreadEventHandler extends DebugEventHandler { private void fireDeltaUpdatingTopFrame(IThread thread, int flags) { ModelDelta delta = buildRootDelta(); - ModelDelta node = addPathToThread(delta, thread); + ModelDelta node = addPathToThraed(delta, thread); IStackFrame prev = null; synchronized (this) { prev = (IStackFrame) fLastTopFrame.get(thread); diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesView.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesView.java index bf1cc15d4..f0ef0ef30 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesView.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesView.java @@ -604,7 +604,7 @@ public class VariablesView extends AbstractDebugView implements IDebugContextLis setSashForm(new SashForm(parent, SWT.NONE)); // add tree viewer - final VariablesViewer variablesViewer = new VariablesViewer(getSashForm(), SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL, this); + final VariablesViewer variablesViewer = new VariablesViewer(getSashForm(), SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL, this); variablesViewer.setUseHashlookup(false); variablesViewer.getControl().addFocusListener(new FocusAdapter() { /* (non-Javadoc) diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewer.java index 315d955e4..0c7434e1d 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewer.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewer.java @@ -53,7 +53,7 @@ public class VariablesViewer extends AsynchronousTreeViewer{ */ protected void internalRefresh(Object element, Widget item) { super.internalRefresh(element, item); - if (fView != null && element.equals(((IStructuredSelection)getSelection()).getFirstElement())) { + if (element.equals(((IStructuredSelection)getSelection()).getFirstElement())) { fView.populateDetailPane(); } } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/InspectPopupDialog.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/InspectPopupDialog.java index 783bfcc78..66644e00c 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/InspectPopupDialog.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/InspectPopupDialog.java @@ -122,7 +122,7 @@ public class InspectPopupDialog extends DebugPopup { VariablesView view = getViewToEmulate(); - fVariablesViewer = new VariablesViewer(fSashForm, SWT.NO_TRIM | SWT.VIRTUAL, null); + fVariablesViewer = new VariablesViewer(fSashForm, SWT.NO_TRIM, null); fVariablesViewer.setContext(new PresentationContext(view)); fModelPresentation = new VariablesViewModelPresentation(); |