### Eclipse Workspace Patch 1.0 #P org.eclipse.jface Index: src/org/eclipse/jface/viewers/TreeViewer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface/src/org/eclipse/jface/viewers/TreeViewer.java,v retrieving revision 1.74 diff -u -r1.74 TreeViewer.java --- src/org/eclipse/jface/viewers/TreeViewer.java 13 Dec 2006 04:23:50 -0000 1.74 +++ src/org/eclipse/jface/viewers/TreeViewer.java 13 Dec 2006 09:07:04 -0000 @@ -13,23 +13,16 @@ package org.eclipse.jface.viewers; -import java.util.Iterator; import java.util.List; -import org.eclipse.jface.util.Policy; import org.eclipse.jface.viewers.CellEditor.LayoutData; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TreeEditor; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.TreeEvent; import org.eclipse.swt.events.TreeListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Item; -import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swt.widgets.Widget; @@ -53,30 +46,11 @@ * support sorting or filtering. *
*/ -public class TreeViewer extends AbstractTreeViewer { - - private static final String VIRTUAL_DISPOSE_KEY = Policy.JFACE - + ".DISPOSE_LISTENER"; //$NON-NLS-1$ - - /** - * This viewer's control. - */ +public class TreeViewer extends VirtualAbstractTreeViewer { private Tree tree; - - /** - * This viewer's tree editor. - */ + private TreeEditor treeEditor; - - /** - * Flag for whether the tree has been disposed of. - */ - private boolean treeIsDisposed = false; - - private boolean contentProviderIsLazy; - - private boolean contentProviderIsTreeBased; - + /** * Creates a tree viewer on a newly-created tree control under the given * parent. The tree control is created using the SWT style bits @@ -127,81 +101,14 @@ ((Tree) c).addTreeListener(listener); } - /* - * (non-Javadoc) Method declared in AbstractTreeViewer. - */ - protected void doUpdateItem(final Item item, Object element) { - if (!(item instanceof TreeItem)) { - return; - } - TreeItem treeItem = (TreeItem) item; - if (treeItem.isDisposed()) { - unmapElement(element, treeItem); - return; - } - - int columnCount = getTree().getColumnCount(); - if (columnCount == 0)// If no columns are created then fake one - columnCount = 1; - - for (int column = 0; column < columnCount; column++) { - ViewerColumn columnViewer = getViewerColumn(column); - columnViewer.refresh(updateCell(getViewerRowFromItem(treeItem), - column)); - - // As it is possible for user code to run the event - // loop check here. - if (item.isDisposed()) { - unmapElement(element, item); - return; - } - - } - + protected Widget doGetColumn(int index) { + return tree.getColumn(index); } - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.ColumnViewer#getColumnViewerOwner(int) - */ - protected Widget getColumnViewerOwner(int columnIndex) { - if (columnIndex < 0 || ( columnIndex > 0 && columnIndex >= getTree().getColumnCount() ) ) { - return null; - } - - if (getTree().getColumnCount() == 0)// Hang it off the table if it - return getTree(); - - return getTree().getColumn(columnIndex); + protected int doGetColumnCount() { + return tree.getColumnCount(); } - /** - * Override to handle tree paths. - * - * @see org.eclipse.jface.viewers.StructuredViewer#buildLabel(org.eclipse.jface.viewers.ViewerLabel, - * java.lang.Object) - */ - protected void buildLabel(ViewerLabel updateLabel, Object elementOrPath) { - Object element; - if (elementOrPath instanceof TreePath) { - TreePath path = (TreePath) elementOrPath; - IBaseLabelProvider provider = getLabelProvider(); - if (provider instanceof ITreePathLabelProvider) { - ITreePathLabelProvider pprov = (ITreePathLabelProvider) provider; - buildLabel(updateLabel, path, pprov); - return; - } - element = path.getLastSegment(); - } else { - element = elementOrPath; - } - super.buildLabel(updateLabel, element); - } - - /* - * (non-Javadoc) Method declared in AbstractTreeViewer. - */ protected Item[] getChildren(Widget o) { if (o instanceof TreeItem) { return ((TreeItem) o).getItems(); @@ -211,125 +118,52 @@ } return null; } - - /* - * (non-Javadoc) Method declared in Viewer. - */ + public Control getControl() { return tree; } - /* - * (non-Javadoc) Method declared in AbstractTreeViewer. - */ protected boolean getExpanded(Item item) { return ((TreeItem) item).getExpanded(); } - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.ColumnViewer#getItemAt(org.eclipse.swt.graphics.Point) - */ protected Item getItemAt(Point p) { - return getTree().getItem(p); - } - - /* - * (non-Javadoc) Method declared in AbstractTreeViewer. - */ - protected int getItemCount(Control widget) { - return ((Tree) widget).getItemCount(); - } - - /* - * (non-Javadoc) Method declared in AbstractTreeViewer. - */ - protected int getItemCount(Item item) { - return ((TreeItem) item).getItemCount(); + return tree.getItem(p); } - /* - * (non-Javadoc) Method declared in AbstractTreeViewer. - */ protected Item[] getItems(Item item) { return ((TreeItem) item).getItems(); } - + /** - * The tree viewer implementation of thisViewer
framework
- * method ensures that the given label provider is an instance of either
- * ITableLabelProvider
or ILabelProvider
. If
- * it is an ITableLabelProvider
, then it provides a separate
- * label text and image for each column. If it is an
- * ILabelProvider
, then it provides only the label text and
- * image for the first column, and any remaining columns are blank.
+ * Returns this tree viewer's tree control.
+ *
+ * @return the tree control
*/
- public IBaseLabelProvider getLabelProvider() {
- return super.getLabelProvider();
+ public Tree getTree() {
+ return tree;
}
-
- /*
- * (non-Javadoc) Method declared in AbstractTreeViewer.
- */
+
protected Item getParentItem(Item item) {
return ((TreeItem) item).getParentItem();
}
- /*
- * (non-Javadoc) Method declared in AbstractTreeViewer.
- */
protected Item[] getSelection(Control widget) {
return ((Tree) widget).getSelection();
}
- /**
- * Returns this tree viewer's tree control.
- *
- * @return the tree control
- */
- public Tree getTree() {
- return tree;
+ protected Item doGetParentItem(Item item) {
+ return ((TreeItem)item).getParentItem();
}
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.viewers.AbstractTreeViewer#hookControl(org.eclipse.swt.widgets.Control)
- */
- protected void hookControl(Control control) {
- super.hookControl(control);
- Tree treeControl = (Tree) control;
-
- if ((treeControl.getStyle() & SWT.VIRTUAL) != 0) {
- treeControl.addDisposeListener(new DisposeListener() {
- public void widgetDisposed(DisposeEvent e) {
- treeIsDisposed = true;
- unmapAllElements();
- }
- });
- treeControl.addListener(SWT.SetData, new Listener() {
-
- public void handleEvent(Event event) {
- if (contentProviderIsLazy) {
- TreeItem item = (TreeItem) event.item;
- TreeItem parentItem = item.getParentItem();
- int index;
- if (parentItem != null) {
- index = parentItem.indexOf(item);
- } else {
- index = getTree().indexOf(item);
- }
- virtualLazyUpdateWidget(
- parentItem == null ? (Widget) getTree()
- : parentItem, index);
- }
- }
-
- });
- }
+ protected int doIndexOf(Item parentItem, Item item) {
+ return ((TreeItem)parentItem).indexOf((TreeItem)item);
}
+ protected int doIndexOf(Item item) {
+ return tree.indexOf((TreeItem)item);
+ }
+
protected AbstractViewerEditor createViewerEditor() {
return new AbstractViewerEditor(this) {
@@ -361,110 +195,25 @@
};
}
-
- /*
- * (non-Javadoc) Method declared in AbstractTreeViewer.
- */
- protected Item newItem(Widget parent, int flags, int ix) {
- TreeItem item;
-
- if (parent instanceof TreeItem) {
- item = (TreeItem) createNewRowPart(getViewerRowFromItem(parent),
- flags, ix).getItem();
- } else {
- item = (TreeItem) createNewRowPart(null, flags, ix).getItem();
- }
-
- return item;
- }
-
- /*
- * (non-Javadoc) Method declared in AbstractTreeViewer.
- */
+
protected void removeAll(Control widget) {
((Tree) widget).removeAll();
}
- /*
- * (non-Javadoc) Method declared in AbstractTreeViewer.
- */
- protected void setExpanded(Item node, boolean expand) {
- ((TreeItem) node).setExpanded(expand);
- if (contentProviderIsLazy) {
- // force repaints to happen
- getControl().update();
- }
+ protected void doSetExpanded(Item item, boolean expanded) {
+ ((TreeItem) item).setExpanded(expanded);
}
- /*
- * (non-Javadoc) Method declared in AbstractTreeViewer.
- */
- protected void setSelection(List items) {
-
- Item[] current = getSelection(getTree());
-
- // Don't bother resetting the same selection
- if (isSameSelection(items, current)) {
- return;
- }
-
+ protected void doSetSelection(List items) {
TreeItem[] newItems = new TreeItem[items.size()];
items.toArray(newItems);
getTree().setSelection(newItems);
}
- /**
- * Returns true
if the given list and array of items refer to
- * the same model elements. Order is unimportant.
- *
- * @param items
- * the list of items
- * @param current
- * the array of items
- * @return true
if the refer to the same elements,
- * false
otherwise
- *
- * @since 3.1
- */
- protected boolean isSameSelection(List items, Item[] current) {
- // If they are not the same size then they are not equivalent
- int n = items.size();
- if (n != current.length) {
- return false;
- }
-
- CustomHashtable itemSet = newHashtable(n * 2 + 1);
- for (Iterator i = items.iterator(); i.hasNext();) {
- Item item = (Item) i.next();
- Object element = item.getData();
- itemSet.put(element, element);
- }
-
- // Go through the items of the current collection
- // If there is a mismatch return false
- for (int i = 0; i < current.length; i++) {
- if (current[i].getData() == null
- || !itemSet.containsKey(current[i].getData())) {
- return false;
- }
- }
-
- return true;
- }
-
- /*
- * (non-Javadoc) Method declared in AbstractTreeViewer.
- */
protected void showItem(Item item) {
getTree().showItem((TreeItem) item);
}
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.viewers.AbstractTreeViewer#getChild(org.eclipse.swt.widgets.Widget,
- * int)
- */
+
protected Item getChild(Widget widget, int index) {
if (widget instanceof TreeItem) {
return ((TreeItem) widget).getItem(index);
@@ -475,282 +224,38 @@
return null;
}
- protected void assertContentProviderType(IContentProvider provider) {
- if (provider instanceof ILazyTreeContentProvider
- || provider instanceof ILazyTreePathContentProvider) {
- return;
- }
- super.assertContentProviderType(provider);
+ protected void doSetItemCount(int count) {
+ getTree().setItemCount(count);
}
- protected Object[] getRawChildren(Object parent) {
- if (contentProviderIsLazy) {
- return new Object[0];
- }
- return super.getRawChildren(parent);
+ protected void doSetItemCount(Item item, int count) {
+ ((TreeItem)item).setItemCount(count);
}
- /**
- * For a TreeViewer with a tree with the VIRTUAL style bit set, set the
- * number of children of the given element or tree path. To set the number
- * of children of the invisible root of the tree, you can pass the input
- * object or an empty tree path.
- *
- * @param elementOrTreePath
- * the element, or tree path
- * @param count
- *
- * @since 3.2
- */
- public void setChildCount(final Object elementOrTreePath, final int count) {
- preservingSelection(new Runnable() {
- public void run() {
- if (internalIsInputOrEmptyPath(elementOrTreePath)) {
- getTree().setItemCount(count);
- return;
- }
- Widget[] items = internalFindItems(elementOrTreePath);
- for (int i = 0; i < items.length; i++) {
- TreeItem treeItem = (TreeItem) items[i];
- treeItem.setItemCount(count);
- }
- }
- });
+ protected int doGetItemCount() {
+ return tree.getItemCount();
}
- /**
- * For a TreeViewer with a tree with the VIRTUAL style bit set, replace the
- * given parent's child at index with the given element. If the given parent
- * is this viewer's input or an empty tree path, this will replace the root
- * element at the given index.
- * - * This method should be called by implementers of ILazyTreeContentProvider - * to populate this viewer. - *
- * - * @param parentElementOrTreePath - * the parent of the element that should be updated, or the tree - * path to that parent - * @param index - * the index in the parent's children - * @param element - * the new element - * - * @see #setChildCount(Object, int) - * @see ILazyTreeContentProvider - * @see ILazyTreePathContentProvider - * - * @since 3.2 - */ - public void replace(final Object parentElementOrTreePath, final int index, - final Object element) { - preservingSelection(new Runnable() { - public void run() { - if (internalIsInputOrEmptyPath(parentElementOrTreePath)) { - if (index < tree.getItemCount()) { - updateItem(tree.getItem(index), element); - } - } else { - Widget[] parentItems = internalFindItems(parentElementOrTreePath); - for (int i = 0; i < parentItems.length; i++) { - TreeItem parentItem = (TreeItem) parentItems[i]; - if (index < parentItem.getItemCount()) { - updateItem(parentItem.getItem(index), element); - } - } - } - } - - }); + protected Item doGetItem(int index) { + return tree.getItem(index); } - public boolean isExpandable(Object element) { - if (contentProviderIsLazy) { - TreeItem treeItem = (TreeItem) internalExpand(element, false); - if (treeItem == null) { - return false; - } - virtualMaterializeItem(treeItem); - return treeItem.getItemCount() > 0; - } - return super.isExpandable(element); + protected Item doGetItem(Item item, int index) { + return ((TreeItem)item).getItem(index); } - protected Object getParentElement(Object element) { - if (contentProviderIsLazy && !contentProviderIsTreeBased && !(element instanceof TreePath)) { - ILazyTreeContentProvider lazyTreeContentProvider = (ILazyTreeContentProvider) getContentProvider(); - return lazyTreeContentProvider.getParent(element); - } - if (contentProviderIsLazy && contentProviderIsTreeBased && !(element instanceof TreePath)) { - ILazyTreePathContentProvider lazyTreePathContentProvider = (ILazyTreePathContentProvider) getContentProvider(); - TreePath[] parents = lazyTreePathContentProvider - .getParents(element); - if (parents != null && parents.length > 0) { - return parents[0]; - } - } - return super.getParentElement(element); + protected void doClearAll(Item item, boolean all) { + ((TreeItem)item).clearAll(all); } - protected void createChildren(Widget widget) { - if (contentProviderIsLazy) { - Object element = widget.getData(); - if (element == null && widget instanceof TreeItem) { - // parent has not been materialized - virtualMaterializeItem((TreeItem) widget); - // try getting the element now that updateElement was called - element = widget.getData(); - } - if (element == null) { - // give up because the parent is still not materialized - return; - } - Item[] children = getChildren(widget); - if (children.length == 1 && children[0].getData() == null) { - // found a dummy node - virtualLazyUpdateChildCount(widget, children.length); - children = getChildren(widget); - } - // touch all children to make sure they are materialized - for (int i = 0; i < children.length; i++) { - if (children[i].getData() == null) { - virtualLazyUpdateWidget(widget, i); - } - } - return; - } - super.createChildren(widget); + protected int doGetItemCount(Item item) { + return ((TreeItem)item).getItemCount(); } - protected void internalAdd(Widget widget, Object parentElement, - Object[] childElements) { - if (contentProviderIsLazy) { - if (widget instanceof TreeItem) { - TreeItem ti = (TreeItem) widget; - int count = ti.getItemCount() + childElements.length; - ti.setItemCount(count); - ti.clearAll(false); - } else { - Tree t = (Tree) widget; - t.setItemCount(t.getItemCount() + childElements.length); - t.clearAll(false); - } - return; - } - super.internalAdd(widget, parentElement, childElements); + protected void doClearAll(boolean all) { + tree.clearAll(all); } - private void virtualMaterializeItem(TreeItem treeItem) { - if (treeItem.getData() != null) { - // already materialized - return; - } - if (!contentProviderIsLazy) { - return; - } - int index; - Widget parent = treeItem.getParentItem(); - if (parent == null) { - parent = treeItem.getParent(); - } - Object parentElement = parent.getData(); - if (parentElement != null) { - if (parent instanceof Tree) { - index = ((Tree) parent).indexOf(treeItem); - } else { - index = ((TreeItem) parent).indexOf(treeItem); - } - virtualLazyUpdateWidget(parent, index); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.AbstractTreeViewer#internalRefreshStruct(org.eclipse.swt.widgets.Widget, - * java.lang.Object, boolean) - */ - protected void internalRefreshStruct(Widget widget, Object element, - boolean updateLabels) { - if (contentProviderIsLazy) { - // first phase: update child counts - virtualRefreshChildCounts(widget, element); - // second phase: update labels - if (updateLabels) { - if (widget instanceof Tree) { - ((Tree) widget).clearAll(true); - } else if (widget instanceof TreeItem) { - ((TreeItem) widget).clearAll(true); - } - } - return; - } - super.internalRefreshStruct(widget, element, updateLabels); - } - - /** - * Traverses the visible (expanded) part of the tree and updates child - * counts. - * - * @param widget - * @param element - */ - private void virtualRefreshChildCounts(Widget widget, Object element) { - if (widget instanceof Tree || ((TreeItem) widget).getExpanded()) { - // widget shows children - it is safe to call getChildren - if (element != null) { - virtualLazyUpdateChildCount(widget, getChildren(widget).length); - } else { - if (widget instanceof Tree) { - ((Tree) widget).setItemCount(0); - } else { - ((TreeItem) widget).setItemCount(0); - } - } - // need to get children again because they might have been updated - // through a callback to setChildCount. - Item[] items = getChildren(widget); - for (int i = 0; i < items.length; i++) { - Item item = items[i]; - Object data = item.getData(); - if (data != null) { - virtualRefreshChildCounts(item, data); - } - } - } - } - - /* - * To unmap elements correctly, we need to register a dispose listener with - * the item if the tree is virtual. - */ - protected void mapElement(Object element, final Widget item) { - super.mapElement(element, item); - // make sure to unmap elements if the tree is virtual - if ((getTree().getStyle() & SWT.VIRTUAL) != 0) { - // only add a dispose listener if item hasn't already on assigned - // because it is reused - if (item.getData(VIRTUAL_DISPOSE_KEY) == null) { - item.setData(VIRTUAL_DISPOSE_KEY, Boolean.TRUE); - item.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - if (!treeIsDisposed) { - Object data = item.getData(); - if (usingElementMap() && data != null) { - unmapElement(data, item); - } - } - } - }); - } - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.ColumnViewer#getRowPartFromItem(org.eclipse.swt.widgets.Widget) - */ protected ViewerRow getViewerRowFromItem(Widget item) { ViewerRow part = (ViewerRow) item.getData(ViewerRow.ROWPART_KEY); @@ -760,16 +265,9 @@ return part; } + - /** - * Create a new ViewerRow at rowIndex - * - * @param parent - * @param style - * @param rowIndex - * @return ViewerRow - */ - private ViewerRow createNewRowPart(ViewerRow parent, int style, int rowIndex) { + protected ViewerRow doCreateNewRowPart(ViewerRow parent, int style, int rowIndex) { if (parent == null) { if (rowIndex >= 0) { return getViewerRowFromItem(new TreeItem(tree, style, rowIndex)); @@ -786,227 +284,9 @@ SWT.NONE)); } - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.AbstractTreeViewer#internalInitializeTree(org.eclipse.swt.widgets.Control) - */ - protected void internalInitializeTree(Control widget) { - if (contentProviderIsLazy) { - if (widget instanceof Tree && widget.getData() != null) { - virtualLazyUpdateChildCount(widget, 0); - return; - } - } - super.internalInitializeTree(tree); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.AbstractTreeViewer#updatePlus(org.eclipse.swt.widgets.Item, - * java.lang.Object) - */ - protected void updatePlus(Item item, Object element) { - if (contentProviderIsLazy) { - Object data = item.getData(); - int itemCount = 0; - if (data != null) { - // item is already materialized - itemCount = ((TreeItem) item).getItemCount(); - } - virtualLazyUpdateHasChildren(item, itemCount); - } else { - super.updatePlus(item, element); - } - } - - /** - * Removes the element at the specified index of the parent. The selection is updated if required. - * - * @param parentOrTreePath the parent element, the input element, or a tree path to the parent element - * @param index child index - * @since 3.3 - */ - public void remove(final Object parentOrTreePath, final int index) { - preservingSelection(new Runnable() { - public void run() { - if (internalIsInputOrEmptyPath(parentOrTreePath)) { - Tree tree = (Tree) getControl(); - if (index < tree.getItemCount()) { - TreeItem item = tree.getItem(index); - if (item.getData() != null) { - disassociate(item); - } - item.dispose(); - } - } else { - Widget[] parentItems = internalFindItems(parentOrTreePath); - for (int i = 0; i < parentItems.length; i++) { - TreeItem parentItem = (TreeItem) parentItems[i]; - if (index < parentItem.getItemCount()) { - TreeItem item = parentItem.getItem(index); - if (item.getData() != null) { - disassociate(item); - } - item.dispose(); - } - } - } - } - }); - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.AbstractTreeViewer#handleTreeExpand(org.eclipse.swt.events.TreeEvent) - */ - protected void handleTreeExpand(TreeEvent event) { - if (contentProviderIsLazy) { - if (event.item.getData() != null) { - Item[] children = getChildren(event.item); - if (children.length == 1 && children[0].getData()==null) { - // we have a dummy child node, ask for an updated child - // count - virtualLazyUpdateChildCount(event.item, children.length); - } - fireTreeExpanded(new TreeExpansionEvent(this, event.item - .getData())); - } - return; - } - super.handleTreeExpand(event); - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.AbstractTreeViewer#setContentProvider(org.eclipse.jface.viewers.IContentProvider) - */ - public void setContentProvider(IContentProvider provider) { - contentProviderIsLazy = (provider instanceof ILazyTreeContentProvider) - || (provider instanceof ILazyTreePathContentProvider); - contentProviderIsTreeBased = provider instanceof ILazyTreePathContentProvider; - super.setContentProvider(provider); - } - - /** - * For a TreeViewer with a tree with the VIRTUAL style bit set, inform the - * viewer about whether the given element or tree path has children. Avoid - * calling this method if the number of children has already been set. - * - * @param elementOrTreePath - * the element, or tree path - * @param hasChildren - * - * @since 3.3 - */ - public void setHasChildren(Object elementOrTreePath, boolean hasChildren) { - if (internalIsInputOrEmptyPath(elementOrTreePath)) { - if (hasChildren) { - virtualLazyUpdateChildCount(getTree(), getChildren(getTree()).length); - } else { - setChildCount(elementOrTreePath, 0); - } - return; - } - Widget[] items = internalFindItems(elementOrTreePath); - for (int i = 0; i < items.length; i++) { - TreeItem item = (TreeItem) items[i]; - if (!hasChildren) { - item.setItemCount(0); - } else { - if (!item.getExpanded()) { - item.setItemCount(1); - TreeItem child = item.getItem(0); - if (child.getData() != null) { - disassociate(child); - } - item.clear(0, true); - } - } - } - } - - /** - * Update the widget at index. - * @param widget - * @param index - */ - private void virtualLazyUpdateWidget(Widget widget, int index) { - if (contentProviderIsTreeBased) { - TreePath treePath; - if (widget instanceof Item) { - if (widget.getData() == null) { - // temporary fix to avoid a NPE (the tree will still be screwed up) - // see bug 167668 - return; - } - treePath = getTreePathFromItem((Item) widget); - } else { - treePath = TreePath.EMPTY; - } - ((ILazyTreePathContentProvider) getContentProvider()) - .updateElement(treePath, index); - } else { - ((ILazyTreeContentProvider) getContentProvider()).updateElement( - widget.getData(), index); - } - } - - /** - * Update the child count - * @param widget - * @param currentChildCount - */ - private void virtualLazyUpdateChildCount(Widget widget, int currentChildCount) { - if (contentProviderIsTreeBased) { - TreePath treePath; - if (widget instanceof Item) { - treePath = getTreePathFromItem((Item) widget); - } else { - treePath = TreePath.EMPTY; - } - ((ILazyTreePathContentProvider) getContentProvider()) - .updateChildCount(treePath, currentChildCount); - } else { - ((ILazyTreeContentProvider) getContentProvider()).updateChildCount(widget.getData(), currentChildCount); - } - } - - /** - * Update the item with the current child count. - * @param item - * @param currentChildCount - */ - private void virtualLazyUpdateHasChildren(Item item, int currentChildCount) { - if (contentProviderIsTreeBased) { - TreePath treePath; - treePath = getTreePathFromItem(item); - if (currentChildCount == 0) { - // item is not expanded (but may have a plus currently) - ((ILazyTreePathContentProvider) getContentProvider()) - .updateHasChildren(treePath); - } else { - ((ILazyTreePathContentProvider) getContentProvider()) - .updateChildCount(treePath, currentChildCount); - } - } else { - ((ILazyTreeContentProvider) getContentProvider()).updateChildCount(item.getData(), currentChildCount); - } - } - - private boolean internalIsInputOrEmptyPath(final Object elementOrTreePath) { - if (elementOrTreePath.equals(getInput())) - return true; - if (!(elementOrTreePath instanceof TreePath)) - return false; - return ((TreePath) elementOrTreePath).getSegmentCount() == 0; - } - - protected void disassociate(Item item) { - if (contentProviderIsLazy) { - // avoid causing a callback: - item.setText(" "); //$NON-NLS-1$ - } - super.disassociate(item); + + protected void doClear(Item item, boolean all) { + ((TreeItem)item).clear(0, true); } } Index: src/org/eclipse/jface/viewers/AbstractTreeViewer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java,v retrieving revision 1.106 diff -u -r1.106 AbstractTreeViewer.java --- src/org/eclipse/jface/viewers/AbstractTreeViewer.java 24 Nov 2006 13:09:36 -0000 1.106 +++ src/org/eclipse/jface/viewers/AbstractTreeViewer.java 13 Dec 2006 09:07:04 -0000 @@ -1920,6 +1920,7 @@ * element can be expanded, orfalse
if not
*/
public boolean isExpandable(Object elementOrTreePath) {
+ System.err.println("EXPANDABLE CHECK"); //$NON-NLS-1$
Object element;
TreePath path;
if (elementOrTreePath instanceof TreePath) {
@@ -1931,6 +1932,7 @@
}
IContentProvider cp = getContentProvider();
if (cp instanceof ITreePathContentProvider) {
+ System.err.println("TREE-PATH"); //$NON-NLS-1$
ITreePathContentProvider tpcp = (ITreePathContentProvider) cp;
if (path == null) {
// A path was not provided so try and find one
Index: src/org/eclipse/jface/viewers/AbstractTableViewer.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTableViewer.java,v
retrieving revision 1.1
diff -u -r1.1 AbstractTableViewer.java
--- src/org/eclipse/jface/viewers/AbstractTableViewer.java 8 Dec 2006 22:51:09 -0000 1.1
+++ src/org/eclipse/jface/viewers/AbstractTableViewer.java 13 Dec 2006 09:07:03 -0000
@@ -19,6 +19,7 @@
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Item;
@@ -1272,4 +1273,6 @@
* @since 3.3
*/
protected abstract void doClear(int index);
+
+ protected abstract Item getItemAt(Point p);
}
Index: src/org/eclipse/jface/viewers/VirtualAbstractTreeViewer.java
===================================================================
RCS file: src/org/eclipse/jface/viewers/VirtualAbstractTreeViewer.java
diff -N src/org/eclipse/jface/viewers/VirtualAbstractTreeViewer.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/viewers/VirtualAbstractTreeViewer.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,1152 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ * Tom Schindl Tree
control.
+ * + * This class is not intended to be subclassed outside the viewer framework. It + * is designed to be instantiated with a pre-existing SWT tree control and + * configured with a domain-specific content provider, label provider, element + * filter (optional), and element sorter (optional). + *
+ *
+ * Content providers for tree viewers must implement either the
+ * {@link ITreeContentProvider} interface, (as of 3.2) the
+ * {@link ILazyTreeContentProvider} interface, or (as of 3.3) the
+ * {@link ILazyTreePathContentProvider}. If the content provider is an
+ * ILazyTreeContentProvider
or an
+ * ILazyTreePathContentProvider
, the underlying Tree must be
+ * created using the {@link SWT#VIRTUAL} style bit, and the tree viewer will not
+ * support sorting or filtering.
+ *
Viewer
framework
+ * method ensures that the given label provider is an instance of either
+ * ITableLabelProvider
or ILabelProvider
. If
+ * it is an ITableLabelProvider
, then it provides a separate
+ * label text and image for each column. If it is an
+ * ILabelProvider
, then it provides only the label text and
+ * image for the first column, and any remaining columns are blank.
+ */
+ public IBaseLabelProvider getLabelProvider() {
+ return super.getLabelProvider();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.AbstractTreeViewer#hookControl(org.eclipse.swt.widgets.Control)
+ */
+ protected void hookControl(Control control) {
+ super.hookControl(control);
+
+ if ((control.getStyle() & SWT.VIRTUAL) != 0) {
+ control.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ treeIsDisposed = true;
+ unmapAllElements();
+ }
+ });
+ control.addListener(SWT.SetData, new Listener() {
+
+ public void handleEvent(Event event) {
+ if (contentProviderIsLazy) {
+ Item item = (Item) event.item;
+ Item parentItem = doGetParentItem(item);
+ int index;
+ if (parentItem != null) {
+ index = doIndexOf(parentItem, item);
+ } else {
+ index = doIndexOf(item);
+ }
+ virtualLazyUpdateWidget(
+ parentItem == null ? (Widget) getControl()
+ : parentItem, index);
+ }
+ }
+
+ });
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected Item newItem(Widget parent, int flags, int ix) {
+ Item item;
+
+ if (parent instanceof Item) {
+ item = doCreateNewRowPart(getViewerRowFromItem(parent), flags, ix)
+ .getItem();
+ } else {
+ item = doCreateNewRowPart(null, flags, ix).getItem();
+ }
+
+ return item;
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void setExpanded(Item node, boolean expand) {
+ doSetExpanded(node, expand);
+ if (contentProviderIsLazy) {
+ // force repaints to happen
+ getControl().update();
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared in AbstractTreeViewer.
+ */
+ protected void setSelection(List items) {
+
+ Item[] current = getSelection(getControl());
+
+ // Don't bother resetting the same selection
+ if (isSameSelection(items, current)) {
+ return;
+ }
+
+ doSetSelection(items);
+ }
+
+ /**
+ * Returns true
if the given list and array of items refer to
+ * the same model elements. Order is unimportant.
+ *
+ * @param items
+ * the list of items
+ * @param current
+ * the array of items
+ * @return true
if the refer to the same elements,
+ * false
otherwise
+ *
+ * @since 3.1
+ */
+ protected boolean isSameSelection(List items, Item[] current) {
+ // If they are not the same size then they are not equivalent
+ int n = items.size();
+ if (n != current.length) {
+ return false;
+ }
+
+ CustomHashtable itemSet = newHashtable(n * 2 + 1);
+ for (Iterator i = items.iterator(); i.hasNext();) {
+ Item item = (Item) i.next();
+ Object element = item.getData();
+ itemSet.put(element, element);
+ }
+
+ // Go through the items of the current collection
+ // If there is a mismatch return false
+ for (int i = 0; i < current.length; i++) {
+ if (current[i].getData() == null
+ || !itemSet.containsKey(current[i].getData())) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected void assertContentProviderType(IContentProvider provider) {
+ if (provider instanceof ILazyTreeContentProvider
+ || provider instanceof ILazyTreePathContentProvider) {
+ return;
+ }
+ super.assertContentProviderType(provider);
+ }
+
+ protected Object[] getRawChildren(Object parent) {
+ if (contentProviderIsLazy) {
+ return new Object[0];
+ }
+ return super.getRawChildren(parent);
+ }
+
+ /**
+ * For a TreeViewer with a tree with the VIRTUAL style bit set, set the
+ * number of children of the given element or tree path. To set the number
+ * of children of the invisible root of the tree, you can pass the input
+ * object or an empty tree path.
+ *
+ * @param elementOrTreePath
+ * the element, or tree path
+ * @param count
+ *
+ * @since 3.2
+ */
+ public void setChildCount(final Object elementOrTreePath, final int count) {
+ preservingSelection(new Runnable() {
+ public void run() {
+ if (internalIsInputOrEmptyPath(elementOrTreePath)) {
+ doSetItemCount(count);
+ return;
+ }
+ Widget[] items = internalFindItems(elementOrTreePath);
+ for (int i = 0; i < items.length; i++) {
+ doSetItemCount((Item) items[i], count);
+ }
+ }
+ });
+ }
+
+ /**
+ * For a TreeViewer with a tree with the VIRTUAL style bit set, replace the
+ * given parent's child at index with the given element. If the given parent
+ * is this viewer's input or an empty tree path, this will replace the root
+ * element at the given index.
+ * + * This method should be called by implementers of ILazyTreeContentProvider + * to populate this viewer. + *
+ * + * @param parentElementOrTreePath + * the parent of the element that should be updated, or the tree + * path to that parent + * @param index + * the index in the parent's children + * @param element + * the new element + * + * @see #setChildCount(Object, int) + * @see ILazyTreeContentProvider + * @see ILazyTreePathContentProvider + * + * @since 3.2 + */ + public void replace(final Object parentElementOrTreePath, final int index, + final Object element) { + preservingSelection(new Runnable() { + public void run() { + if (internalIsInputOrEmptyPath(parentElementOrTreePath)) { + if (index < doGetItemCount()) { + updateItem(doGetItem(index), element); + } + } else { + Widget[] parentItems = internalFindItems(parentElementOrTreePath); + for (int i = 0; i < parentItems.length; i++) { + Item parentItem = (Item) parentItems[i]; + if (index < doGetItemCount(parentItem)) { + updateItem(doGetItem(parentItem, index), element); + } + } + } + } + + }); + } + + public boolean isExpandable(Object element) { + if (contentProviderIsLazy) { + Item treeItem = (Item) internalExpand(element, false); + if (treeItem == null) { + return false; + } + virtualMaterializeItem(treeItem); + return doGetItemCount(treeItem) > 0; + } + return super.isExpandable(element); + } + + protected Object getParentElement(Object element) { + if (contentProviderIsLazy && !contentProviderIsTreeBased + && !(element instanceof TreePath)) { + ILazyTreeContentProvider lazyTreeContentProvider = (ILazyTreeContentProvider) getContentProvider(); + return lazyTreeContentProvider.getParent(element); + } + if (contentProviderIsLazy && contentProviderIsTreeBased + && !(element instanceof TreePath)) { + ILazyTreePathContentProvider lazyTreePathContentProvider = (ILazyTreePathContentProvider) getContentProvider(); + TreePath[] parents = lazyTreePathContentProvider + .getParents(element); + if (parents != null && parents.length > 0) { + return parents[0]; + } + } + return super.getParentElement(element); + } + + protected void createChildren(Widget widget) { + if (contentProviderIsLazy) { + Object element = widget.getData(); + if (element == null && widget instanceof Item) { + // parent has not been materialized + virtualMaterializeItem((Item) widget); + // try getting the element now that updateElement was called + element = widget.getData(); + } + if (element == null) { + // give up because the parent is still not materialized + return; + } + Item[] children = getChildren(widget); + if (children.length == 1 && children[0].getData() == null) { + // found a dummy node + virtualLazyUpdateChildCount(widget, children.length); + children = getChildren(widget); + } + // touch all children to make sure they are materialized + for (int i = 0; i < children.length; i++) { + if (children[i].getData() == null) { + virtualLazyUpdateWidget(widget, i); + } + } + return; + } + super.createChildren(widget); + } + + protected void internalAdd(Widget widget, Object parentElement, + Object[] childElements) { + if (contentProviderIsLazy) { + if (widget instanceof Item) { + Item ti = (Item) widget; + int count = doGetItemCount(ti) + childElements.length; + doSetItemCount(ti, count); + doClearAll(ti, false); + } else { + doSetItemCount(doGetItemCount() + childElements.length); + doClearAll(false); + } + return; + } + super.internalAdd(widget, parentElement, childElements); + } + + private void virtualMaterializeItem(Item treeItem) { + if (treeItem.getData() != null) { + // already materialized + return; + } + if (!contentProviderIsLazy) { + return; + } + int index; + Widget parent = doGetParentItem(treeItem); + if (parent == null) { + parent = getControl(); + } + Object parentElement = parent.getData(); + if (parentElement != null) { + if (parent instanceof Item) { + index = doIndexOf((Item) parent, treeItem); + } else { + index = doIndexOf(treeItem); + } + virtualLazyUpdateWidget(parent, index); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.AbstractTreeViewer#internalRefreshStruct(org.eclipse.swt.widgets.Widget, + * java.lang.Object, boolean) + */ + protected void internalRefreshStruct(Widget widget, Object element, + boolean updateLabels) { + if (contentProviderIsLazy) { + // first phase: update child counts + virtualRefreshChildCounts(widget, element); + // second phase: update labels + if (updateLabels) { + if (widget instanceof Item) { + doClearAll((Item) widget, true); + } else if (widget instanceof Control) { + doClearAll(true); + } + } + return; + } + super.internalRefreshStruct(widget, element, updateLabels); + } + + /** + * Traverses the visible (expanded) part of the tree and updates child + * counts. + * + * @param widget + * @param element + */ + private void virtualRefreshChildCounts(Widget widget, Object element) { + if (widget instanceof Control || getExpanded((Item) widget)) { + // widget shows children - it is safe to call getChildren + if (element != null) { + virtualLazyUpdateChildCount(widget, getChildren(widget).length); + } else { + if (widget instanceof Item) { + doSetItemCount((Item) widget, 0); + } else { + doSetItemCount(0); + } + } + // need to get children again because they might have been updated + // through a callback to setChildCount. + Item[] items = getChildren(widget); + for (int i = 0; i < items.length; i++) { + Item item = items[i]; + Object data = item.getData(); + if (data != null) { + virtualRefreshChildCounts(item, data); + } + } + } + } + + /* + * To unmap elements correctly, we need to register a dispose listener with + * the item if the tree is virtual. + */ + protected void mapElement(Object element, final Widget item) { + super.mapElement(element, item); + // make sure to unmap elements if the tree is virtual + if ((getControl().getStyle() & SWT.VIRTUAL) != 0) { + // only add a dispose listener if item hasn't already on assigned + // because it is reused + if (item.getData(VIRTUAL_DISPOSE_KEY) == null) { + item.setData(VIRTUAL_DISPOSE_KEY, Boolean.TRUE); + item.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + if (!treeIsDisposed) { + Object data = item.getData(); + if (usingElementMap() && data != null) { + unmapElement(data, item); + } + } + } + }); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.AbstractTreeViewer#internalInitializeTree(org.eclipse.swt.widgets.Control) + */ + protected void internalInitializeTree(Control widget) { + if (contentProviderIsLazy) { + if (widget.getData() != null) { + virtualLazyUpdateChildCount(widget, 0); + return; + } + } + super.internalInitializeTree(getControl()); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.AbstractTreeViewer#updatePlus(org.eclipse.swt.widgets.Item, + * java.lang.Object) + */ + protected void updatePlus(Item item, Object element) { + if (contentProviderIsLazy) { + Object data = item.getData(); + int itemCount = 0; + if (data != null) { + // item is already materialized + itemCount = doGetItemCount(item); + } + virtualLazyUpdateHasChildren(item, itemCount); + } else { + super.updatePlus(item, element); + } + } + + /** + * Removes the element at the specified index of the parent. The selection + * is updated if required. + * + * @param parentOrTreePath + * the parent element, the input element, or a tree path to the + * parent element + * @param index + * child index + * @since 3.3 + */ + public void remove(final Object parentOrTreePath, final int index) { + preservingSelection(new Runnable() { + public void run() { + if (internalIsInputOrEmptyPath(parentOrTreePath)) { + + if (index < doGetItemCount()) { + Item item = doGetItem(index); + if (item.getData() != null) { + disassociate(item); + } + item.dispose(); + } + } else { + Widget[] parentItems = internalFindItems(parentOrTreePath); + for (int i = 0; i < parentItems.length; i++) { + Item parentItem = (Item) parentItems[i]; + if (index < doGetItemCount(parentItem)) { + Item item = doGetItem(parentItem, index); + if (item.getData() != null) { + disassociate(item); + } + item.dispose(); + } + } + } + } + }); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.AbstractTreeViewer#handleTreeExpand(org.eclipse.swt.events.TreeEvent) + */ + protected void handleTreeExpand(TreeEvent event) { + if (contentProviderIsLazy) { + if (event.item.getData() != null) { + Item[] children = getChildren(event.item); + if (children.length == 1 && children[0].getData() == null) { + // we have a dummy child node, ask for an updated child + // count + virtualLazyUpdateChildCount(event.item, children.length); + } + fireTreeExpanded(new TreeExpansionEvent(this, event.item + .getData())); + } + return; + } + super.handleTreeExpand(event); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.AbstractTreeViewer#setContentProvider(org.eclipse.jface.viewers.IContentProvider) + */ + public void setContentProvider(IContentProvider provider) { + contentProviderIsLazy = (provider instanceof ILazyTreeContentProvider) + || (provider instanceof ILazyTreePathContentProvider); + contentProviderIsTreeBased = provider instanceof ILazyTreePathContentProvider; + super.setContentProvider(provider); + } + + /** + * For a TreeViewer with a tree with the VIRTUAL style bit set, inform the + * viewer about whether the given element or tree path has children. Avoid + * calling this method if the number of children has already been set. + * + * @param elementOrTreePath + * the element, or tree path + * @param hasChildren + * + * @since 3.3 + */ + public void setHasChildren(Object elementOrTreePath, boolean hasChildren) { + if (internalIsInputOrEmptyPath(elementOrTreePath)) { + if (hasChildren) { + virtualLazyUpdateChildCount(getControl(), + getChildren(getControl()).length); + } else { + setChildCount(elementOrTreePath, 0); + } + return; + } + Widget[] items = internalFindItems(elementOrTreePath); + for (int i = 0; i < items.length; i++) { + Item item = (Item) items[i]; + if (!hasChildren) { + doSetItemCount(item, 0); + } else { + if (!getExpanded(item)) { + doSetItemCount(item, 1); + Item child = doGetItem(item, 0); + if (child.getData() != null) { + disassociate(child); + } + doClear(item, true); + } + } + } + } + + /** + * Update the widget at index. + * + * @param widget + * @param index + */ + private void virtualLazyUpdateWidget(Widget widget, int index) { + if (contentProviderIsTreeBased) { + TreePath treePath; + if (widget instanceof Item) { + if (widget.getData() == null) { + // temporary fix to avoid a NPE (the tree will still be + // screwed up) + // see bug 167668 + return; + } + treePath = getTreePathFromItem((Item) widget); + } else { + treePath = TreePath.EMPTY; + } + ((ILazyTreePathContentProvider) getContentProvider()) + .updateElement(treePath, index); + } else { + ((ILazyTreeContentProvider) getContentProvider()).updateElement( + widget.getData(), index); + } + } + + /** + * Update the child count + * + * @param widget + * @param currentChildCount + */ + private void virtualLazyUpdateChildCount(Widget widget, + int currentChildCount) { + if (contentProviderIsTreeBased) { + TreePath treePath; + if (widget instanceof Item) { + treePath = getTreePathFromItem((Item) widget); + } else { + treePath = TreePath.EMPTY; + } + ((ILazyTreePathContentProvider) getContentProvider()) + .updateChildCount(treePath, currentChildCount); + } else { + ((ILazyTreeContentProvider) getContentProvider()).updateChildCount( + widget.getData(), currentChildCount); + } + } + + /** + * Update the item with the current child count. + * + * @param item + * @param currentChildCount + */ + private void virtualLazyUpdateHasChildren(Item item, int currentChildCount) { + if (contentProviderIsTreeBased) { + TreePath treePath; + treePath = getTreePathFromItem(item); + if (currentChildCount == 0) { + // item is not expanded (but may have a plus currently) + ((ILazyTreePathContentProvider) getContentProvider()) + .updateHasChildren(treePath); + } else { + ((ILazyTreePathContentProvider) getContentProvider()) + .updateChildCount(treePath, currentChildCount); + } + } else { + ((ILazyTreeContentProvider) getContentProvider()).updateChildCount( + item.getData(), currentChildCount); + } + } + + private boolean internalIsInputOrEmptyPath(final Object elementOrTreePath) { + if (elementOrTreePath.equals(getInput())) + return true; + if (!(elementOrTreePath instanceof TreePath)) + return false; + return ((TreePath) elementOrTreePath).getSegmentCount() == 0; + } + + protected void disassociate(Item item) { + if (contentProviderIsLazy) { + // avoid causing a callback: + item.setText(" "); //$NON-NLS-1$ + } + super.disassociate(item); + } + + // Force subclasses to provide a meaningful implementation + protected abstract Item getItemAt(Point p); + + // Force subclasses to provide a meaningful implementation + protected abstract AbstractViewerEditor createViewerEditor(); + + // Force subclasses to provide a meaningful implementation + protected abstract Item getChild(Widget widget, int index); + + protected final int getItemCount(Control widget) { + return doGetItemCount(); + } + + protected final int getItemCount(Item item) { + return doGetItemCount(item); + } + + /** + * @param parent + * the parent viewer row ornull
if no parent is
+ * known
+ * @param style
+ * the style used to create the row
+ * @param rowIndex
+ * the row index or -1
if the row is append to the
+ * end
+ * @return the new row
+ */
+ protected abstract ViewerRow doCreateNewRowPart(ViewerRow parent,
+ int style, int rowIndex);
+
+ /**
+ * Returns the number of columns contained in the receiver. If no columns
+ * were created by the programmer, this value is zero, despite the fact that
+ * visually, one column of items may be visible. This occurs when the
+ * programmer uses the tree like a list, adding items but never creating a
+ * column.
+ *
+ * @return the number of columns
+ *
+ * @exception SWTException
+ * TreeColumn
s were
+ * created by the programmer, this method will throw
+ * ERROR_INVALID_RANGE
despite the fact that a single column
+ * of data may be visible in the tree. This occurs when the programmer uses
+ * the tree like a list, adding items but never creating a column.
+ *
+ * @param index
+ * the index of the column to return
+ * @return the column at the given index
+ *
+ * @exception IllegalArgumentException
+ * null
when the
+ * receiver is a root.
+ *
+ * @param item
+ * the item the parent is searched for
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException
+ * + * + * @param item + * the item the state is modified + * + * @param expanded + * the new expanded state + * + * @exception SWTException + *
+ * Items that are not in the receiver are ignored. If the receiver is + * single-select and multiple items are specified, then all items are + * ignored. + *
+ * + * @param items + * the list of items + * + * @exception IllegalArgumentException + *SWT.VIRTUAL
style, these
+ * attributes are requested again as needed.
+ * @param item the item whose children should be cleared
+ *
+ * @param all true
if all child items should be cleared
+ * recursively, and false
otherwise
+ *
+ * @exception SWTException SWT.VIRTUAL
style, these
+ * attributes are requested again as needed.
+ *
+ * @param all true
if all child items should be cleared
+ * recursively, and false
otherwise
+ *
+ * @exception SWTException