Java tutorial
/******************************************************************************* * Copyright (c) 2008 BestSolution.at Systemhaus GmbH * 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: * tom.schindl@bestsolution - initial API and implementation ******************************************************************************/ package org.mingy.jsfs.ui.viewer; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.eclipse.jface.util.Policy; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ColumnViewerEditor; import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ILazyTreeContentProvider; import org.eclipse.jface.viewers.ILazyTreePathContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.TreeExpansionEvent; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewerRow; import org.eclipse.swt.SWT; 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.Widget; import org.mingy.jsfs.ui.widget.CTreeCombo; import org.mingy.jsfs.ui.widget.CTreeComboItem; public class CTreeComboViewer extends AbstractTreeViewer { private static final String VIRTUAL_DISPOSE_KEY = Policy.JFACE + ".DISPOSE_LISTENER"; //$NON-NLS-1$ /** * This viewer's control. */ private CTreeCombo tree; /** * Flag for whether the tree has been disposed of. */ private boolean treeIsDisposed = false; private boolean contentProviderIsLazy; private boolean contentProviderIsTreeBased; /** * The row object reused */ private CTreeComboViewerRow cachedRow; /** * true if we are inside a preservingSelection() call */ private boolean preservingSelection; /** * Creates a tree viewer on a newly-created tree control under the given * parent. The tree control is created using the SWT style bits * <code>MULTI, H_SCROLL, V_SCROLL,</code> and <code>BORDER</code>. The * viewer has no input, no content provider, a default label provider, no * sorter, and no filters. * * @param parent * the parent control */ public CTreeComboViewer(Composite parent) { this(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); } /** * Creates a tree viewer on a newly-created tree control under the given * parent. The tree control is created using the given SWT style bits. The * viewer has no input, no content provider, a default label provider, no * sorter, and no filters. * * @param parent * the parent control * @param style * the SWT style bits used to create the tree. */ public CTreeComboViewer(Composite parent, int style) { this(new CTreeCombo(parent, style)); } /** * Creates a tree viewer on the given tree control. The viewer has no input, * no content provider, a default label provider, no sorter, and no filters. * * @param tree * the tree control */ public CTreeComboViewer(CTreeCombo tree) { super(); this.tree = tree; hookControl(tree); } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected void addTreeListener(Control c, TreeListener listener) { ((CTreeCombo) c).addTreeListener(listener); } /* * (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); } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected Item[] getChildren(Widget o) { if (o instanceof CTreeComboItem) { return ((CTreeComboItem) o).getItems(); } if (o instanceof CTreeCombo) { return ((CTreeCombo) o).getItems(); } 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 ((CTreeComboItem) item).getExpanded(); } /* * (non-Javadoc) * * @see * org.eclipse.jface.viewers.ColumnViewer#getItemAt(org.eclipse.swt.graphics * .Point) */ protected Item getItemAt(Point p) { CTreeComboItem[] selection = tree.getSelection(); if (selection.length == 1) { int columnCount = tree.getColumnCount(); for (int i = 0; i < columnCount; i++) { if (selection[0].getBounds(i).contains(p)) { return selection[0]; } } } return getTree().getItem(p); } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected int getItemCount(Control widget) { return ((CTreeCombo) widget).getItemCount(); } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected int getItemCount(Item item) { return ((CTreeComboItem) item).getItemCount(); } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected Item[] getItems(Item item) { return ((CTreeComboItem) item).getItems(); } /** * The tree viewer implementation of this <code>Viewer</code> framework * method ensures that the given label provider is an instance of either * <code>ITableLabelProvider</code> or <code>ILabelProvider</code>. If it is * an <code>ITableLabelProvider</code>, then it provides a separate label * text and image for each column. If it is an <code>ILabelProvider</code>, * 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) Method declared in AbstractTreeViewer. */ protected Item getParentItem(Item item) { return ((CTreeComboItem) item).getParentItem(); } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected Item[] getSelection(Control widget) { return ((CTreeCombo) widget).getSelection(); } /** * Returns this tree viewer's tree control. * * @return the tree control */ public CTreeCombo getTree() { return tree; } /* * (non-Javadoc) * * @see * org.eclipse.jface.viewers.AbstractTreeViewer#hookControl(org.eclipse. * swt.widgets.Control) */ protected void hookControl(Control control) { super.hookControl(control); CTreeCombo treeControl = (CTreeCombo) 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) { CTreeComboItem item = (CTreeComboItem) event.item; CTreeComboItem parentItem = item.getParentItem(); int index = event.index; virtualLazyUpdateWidget(parentItem == null ? (Widget) getTree() : parentItem, index); } } }); } } protected ColumnViewerEditor createViewerEditor() { return /*new TreeViewerEditor(this, null, new ColumnViewerEditorActivationStrategy(this), ColumnViewerEditor.DEFAULT)*/null; } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected Item newItem(Widget parent, int flags, int ix) { CTreeComboItem item; if (parent instanceof CTreeComboItem) { item = (CTreeComboItem) createNewRowPart(getViewerRowFromItem(parent), flags, ix).getItem(); } else { item = (CTreeComboItem) createNewRowPart(null, flags, ix).getItem(); } return item; } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected void removeAll(Control widget) { ((CTreeCombo) widget).removeAll(); } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected void setExpanded(Item node, boolean expand) { ((CTreeComboItem) node).setExpanded(expand); if (contentProviderIsLazy) { // force repaints to happen getControl().update(); } } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ @SuppressWarnings({ "unchecked", "rawtypes" }) protected void setSelection(List items) { Item[] current = getSelection(getTree()); // Don't bother resetting the same selection if (isSameSelection(items, current)) { return; } CTreeComboItem[] newItems = new CTreeComboItem[items.size()]; items.toArray(newItems); getTree().setSelection(newItems); } /* * (non-Javadoc) Method declared in AbstractTreeViewer. */ protected void showItem(Item item) { getTree().showItem((CTreeComboItem) 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 CTreeComboItem) { return ((CTreeComboItem) widget).getItem(index); } if (widget instanceof CTreeCombo) { return ((CTreeCombo) widget).getItem(index); } return null; } 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); } // void preservingSelection(Runnable updateCode, boolean reveal) { // if (preservingSelection) { // // avoid preserving the selection if called reentrantly, // // see bug 172640 // updateCode.run(); // return; // } // preservingSelection = true; // try { // super.preservingSelection(updateCode, reveal); // } finally { // preservingSelection = false; // } // } /** * 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) { if (checkBusy()) return; 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++) { CTreeComboItem treeItem = (CTreeComboItem) items[i]; treeItem.setItemCount(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. * <p> * This method should be called by implementers of ILazyTreeContentProvider * to populate this viewer. * </p> * * @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) { if (checkBusy()) return; Item[] selectedItems = getSelection(getControl()); TreeSelection selection = (TreeSelection) getSelection(); Widget[] itemsToDisassociate; if (parentElementOrTreePath instanceof TreePath) { TreePath elementPath = ((TreePath) parentElementOrTreePath).createChildPath(element); itemsToDisassociate = internalFindItems(elementPath); } else { itemsToDisassociate = internalFindItems(element); } if (internalIsInputOrEmptyPath(parentElementOrTreePath)) { if (index < tree.getItemCount()) { CTreeComboItem item = tree.getItem(index); selection = adjustSelectionForReplace(selectedItems, selection, item, element, getRoot()); // disassociate any different item that represents the // same element under the same parent (the tree) for (int i = 0; i < itemsToDisassociate.length; i++) { if (itemsToDisassociate[i] instanceof CTreeComboItem) { CTreeComboItem itemToDisassociate = (CTreeComboItem) itemsToDisassociate[i]; if (itemToDisassociate != item && itemToDisassociate.getParentItem() == null) { int indexToDisassociate = getTree().indexOf(itemToDisassociate); disassociate(itemToDisassociate); getTree().clear(indexToDisassociate, true); } } } Object oldData = item.getData(); updateItem(item, element); if (!CTreeComboViewer.this.equals(oldData, element)) { item.clearAll(true); } } } else { Widget[] parentItems = internalFindItems(parentElementOrTreePath); for (int i = 0; i < parentItems.length; i++) { CTreeComboItem parentItem = (CTreeComboItem) parentItems[i]; if (index < parentItem.getItemCount()) { CTreeComboItem item = parentItem.getItem(index); selection = adjustSelectionForReplace(selectedItems, selection, item, element, parentItem.getData()); // disassociate any different item that represents the // same element under the same parent (the tree) for (int j = 0; j < itemsToDisassociate.length; j++) { if (itemsToDisassociate[j] instanceof CTreeComboItem) { CTreeComboItem itemToDisassociate = (CTreeComboItem) itemsToDisassociate[j]; if (itemToDisassociate != item && itemToDisassociate.getParentItem() == parentItem) { int indexToDisaccociate = parentItem.indexOf(itemToDisassociate); disassociate(itemToDisassociate); parentItem.clear(indexToDisaccociate, true); } } } Object oldData = item.getData(); updateItem(item, element); if (!CTreeComboViewer.this.equals(oldData, element)) { item.clearAll(true); } } } } // Restore the selection if we are not already in a nested // preservingSelection: if (!preservingSelection) { setSelectionToWidget(selection, false); // send out notification if old and new differ ISelection newSelection = getSelection(); if (!newSelection.equals(selection)) { handleInvalidSelection(selection, newSelection); } } } /** * Fix for bug 185673: If the currently replaced item was selected, add it * to the selection that is being restored. Only do this if its getData() is * currently null * * @param selectedItems * @param selection * @param item * @param element * @return */ private TreeSelection adjustSelectionForReplace(Item[] selectedItems, TreeSelection selection, CTreeComboItem item, Object element, Object parentElement) { if (item.getData() != null || selectedItems.length == selection.size() || parentElement == null) { // Don't do anything - we are not seeing an instance of bug 185673 return selection; } for (int i = 0; i < selectedItems.length; i++) { if (item == selectedItems[i]) { // The current item was selected, but its data is null. // The data will be replaced by the given element, so to keep // it selected, we have to add it to the selection. TreePath[] originalPaths = selection.getPaths(); int length = originalPaths.length; TreePath[] paths = new TreePath[length + 1]; System.arraycopy(originalPaths, 0, paths, 0, length); // set the element temporarily so that we can call // getTreePathFromItem item.setData(element); paths[length] = getTreePathFromItem(item); item.setData(null); return new TreeSelection(paths, selection.getElementComparer()); } } // The item was not selected, return the given selection return selection; } public boolean isExpandable(Object element) { if (contentProviderIsLazy) { CTreeComboItem treeItem = (CTreeComboItem) internalExpand(element, false); if (treeItem == null) { return false; } virtualMaterializeItem(treeItem); return treeItem.getItemCount() > 0; } return super.isExpandable(element); } protected Object getParentElement(Object element) { boolean oldBusy = isBusy(); setBusy(true); try { 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); } finally { setBusy(oldBusy); } } protected void createChildren(Widget widget) { if (contentProviderIsLazy) { Object element = widget.getData(); if (element == null && widget instanceof CTreeComboItem) { // parent has not been materialized virtualMaterializeItem((CTreeComboItem) 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 CTreeComboItem) { CTreeComboItem ti = (CTreeComboItem) widget; int count = ti.getItemCount() + childElements.length; ti.setItemCount(count); ti.clearAll(false); } else { CTreeCombo t = (CTreeCombo) widget; t.setItemCount(t.getItemCount() + childElements.length); t.clearAll(false); } return; } super.internalAdd(widget, parentElement, childElements); } private void virtualMaterializeItem(CTreeComboItem 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 CTreeCombo) { index = ((CTreeCombo) parent).indexOf(treeItem); } else { index = ((CTreeComboItem) parent).indexOf(treeItem); } virtualLazyUpdateWidget(parent, index); } } /* * 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) { if (cachedRow == null) { cachedRow = new CTreeComboViewerRow((CTreeComboItem) item); } else { cachedRow.setItem((CTreeComboItem) item); } return cachedRow; } /** * Create a new ViewerRow at rowIndex * * @param parent * @param style * @param rowIndex * @return ViewerRow */ private ViewerRow createNewRowPart(ViewerRow parent, int style, int rowIndex) { if (parent == null) { if (rowIndex >= 0) { return getViewerRowFromItem(new CTreeComboItem(tree, style, rowIndex)); } return getViewerRowFromItem(new CTreeComboItem(tree, style)); } if (rowIndex >= 0) { return getViewerRowFromItem(new CTreeComboItem((CTreeComboItem) parent.getItem(), SWT.NONE, rowIndex)); } return getViewerRowFromItem(new CTreeComboItem((CTreeComboItem) parent.getItem(), 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 CTreeCombo && 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 = ((CTreeComboItem) 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 */ @SuppressWarnings({ "unchecked", "rawtypes" }) public void remove(final Object parentOrTreePath, final int index) { if (checkBusy()) return; final List oldSelection = new LinkedList(Arrays.asList(((TreeSelection) getSelection()).getPaths())); preservingSelection(new Runnable() { public void run() { TreePath removedPath = null; if (internalIsInputOrEmptyPath(parentOrTreePath)) { CTreeCombo tree = (CTreeCombo) getControl(); if (index < tree.getItemCount()) { CTreeComboItem item = tree.getItem(index); if (item.getData() != null) { removedPath = getTreePathFromItem(item); disassociate(item); } item.dispose(); } } else { Widget[] parentItems = internalFindItems(parentOrTreePath); for (int i = 0; i < parentItems.length; i++) { CTreeComboItem parentItem = (CTreeComboItem) parentItems[i]; if (parentItem.isDisposed()) continue; if (index < parentItem.getItemCount()) { CTreeComboItem item = parentItem.getItem(index); if (item.getData() != null) { removedPath = getTreePathFromItem(item); disassociate(item); } item.dispose(); } } } if (removedPath != null) { boolean removed = false; for (Iterator it = oldSelection.iterator(); it.hasNext();) { TreePath path = (TreePath) it.next(); if (path.startsWith(removedPath, getComparer())) { it.remove(); removed = true; } } if (removed) { setSelection(new TreeSelection( (TreePath[]) oldSelection.toArray(new TreePath[oldSelection.size()]), getComparer()), false); } } } }); } /* * (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(final Object elementOrTreePath, final boolean hasChildren) { if (checkBusy()) return; preservingSelection(new Runnable() { public void run() { 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++) { CTreeComboItem item = (CTreeComboItem) items[i]; if (!hasChildren) { item.setItemCount(0); } else { if (!item.getExpanded()) { item.setItemCount(1); CTreeComboItem child = item.getItem(0); if (child.getData() != null) { disassociate(child); } item.clear(0, true); } else { virtualLazyUpdateChildCount(item, item.getItemCount()); } } } } }); } /** * Update the widget at index. * * @param widget * @param index */ private void virtualLazyUpdateWidget(Widget widget, int index) { boolean oldBusy = isBusy(); setBusy(false); try { if (contentProviderIsTreeBased) { TreePath treePath; if (widget instanceof Item) { if (widget.getData() == null) { // we need to materialize the parent first // see bug 167668 // however, that would be too risky // see bug 182782 and bug 182598 // so we just ignore this call altogether // and don't do this: virtualMaterializeItem((TreeItem) // widget); return; } treePath = getTreePathFromItem((Item) widget); } else { treePath = TreePath.EMPTY; } ((ILazyTreePathContentProvider) getContentProvider()).updateElement(treePath, index); } else { ((ILazyTreeContentProvider) getContentProvider()).updateElement(widget.getData(), index); } } finally { setBusy(oldBusy); } } /** * Update the child count * * @param widget * @param currentChildCount */ private void virtualLazyUpdateChildCount(Widget widget, int currentChildCount) { boolean oldBusy = isBusy(); setBusy(false); try { 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); } } finally { setBusy(oldBusy); } } /** * Update the item with the current child count. * * @param item * @param currentChildCount */ private void virtualLazyUpdateHasChildren(Item item, int currentChildCount) { boolean oldBusy = isBusy(); setBusy(false); try { 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); } } finally { setBusy(oldBusy); } } protected void disassociate(Item item) { if (contentProviderIsLazy) { // avoid causing a callback: item.setText(" "); //$NON-NLS-1$ } super.disassociate(item); } protected int doGetColumnCount() { return tree.getColumnCount(); } /** * Sets a new selection for this viewer and optionally makes it visible. * <p> * <b>Currently the <code>reveal</code> parameter is not honored because * {@link Tree} does not provide an API to only select an item without * scrolling it into view</b> * </p> * * @param selection * the new selection * @param reveal * <code>true</code> if the selection is to be made visible, and * <code>false</code> otherwise */ public void setSelection(ISelection selection, boolean reveal) { super.setSelection(selection, reveal); } public void editElement(Object element, int column) { if (element instanceof TreePath) { try { getControl().setRedraw(false); setSelection(new TreeSelection((TreePath) element)); CTreeComboItem[] items = tree.getSelection(); if (items.length == 1) { ViewerRow row = getViewerRowFromItem(items[0]); if (row != null) { ViewerCell cell = row.getCell(column); if (cell != null) { triggerEditorActivationEvent(new ColumnViewerEditorActivationEvent(cell)); } } } } finally { getControl().setRedraw(true); } } else { super.editElement(element, column); } } }