gt: 			Item[] children = getChildren(widget);
context: /*******************************************************************************
   * Copyright (c) 2004, 2014 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 <tom.schindl@bestsolution.at> - concept of ViewerRow,
   *                                                 refactoring (bug 153993), bug 167323, 191468, 205419
   *     Matthew Hall - bug 221988
   *     Pawel Piech, WindRiver - bug 296573
   *     Lars Vogel <Lars.Vogel@gmail.com> - Bug 430873
   *******************************************************************************/
  
  package org.eclipse.jface.viewers;
  
  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.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.Tree;
  import org.eclipse.swt.widgets.TreeItem;
  import org.eclipse.swt.widgets.Widget;
  
  /**
   * A concrete viewer based on an SWT <code>Tree</code> control.
   * <p>
   * 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).
   * </p>
   * <p>
   * As of 3.2, TreeViewer supports multiple equal elements (each with a
   * different parent chain) in the tree. This support requires that clients
   * enable the element map by calling <code>setUseHashLookup(true)</code>.
   * </p>
   * <p>
   * 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
   * <code>ILazyTreeContentProvider</code> or an
   * <code>ILazyTreePathContentProvider</code>, the underlying Tree must be
   * created using the {@link SWT#VIRTUAL} style bit, the tree viewer will not
   * support sorting or filtering, and hash lookup must be enabled by calling
   * {@link #setUseHashlookup(boolean)}.
   * </p>
   * <p>
   * Users setting up an editable tree with more than 1 column <b>have</b> to pass the
   * SWT.FULL_SELECTION style bit
   * </p>
   * @noextend This class is not intended to be subclassed by clients.
   */
  public class TreeViewer extends AbstractTreeViewer {
  
  	private static final String VIRTUAL_DISPOSE_KEY = Policy.JFACE
  			+ ".DISPOSE_LISTENER"; //$NON-NLS-1$
  
  	/**
  	 * This viewer's control.
  	 */
  	private Tree 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 TreeViewerRow cachedRow;
  
  	/**
  	 * true if we are inside a preservingSelection() call
  	 */
  	private boolean insidePreservingSelection;
  
  	/**
  	 * 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 TreeViewer(Composite parent) {
  		this(parent, SWT.MULTI | 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 TreeViewer(Composite parent, int style) {
  		this(new Tree(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 TreeViewer(Tree tree) {
  		super();
  		this.tree = tree;
  		hookControl(tree);
  	}
  
  	@Override
  	protected void addTreeListener(Control c, TreeListener listener) {
  		((Tree) c).addTreeListener(listener);
  	}
  
  	@Override
  	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);
  	}
  
  	@Override
  	protected Item[] getChildren(Widget o) {
  		if (o instanceof TreeItem) {
  			return ((TreeItem) o).getItems();
  		}
  		if (o instanceof Tree) {
  			return ((Tree) o).getItems();
  		}
  		return null;
  	}
  
  	@Override
  	public Control getControl() {
  		return tree;
  	}
  
  	@Override
  	protected boolean getExpanded(Item item) {
  		return ((TreeItem) item).getExpanded();
  	}
  
  	@Override
  	protected Item getItemAt(Point p) {
  		TreeItem[] 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);
  	}
  
  	@Override
  	protected int getItemCount(Control widget) {
  		return ((Tree) widget).getItemCount();
  	}
  
  	@Override
  	protected int getItemCount(Item item) {
  		return ((TreeItem) item).getItemCount();
  	}
  
  	@Override
  	protected Item[] getItems(Item item) {
  		return ((TreeItem) 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.
  	 */
  	@Override
  	public IBaseLabelProvider getLabelProvider() {
  		return super.getLabelProvider();
  	}
  
  	@Override
  	protected Item getParentItem(Item item) {
  		return ((TreeItem) item).getParentItem();
  	}
  
  	@Override
  	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;
  	}
  
  	@Override
  	protected void hookControl(Control control) {
  		super.hookControl(control);
  		Tree treeControl = (Tree) control;
  
  		if ((treeControl.getStyle() & SWT.VIRTUAL) != 0) {
  			treeControl.addDisposeListener(new DisposeListener() {
  				@Override
  				public void widgetDisposed(DisposeEvent e) {
  					treeIsDisposed = true;
  					unmapAllElements();
  				}
  			});
  			treeControl.addListener(SWT.SetData, new Listener() {
  
  				@Override
  				public void handleEvent(Event event) {
  					if (contentProviderIsLazy) {
  						TreeItem item = (TreeItem) event.item;
  						TreeItem parentItem = item.getParentItem();
  						int index = event.index;
  						virtualLazyUpdateWidget(
  								parentItem == null ? (Widget) getTree()
  										: parentItem, index);
  					}
  				}
  
  			});
  		}
  	}
  
  	@Override
  	protected ColumnViewerEditor createViewerEditor() {
  		return new TreeViewerEditor(this,null,new ColumnViewerEditorActivationStrategy(this),ColumnViewerEditor.DEFAULT);
  	}
  
  	@Override
  	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;
  	}
  
  	@Override
  	protected void removeAll(Control widget) {
  		((Tree) widget).removeAll();
  	}
  
  	@Override
  	protected void setExpanded(Item node, boolean expand) {
  		((TreeItem) node).setExpanded(expand);
  		if (contentProviderIsLazy) {
  			// force repaints to happen
  			getControl().update();
  		}
  	}
  
  	@Override
  	protected void setSelection(List items) {
  
  		Item[] current = getSelection(getTree());
  
  		// Don't bother resetting the same selection
  		if (isSameSelection(items, current)) {
  			return;
  		}
  
  		TreeItem[] newItems = new TreeItem[items.size()];
  		items.toArray(newItems);
  		getTree().setSelection(newItems);
  	}
  
  	@Override
  	protected void showItem(Item item) {
  		getTree().showItem((TreeItem) item);
  	}
  
  	@Override
  	protected Item getChild(Widget widget, int index) {
  		if (widget instanceof TreeItem) {
  			return ((TreeItem) widget).getItem(index);
  		}
  		if (widget instanceof Tree) {
  			return ((Tree) widget).getItem(index);
  		}
  		return null;
  	}
  
  	@Override
  	protected void assertContentProviderType(IContentProvider provider) {
  		if (provider instanceof ILazyTreeContentProvider
  				|| provider instanceof ILazyTreePathContentProvider) {
  			return;
  		}
  		super.assertContentProviderType(provider);
  	}
  
  	@Override
  	protected Object[] getRawChildren(Object parent) {
  		if (contentProviderIsLazy) {
  			return new Object[0];
  		}
  		return super.getRawChildren(parent);
  	}
  
  	@Override
  	void preservingSelection(Runnable updateCode, boolean reveal) {
  		if (insidePreservingSelection || !getPreserveSelection()){
  			// avoid preserving the selection if called reentrantly,
  			// see bug 172640
  			updateCode.run();
  			return;
  		}
  		insidePreservingSelection = true;
  		try {
  			super.preservingSelection(updateCode, reveal);
  		} finally {
  			insidePreservingSelection = 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() {
  			@Override
  			public void run() {
  				if (internalIsInputOrEmptyPath(elementOrTreePath)) {
  					getTree().setItemCount(count);
  					return;
  				}
  				Widget[] items = internalFindItems(elementOrTreePath);
  				for (Widget item : items) {
  					TreeItem treeItem = (TreeItem) item;
  					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()) {
  				TreeItem 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 (Widget widget : itemsToDisassociate) {
  					if (widget instanceof TreeItem) {
  						TreeItem itemToDisassociate = (TreeItem) widget;
  						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 (!TreeViewer.this.equals(oldData, element)) {
  					item.clearAll(true);
  				}
  			}
  		} else {
  			Widget[] parentItems = internalFindItems(parentElementOrTreePath);
  			for (Widget widget : parentItems) {
  				TreeItem parentItem = (TreeItem) widget;
  				if (index < parentItem.getItemCount()) {
  					TreeItem 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 (Widget widgetToDisassociate : itemsToDisassociate) {
  						if (widgetToDisassociate instanceof TreeItem) {
  							TreeItem itemToDisassociate = (TreeItem) widgetToDisassociate;
  							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 (!TreeViewer.this.equals(oldData, element)) {
  						item.clearAll(true);
  					}
  				}
  			}
  		}
  		// Restore the selection if we are not already in a nested preservingSelection:
  		if (!insidePreservingSelection) {
  			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 the adjusted selection
  	 */
  	private TreeSelection adjustSelectionForReplace(Item[] selectedItems,
  			TreeSelection selection, TreeItem 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 (Item selectedItem : selectedItems) {
  			if (item == selectedItem) {
  				// 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;
  	}
  
  	@Override
  	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);
  	}
  
  	@Override
  	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);
  		}
  	}
  
  	@Override
  	void createChildren(Widget widget, boolean materialize) {
  		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;
  			}
  