### 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 this 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. + * 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, or false 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 - concept of ViewerRow, + * refactoring (bug 153993) + *******************************************************************************/ + +package org.eclipse.jface.viewers; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.util.Policy; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.TreeEvent; +import org.eclipse.swt.graphics.Point; +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.Widget; + +/** + * A concrete viewer based on an SWT 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. + *

+ */ +public abstract class VirtualAbstractTreeViewer extends AbstractTreeViewer { + + private static final String VIRTUAL_DISPOSE_KEY = Policy.JFACE + + ".DISPOSE_LISTENER"; //$NON-NLS-1$ + + /** + * Flag for whether the tree has been disposed of. + */ + private boolean treeIsDisposed = false; + + private boolean contentProviderIsLazy; + + private boolean contentProviderIsTreeBased; + + /* + * (non-Javadoc) Method declared in AbstractTreeViewer. + */ + protected void doUpdateItem(final Item item, Object element) { + if (item.isDisposed()) { + unmapElement(element, item); + return; + } + + int columnCount = doGetColumnCount(); + 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(item), column)); + + // As it is possible for user code to run the event + // loop check here. + if (item.isDisposed()) { + unmapElement(element, item); + return; + } + + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.viewers.ColumnViewer#getColumnViewerOwner(int) + */ + protected Widget getColumnViewerOwner(int columnIndex) { + if (columnIndex < 0 + || (columnIndex > 0 && columnIndex >= doGetColumnCount())) { + return null; + } + + if (doGetColumnCount() == 0)// Hang it off the table if it + return getControl(); + + return doGetColumn(columnIndex); + } + + /** + * 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); + } + + /** + * The tree viewer implementation of this 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 or null 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 + * + * + * @since 3.3 + */ + protected abstract int doGetColumnCount(); + + /** + * Returns the column at the given, zero-relative index in the receiver. + * Throws an exception if the index is out of range. Columns are returned in + * the order that they were created. If no TreeColumns 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 + * + * @exception SWTException + * + * + * + * @since 3.3 + */ + protected abstract Widget doGetColumn(int index); + + /** + * TODO Boris please give me hints what's done here + * + * @param item + * @param all + * + * @since 3.3 + */ + protected abstract void doClear(Item item, boolean all); + + /** + * Returns the given item's parent item or null when the + * receiver is a root. + * + * @param item + * the item the parent is searched for + * + * @return the receiver's parent item + * + * @exception SWTException + * + * @since 3.3 + */ + protected abstract Item doGetParentItem(Item item); + + /** + * Searches the parent's item list starting at the first item (index 0) + * until an item is found that is equal to the argument, and returns the + * index of that item. If no item is found, returns -1. + * + * @param parentItem + * the item which is parent of the searched one + * + * @param item + * the search item + * @return the index of the item + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * + * @since 3.3 + */ + protected abstract int doIndexOf(Item parentItem, Item item); + + /** + * Searches the receiver's list starting at the first item (index 0) until + * an item is found that is equal to the argument, and returns the index of + * that item. If no item is found, returns -1. + * + * @param item + * the search item + * @return the index of the item + * + * @exception IllegalArgumentException + * + * @exception SWTException + * + * + * @since 3.3 + */ + protected abstract int doIndexOf(Item item); + + /** + * Sets the expanded state of the given item. + *

+ * + * @param item + * the item the state is modified + * + * @param expanded + * the new expanded state + * + * @exception SWTException + *

+ */ + protected abstract void doSetExpanded(Item item, boolean expanded); + + /** + * Sets the receiver's selection to be the given list of items. The current + * selection is cleared before the new items are selected. + *

+ * 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 + * + * @exception SWTException + * + * + * @since 3.3 + */ + protected abstract void doSetSelection(List items); + + /** + * Sets the number of root-level items contained in the receiver. + * + * @param count + * the number of items + * + * @exception SWTException + * + * + * @since 3.3 + */ + protected abstract void doSetItemCount(int count); + + /** + * Sets the number of child items contained in the given item. + * + * @param item + * the item the count is modified + * + * @param count + * the number of items + * + * @exception SWTException + * + * + * @since 3.3 + */ + protected abstract void doSetItemCount(Item item, int count); + + /** + * Returns the number of items contained in the receiver that are direct + * item children of the receiver. The number that is returned is the number + * of roots in the tree. + * + * @return the number of items + * + * @exception SWTException + * + * @since 3.3 + */ + protected abstract int doGetItemCount(); + + /** + * Returns the number of items contained in the given item that are direct + * item children of the receiver. + * + * @param item + * the item the count is searched for + * + * @return the number of items + * + * @exception SWTException + * + */ + protected abstract int doGetItemCount(Item item); + + /** + * Returns the item at the given, zero-relative index in the + * receiver. Throws an exception if the index is out of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException + * @exception SWTException + * + * @since 3.3 + */ + protected abstract Item doGetItem(int index); + + /** + * Returns the item at the given, zero-relative index in the + * given item. Throws an exception if the index is out of range. + * @param item the parent item to search in + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException + * @exception SWTException + * + * @since 3.3 + */ + protected abstract Item doGetItem(Item item, int index); + + /** + * Clears all the items in the given item. The text, icon and other + * attributes of the items are set to their default values. If the + * tree was created with the 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 + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.3 + */ + protected abstract void doClearAll(Item item, boolean all); + + /** + * Clears all the items in the tree. The text, icon and other + * attributes of the items are set to their default values. If the + * tree was created with the 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 + * + * @see SWT#VIRTUAL + * @see SWT#SetData + * + * @since 3.3 + */ + protected abstract void doClearAll(boolean all); + +}