Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java')
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java892
1 files changed, 892 insertions, 0 deletions
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
new file mode 100644
index 000000000..1866a5623
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java
@@ -0,0 +1,892 @@
+/*******************************************************************************
+ * 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.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IAdaptable;
+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.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.TreeEvent;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.graphics.Color;
+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.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.progress.WorkbenchJob;
+
+/**
+ * A tree viewer that retrieves children and labels asynchronously via adapters
+ * and supports duplicate elements in the tree with different parents.
+ * Retrieving children and labels asynchrnously allows for arbitrary latency
+ * without blocking the UI thread.
+ * <p>
+ * TODO: tree editor not implemented TODO: table tree - what implications does
+ * it have on IPresentationAdapter?
+ *
+ * TODO: Deprecate the public/abstract deferred workbench adapter in favor of
+ * the presentation adapter.
+ * </p>
+ * <p>
+ * Clients may instantiate and subclass this class.
+ * </p>
+ *
+ * @since 3.2
+ */
+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;
+
+ /**
+ * Array of tree paths to be expanded. As paths are expanded, those entries
+ * are set to <code>null</code>.
+ */
+ private TreePath[] fPendingExpansion;
+
+ /**
+ * 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);
+ }
+
+ 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);
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * 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) {
+ fPendingExpansion = ((TreeSelection) selection).getPaths();
+ 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();
+ }
+ }
+ }
+
+ /**
+ * Attempts to expand all pending expansions.
+ */
+ synchronized void attemptExpansion() {
+ if (fPendingExpansion != null) {
+ for (int i = 0; i < fPendingExpansion.length; i++) {
+ TreePath path = fPendingExpansion[i];
+ if (path != null && attemptExpansion(path)) {
+ fPendingExpansion[i] = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * 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)
+ */
+ protected void inputChanged(Object input, Object oldInput) {
+ 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);
+ }
+ 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 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();
+ }
+
+ /**
+ * 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() {
+
+ public void run() {
+ // apply filters
+ 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();
+ }
+
+ 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 {
+ 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++;
+ }
+ }
+
+ });
+
+ 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);
+ }
+ }
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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();
+ }
+ }
+ }
+
+ 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.jface.viewers.ISelectionProvider#getSelection()
+ */
+ public ISelection getSelection() {
+ 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 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 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]);
+ }
+
+ public void add(final TreePath treePath) {
+ WorkbenchJob job = new WorkbenchJob("AsynchronousTreeViewer.add()") { //$NON-NLS-1$
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ Widget widget = getTree();
+ for (int i = 0; i < treePath.getSegmentCount(); i++) {
+ Object segment = treePath.getSegment(i);
+ if (!segment.equals(getInput())) {
+ Widget child = findChild(widget, segment, true);
+ if (child == null) {
+ return Status.OK_STATUS;
+ }
+ widget = child;
+ }
+ }
+ return Status.OK_STATUS;
+ }
+ };
+
+ job.setSystem(true);
+ job.schedule();
+ }
+
+ private Widget findChild(Widget widget, Object segment, boolean create) {
+ TreeItem[] items = null;
+ if (widget instanceof Tree) {
+ items = ((Tree) widget).getItems();
+ } else if (widget instanceof TreeItem) {
+ items = ((TreeItem) widget).getItems();
+ }
+
+ if (items != null) {
+ for (int i = 0; i < items.length; i++) {
+ TreeItem item = items[i];
+ if (segment.equals(item.getData())) {
+ return item;
+ }
+ }
+ }
+
+ if (create) {
+ // child doesn't exist. create it.
+ List datas = new ArrayList();
+ for (int i = 0; i < items.length; i++) {
+ Object data = items[i].getData();
+ if (data != null)
+ datas.add(data);
+ }
+ datas.add(segment);
+ setChildren(widget, datas);
+
+ // search for the new child and return it...
+ Widget child = findChild(widget, segment, false);
+ return child;
+ }
+
+ return null;
+ }
+
+ public void remove(final TreePath treePath) {
+ WorkbenchJob job = new WorkbenchJob("AsynchronousTreeViewer.remove()") { //$NON-NLS-1$
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ Object lastSegment = treePath.getLastSegment();
+ TreePath[] treePaths = getTreePaths(lastSegment);
+ if (treePaths != null) {
+ for (int i = 0; i < treePaths.length; i++) {
+ TreePath path = treePaths[i];
+ if (path.equals(treePath)) {
+ TreeItem treeItem = path.getTreeItem();
+ unmap(lastSegment, treeItem);
+ treeItem.dispose();
+ }
+ }
+ }
+ return Status.OK_STATUS;
+ }
+ };
+
+ }
+
+ void setLabels(Widget widget, String[] text, ImageDescriptor[] image) {
+ if (widget instanceof TreeItem) {
+ TreeItem item = (TreeItem) widget;
+ item.setText(text);
+ item.setImage(getImages(image));
+ }
+ }
+
+}

Back to the top