/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.jface.viewers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TreeEvent;
import org.eclipse.swt.events.TreeListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Widget;

/**
 * Abstract base implementation for tree-structure-oriented viewers (trees and
 * table trees).
 * <p>
 * Nodes in the tree can be in either an expanded or a collapsed state,
 * depending on whether the children on a node are visible. This class
 * introduces public methods for controlling the expanding and collapsing of
 * nodes.
 * </p>
 * <p>
 * Content providers for abstract tree viewers must implement the <code>ITreeContentProvider</code>
 * interface.
 * </p>
 * 
 * @see TreeViewer
 * @see TableTreeViewer
 */
public abstract class AbstractTreeViewer extends StructuredViewer {

    /**
     * Constant indicating that all levels of the tree should be expanded or
     * collapsed.
     * 
     * @see #expandToLevel
     * @see #collapseToLevel
     */
    public static final int ALL_LEVELS = -1;

    /**
     * List of registered tree listeners (element type: <code>TreeListener</code>). */
    private ListenerList treeListeners = new ListenerList();

    /**
     * The level to which the tree is automatically expanded each time the
     * viewer's input is changed (that is, by <code>setInput</code>). A
     * value of 0 means that auto-expand is off.
     * 
     * @see #setAutoExpandLevel
     */
    private int expandToLevel = 0;

    /**
     * Safe runnable used to update an item.
     */
    class UpdateItemSafeRunnable extends SafeRunnable {
        private Object element;

        private Item item;

        UpdateItemSafeRunnable(Item item, Object element) {
            this.item = item;
            this.element = element;
        }

        public void run() {
            doUpdateItem(item, element);
        }
        
    }

    /**
     * Creates an abstract tree viewer. The viewer has no input, no content
     * provider, a default label provider, no sorter, no filters, and has
     * auto-expand turned off.
     */
    protected AbstractTreeViewer() {
        // do nothing
    }

    /**
     * Adds the given child elements to this viewer as children of the given
     * parent element. If this viewer does not have a sorter, the elements are
     * added at the end of the parent's list of children in the order given;
     * otherwise, the elements are inserted at the appropriate positions.
     * <p>
     * This method should be called (by the content provider) when elements
     * have been added to the model, in order to cause the viewer to accurately
     * reflect the model. This method only affects the viewer, not the model.
     * </p>
     * 
     * @param parentElement
     *           the parent element
     * @param childElements
     *           the child elements to add
     */
    public void add(Object parentElement, Object[] childElements) {
        Assert.isNotNull(parentElement);
        assertElementsNotNull(childElements);

        Widget[] widgets = findItems(parentElement);
        // If parent hasn't been realized yet, just ignore the add.
        if (widgets.length == 0)
            return;

		for (int i = 0; i < widgets.length; i++) {
			internalAdd(widgets[i], parentElement, childElements);
		}        
    }

	/**
     * Adds the given child elements to this viewer as children of the given
     * parent element.
     * <p>
     * EXPERIMENTAL.  Not to be used except by JDT.
     * This method was added to support JDT's explorations
     * into grouping by working sets, which requires viewers to support multiple 
     * equal elements.  See bug 76482 for more details.  This support will
     * likely be removed in Eclipse 3.2 in favour of proper support for
     * multiple equal elements. 
     * </p>
     *
     * @param widget 
     *           the widget for the parent element
     * @param parentElement
     *           the parent element
     * @param childElements
     *           the child elements to add
     * @since 3.1
     */
    protected void internalAdd(Widget widget, Object parentElement, Object[] childElements) {
		
		// optimization!
        // if the widget is not expanded we just invalidate the subtree
        if (widget instanceof Item) {
            Item ti = (Item) widget;
            if (!getExpanded(ti)) {
                boolean needDummy = isExpandable(parentElement);
                boolean haveDummy = false;
                // remove all children
                Item[] items = getItems(ti);
                for (int i = 0; i < items.length; i++) {
                    if (items[i].getData() != null) {
                        disassociate(items[i]);
                        items[i].dispose();
                    } else {
                        if (needDummy && !haveDummy) {
                            haveDummy = true;
                        } else {
                            items[i].dispose();
                        }
                    }
                }
                // append a dummy if necessary
                if (needDummy && !haveDummy) 
                    newItem(ti, SWT.NULL, -1);
                return;
            }
        }

        if (childElements.length > 0) {
            Object[] filtered = filter(childElements);
			if(getSorter() != null)
				getSorter().sort(this,filtered);
            createAddedElements(widget, filtered);
        }
	}

	/**
     * Create the new elements in the parent widget. If the
     * child already exists do nothing.
     * @param widget
     * @param elements Sorted list of elements to add.
     */
    private void createAddedElements(Widget widget, Object[] elements) {

		if(elements.length == 1){
			if (equals(elements[0], widget.getData()))
				return;
		}
		
		ViewerSorter sorter = getSorter ();
		Item[] items = getChildren(widget);
		
		//As the items are sorted already we optimize for a 
		//start position
		int lastInsertion = 0;		
		
		//Optimize for the empty case
		if(items.length == 0){
			for (int i = 0; i < elements.length; i++) {
				createTreeItem(widget, elements[i], -1);		
			}
			return;
		}
	
		for (int i = 0; i < elements.length; i++) {
			boolean newItem = true;
			Object element = elements[i];
			int index;
			if(sorter == null){
				if(itemExists(items,element)){
					refresh(element);
					newItem = false;
				}
				index = -1;
			}
			else{
				lastInsertion = insertionPosition(items,sorter,lastInsertion, element);
				//As we are only searching the original array we keep track of those positions only
				if(lastInsertion == items.length)
					index = -1;
				else{//See if we should just refresh
					while(lastInsertion < items.length && sorter.compare(this,element,items[lastInsertion].getData()) == 0){
						//As we cannot assume the sorter is consistent with equals() - therefore we can
						// just check against the item prior to this index (if any)
						if (items[lastInsertion].getData().equals(element)) {
							//refresh the element in case it has new children
							refresh(element);
							newItem = false;
						}
						lastInsertion ++;//We had an insertion so increment
					}
					//Did we get to the end?
					if(lastInsertion == items.length)
						index = -1;
					else
						index = lastInsertion + i; //Add the index as the array is growing					
				}
			}
			if(newItem)
				createTreeItem(widget, element, index);		
		}
    }
	

    /**
     * See if element is the data of one of the elements in 
     * items.
     * @param items
     * @param element
     * @return <code>true</code> if the element matches.
     */
	private boolean itemExists(Item[] items, Object element) {
		if(usingElementMap())//if we can do a constant time lookup find it
			return findItem(element) != null;
		for (int i = 0; i < items.length; i++) {
			if(items[i].getData().equals(element))
				return true;
		}
		return false;
	}

	/**
     * Returns the index where the item should be inserted. It uses sorter to
     * determine the correct position, if sorter is not assigned, returns the
     * index of the element after the last.
     * 
     * @param items the items to search
     * @param sorter The sorter to use.
     * @param lastInsertion
     *            the start index to start search for position from this allows
     *            optimising search for multiple elements that are sorted
     *            themself.
     * @param element
     *            element to find position for.
     * @return the index to use when inserting the element.
     * 
     */
	
	private int insertionPosition(Item[] items,  ViewerSorter sorter, int lastInsertion, Object element) {
	    
		int size = items.length;
		if (sorter == null)
			return size;
	    int min = lastInsertion, max = size - 1;

		while (min <= max) {
            int mid = (min + max) / 2;
            Object data = items[mid].getData();
            int compare = sorter.compare(this, data, element);
            if (compare == 0) {
                return mid;//Return if we already match
            }
            if (compare < 0)
                min = mid + 1;
            else
                max = mid - 1;
	        }
	   return min;
	    
			
	}

	/**
     * Returns the index where the item should be inserted. It uses sorter to
     * determine the correct position, if sorter is not assigned, returns the
     * index of the element after the last.
     * 
     * @param parent The parent widget
     * @param sorter The sorter to use.
     * @param startIndex
     *            the start index to start search for position from this allows
     *            optimising search for multiple elements that are sorted
     *            themself.
     * @param element
     *            element to find position for.
     * @param currentSize
     * 			the current size of the collection
     * @return the index to use when inserting the element.
     * 
     */
	
    /**
     * Returns the index where the item should be inserted.
     * 
     * @param parent
     *           The parent widget the element will be inserted into.
     * @param element
     *           The element to insert.
     * @return int
     */
    protected int indexForElement(Widget parent, Object element) {
        ViewerSorter sorter = getSorter();
		
		
		Item[] items = getChildren(parent);
		int count = items.length;

        if (sorter == null)
            return count;
        int min = 0, max = count - 1;

        while (min <= max) {
            int mid = (min + max) / 2;
            Object data = items[mid].getData();
            int compare = sorter.compare(this, data, element);
            if (compare == 0) {
                // find first item > element
                while (compare == 0) {
                    ++mid;
                    if (mid >= count) {
                        break;
                    }
                    data = items[mid].getData();
                    compare = sorter.compare(this, data, element);
                }
                return mid;
            }
            if (compare < 0)
                min = mid + 1;
            else
                max = mid - 1;
        }
        return min;
    }

    /**
     * Adds the given child element to this viewer as a child of the given
     * parent element. If this viewer does not have a sorter, the element is
     * added at the end of the parent's list of children; otherwise, the
     * element is inserted at the appropriate position.
     * <p>
     * This method should be called (by the content provider) when a single
     * element has been added to the model, in order to cause the viewer to
     * accurately reflect the model. This method only affects the viewer, not
     * the model. Note that there is another method for efficiently processing
     * the simultaneous addition of multiple elements.
     * </p>
     * 
     * @param parentElement
     *           the parent element
     * @param childElement
     *           the child element
     */
    public void add(Object parentElement, Object childElement) {
        add(parentElement, new Object[] { childElement });
    }

    /**
     * Adds the given SWT selection listener to the given SWT control.
     * 
     * @param control
     *           the SWT control
     * @param listener
     *           the SWT selection listener
     * @deprecated
     */
    protected void addSelectionListener(Control control,
            SelectionListener listener) {
        // do nothing
    }

    /**
     * Adds a listener for expand and collapse events in this viewer. Has no
     * effect if an identical listener is already registered.
     * 
     * @param listener
     *           a tree viewer listener
     */
    public void addTreeListener(ITreeViewerListener listener) {
        treeListeners.add(listener);
    }

    /**
     * Adds the given SWT tree listener to the given SWT control.
     * 
     * @param control
     *           the SWT control
     * @param listener
     *           the SWT tree listener
     */
    protected abstract void addTreeListener(Control control,
            TreeListener listener);

    /* (non-Javadoc) @see StructuredViewer#associate(Object, Item) */
    protected void associate(Object element, Item item) {
        Object data = item.getData();
        if (data != null && data != element && equals(data, element)) {
            // workaround for PR 1FV62BT
            // assumption: elements are equal but not identical
            // -> remove from map but don't touch children
            unmapElement(data, item);
            item.setData(element);
            mapElement(element, item);
        } else {
            // recursively disassociate all
            super.associate(element, item);
        }
    }

    /**
     * Collapses all nodes of the viewer's tree, starting with the root. This
     * method is equivalent to <code>collapseToLevel(ALL_LEVELS)</code>.
     */
    public void collapseAll() {
        Object root = getRoot();
        if (root != null) {
            collapseToLevel(root, ALL_LEVELS);
        }
    }

    /**
     * Collapses the subtree rooted at the given element or tree path to the given level.
     * 
     * @param elementOrTreePath
     *           the element or tree path
     * @param level
     *           non-negative level, or <code>ALL_LEVELS</code> to collapse
     *           all levels of the tree
     */
    public void collapseToLevel(Object elementOrTreePath, int level) {
        Assert.isNotNull(elementOrTreePath);
        Widget w = internalGetWidgetToSelect(elementOrTreePath);
        if (w != null)
            internalCollapseToLevel(w, level);
    }

    /**
     * Creates all children for the given widget.
     * <p>
     * The default implementation of this framework method assumes that <code>widget.getData()</code>
     * returns the element corresponding to the node. Note: the node is not
     * visually expanded! You may have to call <code>parent.setExpanded(true)</code>.
     * </p>
     * 
     * @param widget
     *           the widget
     */
    protected void createChildren(final Widget widget) {
        final Item[] tis = getChildren(widget);
        if (tis != null && tis.length > 0) {
            Object data = tis[0].getData();
            if (data != null)
                return; // children already there!
        }

        BusyIndicator.showWhile(widget.getDisplay(), new Runnable() {
            public void run() {
                // fix for PR 1FW89L7:
                // don't complain and remove all "dummies" ...
                if (tis != null) {
                    for (int i = 0; i < tis.length; i++) {
                        if (tis[i].getData() != null) {
                            disassociate(tis[i]);
                            Assert.isTrue(tis[i].getData() == null,
                                    "Second or later child is non -null");//$NON-NLS-1$

                        }
                        tis[i].dispose();
                    }
                }
                Object d = widget.getData();
                if (d != null) {
                    Object parentElement = d;
                    Object[] children = getSortedChildren(parentElement);
                    for (int i = 0; i < children.length; i++) {
                        createTreeItem(widget, children[i], -1);
                    }
                }
            }
        });
    }

    /**
     * Creates a single item for the given parent and synchronizes it with the
     * given element.
     * 
     * @param parent
     *           the parent widget
     * @param element
     *           the element
     * @param index
     *           if non-negative, indicates the position to insert the item
     *           into its parent
     */
    protected void createTreeItem(Widget parent, Object element, int index) {
        Item item = newItem(parent, SWT.NULL, index);
        updateItem(item, element);
        updatePlus(item, element);
    }

    /**
     * The <code>AbstractTreeViewer</code> implementation of this method also
     * recurses over children of the corresponding element.
     */
    protected void disassociate(Item item) {
        super.disassociate(item);
        // recursively unmapping the items is only required when
        // the hash map is used. In the other case disposing
        // an item will recursively dispose its children.
        if (usingElementMap())
            disassociateChildren(item);
    }

    /**
     * Disassociates the children of the given SWT item from their
     * corresponding elements.
     * 
     * @param item
     *           the widget
     */
    private void disassociateChildren(Item item) {
        Item[] items = getChildren(item);
        for (int i = 0; i < items.length; i++) {
            if (items[i].getData() != null)
                disassociate(items[i]);
        }
    }

    /* (non-Javadoc) Method declared on StructuredViewer. */
    protected Widget doFindInputItem(Object element) {
        // compare with root
        Object root = getRoot();
        if (root == null)
            return null;

        if (equals(root, element))
            return getControl();
        return null;
    }

    /* (non-Javadoc) Method declared on StructuredViewer. */
    protected Widget doFindItem(Object element) {
        // compare with root
        Object root = getRoot();
        if (root == null)
            return null;

        Item[] items = getChildren(getControl());
        if (items != null) {
            for (int i = 0; i < items.length; i++) {
                Widget o = internalFindItem(items[i], element);
                if (o != null)
                    return o;
            }
        }
        return null;
    }

    /**
     * Copies the attributes of the given element into the given SWT item.
     * 
     * @param item
     *           the SWT item
     * @param element
     *           the element
     */
    protected abstract void doUpdateItem(Item item, Object element);

    /* (non-Javadoc) Method declared on StructuredViewer. */
    protected void doUpdateItem(Widget widget, Object element, boolean fullMap) {
        if (widget instanceof Item) {
            Item item = (Item) widget;

            // ensure that backpointer is correct
            if (fullMap) {
                associate(element, item);
            } else {
            	Object data = item.getData();
            	if (data != null) {
            		unmapElement(data, item);
            	}
                item.setData(element);
                mapElement(element, item);
            }

            // update icon and label
            SafeRunnable.run(new UpdateItemSafeRunnable(item, element));
        }
    }

    /**
     * Expands all nodes of the viewer's tree, starting with the root. This
     * method is equivalent to <code>expandToLevel(ALL_LEVELS)</code>.
     */
    public void expandAll() {
        expandToLevel(ALL_LEVELS);
    }

    /**
     * Expands the root of the viewer's tree to the given level.
     * 
     * @param level
     *           non-negative level, or <code>ALL_LEVELS</code> to expand all
     *           levels of the tree
     */
    public void expandToLevel(int level) {
        expandToLevel(getRoot(), level);
    }

    /**
     * Expands all ancestors of the given element or tree path so that the given element
     * becomes visible in this viewer's tree control, and then expands the
     * subtree rooted at the given element to the given level.
     * 
     * @param elementOrTreePath
     *           the element
     * @param level
     *           non-negative level, or <code>ALL_LEVELS</code> to expand all
     *           levels of the tree
     */
    public void expandToLevel(Object elementOrTreePath, int level) {
        Widget w = internalExpand(elementOrTreePath, true);
        if (w != null)
            internalExpandToLevel(w, level);
    }

    /**
     * Fires a tree collapsed event. Only listeners registered at the time this
     * method is called are notified.
     * 
     * @param event
     *           the tree expansion event
     * @see ITreeViewerListener#treeCollapsed
     */
    protected void fireTreeCollapsed(final TreeExpansionEvent event) {
        Object[] listeners = treeListeners.getListeners();
        for (int i = 0; i < listeners.length; ++i) {
            final ITreeViewerListener l = (ITreeViewerListener) listeners[i];
            SafeRunnable.run(new SafeRunnable() {
                public void run() {
                    l.treeCollapsed(event);
                }
            });
        }
    }

    /**
     * Fires a tree expanded event. Only listeners registered at the time this
     * method is called are notified.
     * 
     * @param event
     *           the tree expansion event
     * @see ITreeViewerListener#treeExpanded
     */
    protected void fireTreeExpanded(final TreeExpansionEvent event) {
        Object[] listeners = treeListeners.getListeners();
        for (int i = 0; i < listeners.length; ++i) {
            final ITreeViewerListener l = (ITreeViewerListener) listeners[i];
            SafeRunnable.run(new SafeRunnable() {
                public void run() {
                    l.treeExpanded(event);
                }
            });
        }

    }

    /**
     * Returns the auto-expand level.
     * 
     * @return non-negative level, or <code>ALL_LEVELS</code> if all levels
     *         of the tree are expanded automatically
     * @see #setAutoExpandLevel
     */
    public int getAutoExpandLevel() {
        return expandToLevel;
    }

    /**
     * Returns the SWT child items for the given SWT widget.
     * 
     * @param widget
     *           the widget
     * @return the child items
     */
    protected abstract Item[] getChildren(Widget widget);
	
	/**
	 * Get the child for the widget at index. Note that the default
	 * implementation is not very effecient and should be overridden
	 * if this class is implemented.
	 * @param widget the widget to check
	 * @param index the index of the widget
	 * @return Item or <code>null</code> if widget is not a type
	 * that can contain items.
     *
	 * @throws ArrayIndexOutOfBoundsException if the index is not valid.
     * @since 3.1
	 */
    protected Item getChild (Widget widget, int index) {
		return getChildren(widget)[index];
    }

    /**
     * Returns whether the given SWT item is expanded or collapsed.
     * 
     * @param item
     *           the item
     * @return <code>true</code> if the item is considered expanded and
     *         <code>false</code> if collapsed
     */
    protected abstract boolean getExpanded(Item item);

    /**
     * Returns a list of elements corresponding to expanded nodes in this
     * viewer's tree, including currently hidden ones that are marked as
     * expanded but are under a collapsed ancestor.
     * <p>
     * This method is typically used when preserving the interesting state of a
     * viewer; <code>setExpandedElements</code> is used during the restore.
     * </p>
     * 
     * @return the array of expanded elements
     * @see #setExpandedElements
     */
    public Object[] getExpandedElements() {
        ArrayList items = new ArrayList();
        internalCollectExpandedItems(items, getControl());
        ArrayList result = new ArrayList(items.size());
        for(Iterator it = items.iterator(); it.hasNext();) {
        	Item item = (Item) it.next();
        	Object data = item.getData();
        	if (data != null) {
        		result.add(data);
        	}
        }
        return result.toArray();
    }

    /**
     * Returns whether the node corresponding to the given element or tree path is expanded
     * or collapsed.
     * 
     * @param elementOrTreePath
     *           the element
     * @return <code>true</code> if the node is expanded, and <code>false</code>
     *         if collapsed
     */
    public boolean getExpandedState(Object elementOrTreePath) {
        Assert.isNotNull(elementOrTreePath);
        Widget item = internalGetWidgetToSelect(elementOrTreePath);
        if (item instanceof Item)
            return getExpanded((Item) item);
        return false;
    }

    /**
     * Returns the number of child items of the given SWT control.
     * 
     * @param control
     *           the control
     * @return the number of children
     */
    protected abstract int getItemCount(Control control);

    /**
     * Returns the number of child items of the given SWT item.
     * 
     * @param item
     *           the item
     * @return the number of children
     */
    protected abstract int getItemCount(Item item);

    /**
     * Returns the child items of the given SWT item.
     * 
     * @param item
     *           the item
     * @return the child items
     */
    protected abstract Item[] getItems(Item item);

    /**
     * Returns the item after the given item in the tree, or <code>null</code>
     * if there is no next item.
     * 
     * @param item
     *           the item
     * @param includeChildren
     *           <code>true</code> if the children are considered in
     *           determining which item is next, and <code>false</code> if
     *           subtrees are ignored
     * @return the next item, or <code>null</code> if none
     */
    protected Item getNextItem(Item item, boolean includeChildren) {
        if (item == null) {
            return null;
        }
        if (includeChildren && getExpanded(item)) {
            Item[] children = getItems(item);
            if (children != null && children.length > 0) {
                return children[0];
            }
        }

        //next item is either next sibling or next sibling of first
        //parent that has a next sibling.
        Item parent = getParentItem(item);
        if (parent == null) {
            return null;
        }
        Item[] siblings = getItems(parent);
        if (siblings != null){
        	if(siblings.length <= 1) 
        		return getNextItem(parent, false);
        	
        	for (int i = 0; i < siblings.length; i++) {
                if (siblings[i] == item && i < (siblings.length - 1)) {
                    return siblings[i + 1];
                }
            }
        }
        return getNextItem(parent, false);
    }

    /**
     * Returns the parent item of the given item in the tree, or <code>null</code>
     * if there is no parent item.
     * 
     * @param item
     *           the item
     * @return the parent item, or <code>null</code> if none
     */
    protected abstract Item getParentItem(Item item);

    /**
     * Returns the item before the given item in the tree, or <code>null</code>
     * if there is no previous item.
     * 
     * @param item
     *           the item
     * @return the previous item, or <code>null</code> if none
     */
    protected Item getPreviousItem(Item item) {
        //previous item is either right-most visible descendent of previous
        //sibling or parent
        Item parent = getParentItem(item);
        if (parent == null) {
            return null;
        }
        Item[] siblings = getItems(parent);
        if (siblings.length == 0 || siblings[0] == item) {
            return parent;
        }
        Item previous = siblings[0];
        for (int i = 1; i < siblings.length; i++) {
            if (siblings[i] == item) {
                return rightMostVisibleDescendent(previous);
            }
            previous = siblings[i];
        }
        return null;
    }

    /* (non-Javadoc) Method declared on StructuredViewer. */
    protected Object[] getRawChildren(Object parent) {
        if (parent != null) {
            if (equals(parent, getRoot()))
                return super.getRawChildren(parent);
            ITreeContentProvider cp = (ITreeContentProvider) getContentProvider();
            if (cp != null) {
                Object[] result = cp.getChildren(parent);
                if (result != null)
                    return result;
            }
        }
        return new Object[0];
    }

    /**
     * Returns all selected items for the given SWT control.
     * 
     * @param control
     *           the control
     * @return the list of selected items
     */
    protected abstract Item[] getSelection(Control control);

    /* (non-Javadoc) Method declared on StructuredViewer. */
    protected List getSelectionFromWidget() {
        Widget[] items = getSelection(getControl());
        ArrayList list = new ArrayList(items.length);
        for (int i = 0; i < items.length; i++) {
            Widget item = items[i];
            Object e = item.getData();
            if (e != null)
                list.add(e);
        }
        return list;
    }

    /**
     * Handles a tree collapse event from the SWT widget.
     * 
     * @param event
     *           the SWT tree event
     */
    protected void handleTreeCollapse(TreeEvent event) {
        if (event.item.getData() != null) {
            fireTreeCollapsed(new TreeExpansionEvent(this, event.item.getData()));
        }
    }

    /**
     * Handles a tree expand event from the SWT widget.
     * 
     * @param event
     *           the SWT tree event
     */
    protected void handleTreeExpand(TreeEvent event) {
    	if (!(getContentProvider() instanceof ILazyTreeContentProvider)) {
			createChildren(event.item);
		}
        if (event.item.getData() != null) {
            fireTreeExpanded(new TreeExpansionEvent(this, event.item.getData()));
        }
    }

    /* (non-Javadoc) Method declared on Viewer. */
    protected void hookControl(Control control) {
        super.hookControl(control);
        addTreeListener(control, new TreeListener() {
            public void treeExpanded(TreeEvent event) {
                handleTreeExpand(event);
            }

            public void treeCollapsed(TreeEvent event) {
                handleTreeCollapse(event);
            }
        });
    }

    /*
     * (non-Javadoc) Method declared on StructuredViewer. Builds the initial
     * tree and handles the automatic expand feature.
     */
    protected void inputChanged(Object input, Object oldInput) {
        preservingSelection(new Runnable() {
            public void run() {
                Control tree = getControl();
                boolean useRedraw = true;
                // (size > REDRAW_THRESHOLD) || (table.getItemCount() >
                // REDRAW_THRESHOLD);
                if (useRedraw)
                    tree.setRedraw(false);
                removeAll(tree);
                tree.setData(getRoot());
                createChildren(tree);
                internalExpandToLevel(tree, expandToLevel);
                if (useRedraw)
                    tree.setRedraw(true);
            }
        });
    }

    /**
     * Recursively collapses the subtree rooted at the given widget to the
     * given level.
     * <p>
     * </p>
     * Note that the default implementation of this method does not call <code>setRedraw</code>.
     * 
     * @param widget
     *           the widget
     * @param level
     *           non-negative level, or <code>ALL_LEVELS</code> to collapse
     *           all levels of the tree
     */
    protected void internalCollapseToLevel(Widget widget, int level) {
        if (level == ALL_LEVELS || level > 0) {

            if (widget instanceof Item)
                setExpanded((Item) widget, false);

            if (level == ALL_LEVELS || level > 1) {
                Item[] children = getChildren(widget);
                if (children != null) {
                    int nextLevel = (level == ALL_LEVELS ? ALL_LEVELS
                            : level - 1);
                    for (int i = 0; i < children.length; i++)
                        internalCollapseToLevel(children[i], nextLevel);
                }
            }
        }
    }

    /**
     * Recursively collects all expanded items from the given widget.
     * 
     * @param result
     *           a list (element type: <code>Item</code>) into which to
     *           collect the elements
     * @param widget
     *           the widget
     */
    private void internalCollectExpandedItems(List result, Widget widget) {
        Item[] items = getChildren(widget);
        for (int i = 0; i < items.length; i++) {
            Item item = items[i];
            if (getExpanded(item)) {
            	result.add(item);
            }
            internalCollectExpandedItems(result, item);
        }
    }

    /**
     * Tries to create a path of tree items for the given element or tree path.
     * This method recursively walks up towards the root of the tree and in the
     * case of an element (rather than a tree path) assumes that
     * <code>getParent</code> returns the correct parent of an element.
     * 
     * @param elementOrPath
     *           the element
     * @param expand
     *           <code>true</code> if all nodes on the path should be
     *           expanded, and <code>false</code> otherwise
     * @return Widget
     */
    protected Widget internalExpand(Object elementOrPath, boolean expand) {

        if (elementOrPath == null)
            return null;

        Widget w = internalGetWidgetToSelect(elementOrPath);
        if (w == null) {
            if (equals(elementOrPath, getRoot())) { // stop at root
                return null;
            }
            // my parent has to create me
            Object parent = getParentElement(elementOrPath);
            if (parent != null) {
                Widget pw = internalExpand(parent, false);
                if (pw != null) {
                    // let my parent create me
                    createChildren(pw);
                    // expand parent and find me
                    if (pw instanceof Item) {
                        Item item = (Item) pw;
                        Object element = internalToElement(elementOrPath);
                        w = internalFindChild(item, element);
                        if (expand) {
                        	// expand parent items top-down
                        	LinkedList toExpandList = new LinkedList();
                        	while (item != null && !getExpanded(item)) {
                        		toExpandList.addFirst(item);
                        		item = getParentItem(item);
                        	}
                        	for(Iterator it = toExpandList.iterator(); it.hasNext();) {
                        		Item toExpand = (Item) it.next();
                        		setExpanded(toExpand, true);
                        	}
                        }
                    }
                }
            }
        }
        return w;
    }

    /**
     * If the argument is a tree path, returns its last segment, otherwise
     * return the argument
     * @param elementOrPath an element or a tree path
     * @return the element, or the last segment of the tree path
     */
	private Object internalToElement(Object elementOrPath) {
		if (elementOrPath instanceof TreePath) {
			return ((TreePath)elementOrPath).getLastSegment();
		}
		return elementOrPath;
	}

    /**
	 * This method takes a tree path or an element. If the argument is not a
	 * tree path, returns the parent of the given element or <code>null</code>
	 * if the parent is not known. If the argument is a tree path with more than
	 * one segment, returns its parent tree path, otherwise returns
	 * <code>null</code>.
	 * 
	 * @param elementOrTreePath
	 * @return the parent element, or parent path, or <code>null</code>
	 */ 
    protected Object getParentElement(Object elementOrTreePath) {
    	if(elementOrTreePath instanceof TreePath) {
    		TreePath treePath = (TreePath)elementOrTreePath;
    		if(treePath.getSegmentCount() <= 1) {
    			return null;
    		}
			return (treePath).getParentPath();
    	}
        ITreeContentProvider cp = (ITreeContentProvider) getContentProvider();
        if (cp == null) {
            return null;
        }
        return cp.getParent(elementOrTreePath);
	}

	/**
     * Returns the widget to be selected for the given element or tree path.
     * 
     * @param elementOrTreePath the element or tree path to select
     * @return the widget to be selected, or <code>null</code> if not found
     * 
     * @since 3.1
     */
	protected Widget internalGetWidgetToSelect(Object elementOrTreePath) {
		if(elementOrTreePath instanceof TreePath) {
			TreePath treePath = (TreePath) elementOrTreePath;
			if(treePath.getSegmentCount()==0) {
				return null;
			}
			Widget[] candidates = findItems(treePath.getLastSegment());
			for (int i = 0; i < candidates.length; i++) {
				Widget candidate = candidates[i];
				if(!(candidate instanceof Item)) {
					continue;
				}
				if(treePath.equals(getTreePathFromItem((Item) candidate), getComparer())) {
					return candidate;
				}
			}
			return null;
		}
		return findItem(elementOrTreePath);
	}

    /**
     * Recursively expands the subtree rooted at the given widget to the given
     * level.
     * <p>
     * </p>
     * Note that the default implementation of this method does not call <code>setRedraw</code>.
     * 
     * @param widget
     *           the widget
     * @param level
     *           non-negative level, or <code>ALL_LEVELS</code> to collapse
     *           all levels of the tree
     */
    protected void internalExpandToLevel(Widget widget, int level) {
        if (level == ALL_LEVELS || level > 0) {
    		createChildren(widget);
            if (widget instanceof Item)
                setExpanded((Item) widget, true);
            if (level == ALL_LEVELS || level > 1) {
                Item[] children = getChildren(widget);
                if (children != null) {
                    int newLevel = (level == ALL_LEVELS ? ALL_LEVELS
                            : level - 1);
                    for (int i = 0; i < children.length; i++)
                        internalExpandToLevel(children[i], newLevel);
                }
            }
        }
    }

    /**
     * Non-recursively tries to find the given element as a child of the given
     * parent item.
     * 
     * @param parent
     *           the parent item
     * @param element
     *           the element
     * @return Widget
     */
    private Widget internalFindChild(Item parent, Object element) {
        Item[] items = getChildren(parent);
        for (int i = 0; i < items.length; i++) {
            Item item = items[i];
            Object data = item.getData();
            if (data != null && equals(data, element))
                return item;
        }
        return null;
    }

    /**
     * Recursively tries to find the given element.
     * 
     * @param parent
     *           the parent item
     * @param element
     *           the element
     * @return Widget
     */
    private Widget internalFindItem(Item parent, Object element) {

        // compare with node
        Object data = parent.getData();
        if (data != null) {
            if (equals(data, element))
                return parent;
        }
        // recurse over children
        Item[] items = getChildren(parent);
        for (int i = 0; i < items.length; i++) {
            Item item = items[i];
            Widget o = internalFindItem(item, element);
            if (o != null)
                return o;
        }
        return null;
    }

    /* (non-Javadoc) Method declared on StructuredViewer. */
    protected void internalRefresh(Object element) {
        internalRefresh(element, true);
    }

    /* (non-Javadoc) Method declared on StructuredViewer. */
    protected void internalRefresh(Object element, boolean updateLabels) {
        // If element is null, do a full refresh.
        if (element == null) {
            internalRefresh(getControl(), getRoot(), true, updateLabels);
            return;
        }
        Widget[] items = findItems(element);
        if (items.length != 0) {
			for (int i = 0; i < items.length; i++) {
				// pick up structure changes too
				internalRefresh(items[i], element, true, updateLabels);
			}            
        }
    }

    /**
     * Refreshes the tree starting at the given widget.
     * <p>
     * EXPERIMENTAL.  Not to be used except by JDT.
     * This method was added to support JDT's explorations
     * into grouping by working sets, which requires viewers to support multiple 
     * equal elements.  See bug 76482 for more details.  This support will
     * likely be removed in Eclipse 3.2 in favour of proper support for
     * multiple equal elements. 
     * </p>
     * 
     * @param widget
     *           the widget
     * @param element
     *           the element
     * @param doStruct
     *           <code>true</code> if structural changes are to be picked up,
     *           and <code>false</code> if only label provider changes are of
     *           interest
     * @param updateLabels
     *           <code>true</code> to update labels for existing elements,
     *           <code>false</code> to only update labels as needed, assuming
     *           that labels for existing elements are unchanged.
     * @since 3.1
     */
    protected void internalRefresh(Widget widget, Object element,
            boolean doStruct, boolean updateLabels) {

        if (widget instanceof Item) {
            if (doStruct) {
                updatePlus((Item) widget, element);
            }
            if (updateLabels || !equals(element, widget.getData())) {
                doUpdateItem(widget, element, true);
            } else {
                associate(element, (Item) widget);
            }
        }

        if (doStruct) {
            internalRefreshStruct(widget, element, updateLabels);
        } else {
            Item[] children = getChildren(widget);
            if (children != null) {
                for (int i = 0; i < children.length; i++) {
                    Widget item = children[i];
                    Object data = item.getData();
                    if (data != null)
                        internalRefresh(item, data, doStruct, updateLabels);
                }
            }
        }
    }

    /**
     * Update the structure and recurse. Items are updated in updateChildren,
     * as needed.
     * @param widget
     * @param element
     * @param updateLabels
     */
    private void internalRefreshStruct(Widget widget, Object element,
            boolean updateLabels) {
        updateChildren(widget, element, null, updateLabels);
        Item[] children = getChildren(widget);
        if (children != null) {
            for (int i = 0; i < children.length; i++) {
                Widget item = children[i];
                Object data = item.getData();
                if (data != null)
                    internalRefreshStruct(item, data, updateLabels);
            }
        }
    }

    /**
     * Removes the given elements from this viewer.
     * <p>
     * EXPERIMENTAL.  Not to be used except by JDT.
     * This method was added to support JDT's explorations
     * into grouping by working sets, which requires viewers to support multiple 
     * equal elements.  See bug 76482 for more details.  This support will
     * likely be removed in Eclipse 3.2 in favour of proper support for
     * multiple equal elements. 
     * </p>
     * 
     * @param elements
     *           the elements to remove
     * @since 3.1
     */
    protected void internalRemove(Object[] elements) {
        Object input = getInput();
        // Note: do not use the comparer here since the hashtable
        // contains SWT Items, not model elements.
        CustomHashtable parentItems = new CustomHashtable(5);
        for (int i = 0; i < elements.length; ++i) {
            if (equals(elements[i], input)) {
                setInput(null);
                return;
            }
            Widget[] childItems = findItems(elements[i]);
			for (int j = 0; j < childItems.length; j++) {
				Widget childItem = childItems[j];
				if (childItem instanceof Item) {
					Item parentItem = getParentItem((Item) childItem);
					if (parentItem != null) {
						parentItems.put(parentItem, parentItem);
					}
					disassociate((Item) childItem);
					childItem.dispose();
				}
			}            
        }
        Control tree = getControl();
        for (Enumeration e = parentItems.keys(); e.hasMoreElements();) {
            Item parentItem = (Item) e.nextElement();
            if(parentItem.isDisposed())
            	continue;
            if (!getExpanded(parentItem) && getItemCount(parentItem) == 0) {
                // append a dummy if necessary
                if (isExpandable(parentItem.getData())) {
                    newItem(parentItem, SWT.NULL, -1);
                } else {
                    // XXX: Workaround (PR missing)
                    tree.redraw();
                }
            }
        }
    }

    /**
     * Sets the expanded state of all items to correspond to the given set of
     * expanded elements.
     * 
     * @param expandedElements
     *           the set (element type: <code>Object</code>) of elements
     *           which are expanded
     * @param widget
     *           the widget
     */
    private void internalSetExpanded(CustomHashtable expandedElements,
            Widget widget) {
        Item[] items = getChildren(widget);
        for (int i = 0; i < items.length; i++) {
            Item item = items[i];
            Object data = item.getData();
            if (data != null) {
                // remove the element to avoid an infinite loop
                // if the same element appears on a child item
                boolean expanded = expandedElements.remove(data) != null;
                if (expanded != getExpanded(item)) {
                    if (expanded) {
                        createChildren(item);
                    }
                    setExpanded(item, expanded);
                }
            }
            internalSetExpanded(expandedElements, item);
        }
    }

    /**
     * Sets the expanded state of all items to correspond to the given set of
     * expanded tree paths.
     * 
     * @param expandedTreePaths
     *           the set (element type: <code>TreePath</code>) of elements
     *           which are expanded
     * @param widget
     *           the widget
     */
    private void internalSetExpandedTreePaths(CustomHashtable expandedTreePaths, Widget widget, TreePath currentPath) {
        Item[] items = getChildren(widget);
        for (int i = 0; i < items.length; i++) {
            Item item = items[i];
            Object data = item.getData();
            TreePath childPath = data==null ? null: currentPath.createChildPath(data);
            if (data != null && childPath!=null) {
                // remove the element to avoid an infinite loop
                // if the same element appears on a child item
                boolean expanded = expandedTreePaths.remove(childPath) != null;
                if (expanded != getExpanded(item)) {
                    if (expanded) {
                        createChildren(item);
                    }
                    setExpanded(item, expanded);
                }
            }
            internalSetExpandedTreePaths(expandedTreePaths, item, childPath);
        }
	}

    /**
     * Return whether the tree node representing the given element can be
     * expanded.
     * <p>
     * The default implementation of this framework method calls <code>hasChildren</code>
     * on this viewer's content provider. It may be overridden if necessary.
     * </p>
     * 
     * @param element
     *           the element
     * @return <code>true</code> if the tree node representing the given
     *         element can be expanded, or <code>false</code> if not
     */
    public boolean isExpandable(Object element) {
        ITreeContentProvider cp = (ITreeContentProvider) getContentProvider();
        return cp != null && cp.hasChildren(element);
    }

    /* (non-Javadoc) Method declared on Viewer. */
    protected void labelProviderChanged() {
        // we have to walk the (visible) tree and update every item
        Control tree = getControl();
        tree.setRedraw(false);
        // don't pick up structure changes, but do force label updates
        internalRefresh(tree, getRoot(), false, true);
        tree.setRedraw(true);
    }

    /**
     * Creates a new item.
     * 
     * @param parent
     *           the parent widget
     * @param style
     *           SWT style bits
     * @param index
     *           if non-negative, indicates the position to insert the item
     *           into its parent
     * @return the newly-created item
     */
    protected abstract Item newItem(Widget parent, int style, int index);

    /**
     * Removes the given elements from this viewer. The selection is updated if
     * required.
     * <p>
     * This method should be called (by the content provider) when elements
     * have been removed from the model, in order to cause the viewer to
     * accurately reflect the model. This method only affects the viewer, not
     * the model.
     * </p>
     * 
     * @param elements
     *           the elements to remove
     */
    public void remove(final Object[] elements) {
        assertElementsNotNull(elements);
        if (elements.length == 0) {
        	return;
        }
        preservingSelection(new Runnable() {
            public void run() {
                internalRemove(elements);
            }
        });
    }

    /**
     * Removes the given element from the viewer. The selection is updated if
     * necessary.
     * <p>
     * This method should be called (by the content provider) when a single
     * element has been removed from the model, in order to cause the viewer to
     * accurately reflect the model. This method only affects the viewer, not
     * the model. Note that there is another method for efficiently processing
     * the simultaneous removal of multiple elements.
     * </p>
     * 
     * @param element
     *           the element
     */
    public void remove(Object element) {
        remove(new Object[] { element });
    }

    /**
     * Removes all items from the given control.
     * 
     * @param control
     *           the control
     */
    protected abstract void removeAll(Control control);

    /**
     * Removes a listener for expand and collapse events in this viewer. Has no
     * affect if an identical listener is not registered.
     * 
     * @param listener
     *           a tree viewer listener
     */
    public void removeTreeListener(ITreeViewerListener listener) {
        treeListeners.remove(listener);
    }

    /**
     * This implementation of reveal() reveals the given element or tree path.
     */
    public void reveal(Object elementOrTreePath) {
        Assert.isNotNull(elementOrTreePath);
        Widget w = internalExpand(elementOrTreePath, true);
        if (w instanceof Item)
            showItem((Item) w);
    }

    /**
     * Returns the rightmost visible descendent of the given item. Returns the
     * item itself if it has no children.
     * 
     * @param item
     *           the item to compute the descendent of
     * @return the rightmost visible descendent or the item iself if it has no
     *         children
     */
    private Item rightMostVisibleDescendent(Item item) {
        Item[] children = getItems(item);
        if (getExpanded(item) && children != null && children.length > 0) {
            return rightMostVisibleDescendent(children[children.length - 1]);
        }
        return item;
    }

    /* (non-Javadoc) Method declared on Viewer. */
    public Item scrollDown(int x, int y) {
        Item current = getItem(x, y);
        if (current != null) {
            Item next = getNextItem(current, true);
            showItem(next == null ? current : next);
            return next;
        }
        return null;
    }

    /* (non-Javadoc) Method declared on Viewer. */
    public Item scrollUp(int x, int y) {
        Item current = getItem(x, y);
        if (current != null) {
            Item previous = getPreviousItem(current);
            showItem(previous == null ? current : previous);
            return previous;
        }
        return null;
    }

    /**
     * Sets the auto-expand level. The value 0 means that there is no
     * auto-expand; 1 means that top-level elements are expanded, but not their
     * children; 2 means that top-level elements are expanded, and their
     * children, but not grandchildren; and so on.
     * <p>
     * The value <code>ALL_LEVELS</code> means that all subtrees should be
     * expanded.
     * </p>
     * 
     * @param level
     *           non-negative level, or <code>ALL_LEVELS</code> to expand all
     *           levels of the tree
     */
    public void setAutoExpandLevel(int level) {
        expandToLevel = level;
    }

    /**
     * The <code>AbstractTreeViewer</code> implementation of this method
     * checks to ensure that the content provider is an <code>ITreeContentProvider</code>.
     */
    public void setContentProvider(IContentProvider provider) {
    	// the actual check is in assertContentProviderType
        super.setContentProvider(provider);
    }
    
	protected void assertContentProviderType(IContentProvider provider) {
		Assert.isTrue(provider instanceof ITreeContentProvider);
	}

    /**
     * Sets the expand state of the given item.
     * 
     * @param item
     *           the item
     * @param expand
     *           the expand state of the item
     */
    protected abstract void setExpanded(Item item, boolean expand);

    /**
     * Sets which nodes are expanded in this viewer's tree. The given list
     * contains the elements that are to be expanded; all other nodes are to be
     * collapsed.
     * <p>
     * This method is typically used when restoring the interesting state of a
     * viewer captured by an earlier call to <code>getExpandedElements</code>.
     * </p>
     * 
     * @param elements
     *           the array of expanded elements
     * @see #getExpandedElements
     */
    public void setExpandedElements(Object[] elements) {
        assertElementsNotNull(elements);
        CustomHashtable expandedElements = newHashtable(elements.length * 2 + 1);
        for (int i = 0; i < elements.length; ++i) {
            Object element = elements[i];
            // Ensure item exists for element. This will materialize items for
            // each element and their parents, if possible. This is important
            // to support expanding of inner tree nodes without necessarily
            // expanding their parents.
            internalExpand(element, false);
            expandedElements.put(element, element);
        }
        // this will traverse all existing items, and create children for
        // elements that need to be expanded. If the tree contains multiple
        // equal elements, and those are in the set of elements to be expanded,
        // only the first item found for each element will be expanded.
        internalSetExpanded(expandedElements, getControl());
    }

    /**
     * Sets which nodes are expanded in this viewer's tree. The given list
     * contains the tree paths that are to be expanded; all other nodes are to
     * be collapsed.
     * <p>
     * This method is typically used when restoring the interesting state of a
     * viewer captured by an earlier call to <code>getExpandedTreePaths</code>.
     * </p>
     * 
     * @param treePaths
     *           the array of expanded tree paths
     * @see #getExpandedTreePaths()
     */
    public void setExpandedTreePaths(TreePath[] treePaths) {
        assertElementsNotNull(treePaths);
        final IElementComparer comparer = getComparer();
        IElementComparer treePathComparer = new IElementComparer(){

			public boolean equals(Object a, Object b) {
				return ((TreePath)a).equals(((TreePath)b), comparer);
			}

			public int hashCode(Object element) {
				return ((TreePath)element).hashCode(comparer);
			}};
        CustomHashtable expandedTreePaths = new CustomHashtable(treePaths.length * 2 + 1, treePathComparer);
        for (int i = 0; i < treePaths.length; ++i) {
            TreePath treePath = treePaths[i];
            // Ensure item exists for element. This will materialize items for
            // each element and their parents, if possible. This is important
            // to support expanding of inner tree nodes without necessarily
            // expanding their parents.
            internalExpand(treePath, false);
            expandedTreePaths.put(treePath, treePath);
        }
        // this will traverse all existing items, and create children for
        // elements that need to be expanded. If the tree contains multiple
        // equal elements, and those are in the set of elements to be expanded,
        // only the first item found for each element will be expanded.
        internalSetExpandedTreePaths(expandedTreePaths, getControl(), new TreePath(new Object[0]));
    }

	/**
     * Sets whether the node corresponding to the given element or tree path is expanded or
     * collapsed.
     * 
     * @param elementOrTreePath
     *           the element
     * @param expanded
     *           <code>true</code> if the node is expanded, and <code>false</code>
     *           if collapsed
     */
    public void setExpandedState(Object elementOrTreePath, boolean expanded) {
        Assert.isNotNull(elementOrTreePath);
        Widget item = internalExpand(elementOrTreePath, false);
        if (item instanceof Item) {
            if (expanded) {
                createChildren(item);
            }
            setExpanded((Item) item, expanded);
        }
    }

    /**
     * Sets the selection to the given list of items.
     * 
     * @param items
     *           list of items (element type: <code>org.eclipse.swt.widgets.Item</code>)
     */
    protected abstract void setSelection(List items);

    /**
     *  This implementation of setSelectionToWidget accepts a list of elements
     *  or a list of tree paths.
     **/
    protected void setSelectionToWidget(List v, boolean reveal) {
        if (v == null) {
            setSelection(new ArrayList(0));
            return;
        }
        int size = v.size();
        List newSelection = new ArrayList(size);
        for (int i = 0; i < size; ++i) {
            // Use internalExpand since item may not yet be created. See
            // 1G6B1AR.
            Widget w = internalExpand(v.get(i), false);
            if (w instanceof Item) {
                newSelection.add(w);
            }
        }
        setSelection(newSelection);
        
        // Although setting the selection in the control should reveal it,
        // setSelection may be a no-op if the selection is unchanged,
        // so explicitly reveal the first item in the selection here.
        // See bug 100565 for more details.
        if (reveal && newSelection.size() > 0) {
            showItem((Item) newSelection.get(0));
        }
    }

    /**
     * Shows the given item.
     * 
     * @param item
     *           the item
     */
    protected abstract void showItem(Item item);

    /**
     * Updates the tree items to correspond to the child elements of the given
     * parent element. If null is passed for the children, this method obtains
     * them (only if needed).
     * 
     * @param widget
     *           the widget
     * @param parent
     *           the parent element
     * @param elementChildren
     *           the child elements, or null
     * @deprecated this is no longer called by the framework
     */
    protected void updateChildren(Widget widget, Object parent,
            Object[] elementChildren) {
        updateChildren(widget, parent, elementChildren, true);
    }

    /**
     * Updates the tree items to correspond to the child elements of the given
     * parent element. If null is passed for the children, this method obtains
     * them (only if needed).
     * 
     * @param widget
     *           the widget
     * @param parent
     *           the parent element
     * @param elementChildren
     *           the child elements, or null
     * @param updateLabels
     *           <code>true</code> to update labels for existing elements,
     *           <code>false</code> to only update labels as needed, assuming
     *           that labels for existing elements are unchanged.
     * @since 2.1
     */
    private void updateChildren(Widget widget, Object parent,
            Object[] elementChildren, boolean updateLabels) {
        // optimization! prune collapsed subtrees
        if (widget instanceof Item) {
            Item ti = (Item) widget;
            if (!getExpanded(ti)) {
                // need a dummy node if element is expandable;
                // but try to avoid recreating the dummy node
                boolean needDummy = isExpandable(parent);
                boolean haveDummy = false;
                // remove all children
                Item[] items = getItems(ti);
                for (int i = 0; i < items.length; i++) {
                    if (items[i].getData() != null) {
                        disassociate(items[i]);
                        items[i].dispose();
                    } else {
                        if (needDummy && !haveDummy) {
                            haveDummy = true;
                        } else {
                            items[i].dispose();
                        }
                    }
                }
                if (needDummy && !haveDummy) {
                    newItem(ti, SWT.NULL, -1);
                }

                return;
            }
        }

        // If the children weren't passed in, get them now since they're needed
        // below.
        if (elementChildren == null) {
            elementChildren = getSortedChildren(parent);
        }

        Control tree = getControl();

        // WORKAROUND
        int oldCnt = -1;
        if (widget == tree)
            oldCnt = getItemCount(tree);

        Item[] items = getChildren(widget);

        // save the expanded elements
        CustomHashtable expanded = newHashtable(CustomHashtable.DEFAULT_CAPACITY); // assume num expanded is small
        for (int i = 0; i < items.length; ++i) {
            if (getExpanded(items[i])) {
                Object element = items[i].getData();
                if (element != null) {
                    expanded.put(element, element);
                }
            }
        }

        int min = Math.min(elementChildren.length, items.length);

        // Note: In the code below, doing disassociate calls before associate
        // calls is important,
        // since a later disassociate can undo an earlier associate,
        // if items are changing position.

        // dispose of all items beyond the end of the current elements
        for (int i = items.length; --i >= min;) {
            if (items[i].getData() != null) {
                disassociate(items[i]);
            }
            items[i].dispose();
        }

        // compare first min items, and update item if necessary
        // need to do it in two passes:
        // 1: disassociate old items
        // 2: associate new items
        // because otherwise a later disassociate can remove a mapping made for
        // a previous associate,
        // making the map inconsistent
        for (int i = 0; i < min; ++i) {
            Item item = items[i];
            Object oldElement = item.getData();
            if (oldElement != null) {
                Object newElement = elementChildren[i];
                if (newElement != oldElement) {
                    if (equals(newElement, oldElement)) {
                        // update the data to be the new element, since
                        // although the elements
                        // may be equal, they may still have different labels
                        // or children
                    	Object data = item.getData();
                    	if (data != null) {
                    		unmapElement(data, item);
                    	}
                        item.setData(newElement);
                        mapElement(newElement, item);
                    } else {
                        disassociate(item);
                        //Clear the text and image to force a label update
                        item.setImage(null);
                        item.setText("");//$NON-NLS-1$

                    }
                }
            }
        }
        for (int i = 0; i < min; ++i) {
            Item item = items[i];
            Object newElement = elementChildren[i];
            if (item.getData() == null) {
                // old and new elements are not equal
                associate(newElement, item);
                updatePlus(item, newElement);
                updateItem(item, newElement);
                // Restore expanded state for items that changed position.
                // Make sure setExpanded is called after updatePlus, since
                // setExpanded(false) fails if item has no children.
                // Need to call setExpanded for both expanded and unexpanded
                // cases
                // since the expanded state can change either way.
                setExpanded(item, expanded.containsKey(newElement));
            } else {
                // old and new elements are equal
                updatePlus(item, newElement);
                if (updateLabels) {
                    updateItem(item, newElement);
                }
            }
        }

        // add any remaining elements
        if (min < elementChildren.length) {
            for (int i = min; i < elementChildren.length; ++i) {
                createTreeItem(widget, elementChildren[i], i);
            }

            // Need to restore expanded state in a separate pass
            // because createTreeItem does not return the new item.
            // Avoid doing this unless needed.
            if (expanded.size() > 0) {
                // get the items again, to include the new items
                items = getChildren(widget);
                for (int i = min; i < elementChildren.length; ++i) {
                    // Restore expanded state for items that changed position.
                    // Make sure setExpanded is called after updatePlus (called
                    // in createTreeItem), since
                    // setExpanded(false) fails if item has no children.
                    // Only need to call setExpanded if element was expanded
                    // since new items are initially unexpanded.
                    if (expanded.containsKey(elementChildren[i])) {
                        setExpanded(items[i], true);
                    }
                }
            }
        }

        // WORKAROUND
        if (widget == tree && oldCnt == 0 && getItemCount(tree) != 0) {
            //System.out.println("WORKAROUND setRedraw");
            tree.setRedraw(false);
            tree.setRedraw(true);
        }
    }

    /**
     * Updates the "+"/"-" icon of the tree node from the given element. It
     * calls <code>isExpandable</code> to determine whether an element is
     * expandable.
     * 
     * @param item
     *           the item
     * @param element
     *           the element
     */
    protected void updatePlus(Item item, Object element) {
        boolean hasPlus = getItemCount(item) > 0;
        boolean needsPlus = isExpandable(element);
        boolean removeAll = false;
        boolean addDummy = false;
        Object data = item.getData();
        if (data != null && equals(element, data)) {
            // item shows same element
            if (hasPlus != needsPlus) {
                if (needsPlus)
                    addDummy = true;
                else
                    removeAll = true;
            }
        } else {
            // item shows different element
            removeAll = true;
            addDummy = needsPlus;

            // we cannot maintain expand state so collapse it
            setExpanded(item, false);
        }
        if (removeAll) {
            // remove all children
            Item[] items = getItems(item);
            for (int i = 0; i < items.length; i++) {
                if (items[i].getData() != null)
                    disassociate(items[i]);
                items[i].dispose();
            }
        }
        if (addDummy)
            newItem(item, SWT.NULL, -1); // append a dummy
    }

    /**
     * Gets the expanded elements that are visible to the user. An expanded
     * element is only visible if the parent is expanded.
     * 
     * @return the visible expanded elements
     * @since 2.0
     */
    public Object[] getVisibleExpandedElements() {
        ArrayList v = new ArrayList();
        internalCollectVisibleExpanded(v, getControl());
        return v.toArray();
    }

    private void internalCollectVisibleExpanded(ArrayList result, Widget widget) {
        Item[] items = getChildren(widget);
        for (int i = 0; i < items.length; i++) {
            Item item = items[i];
            if (getExpanded(item)) {
                Object data = item.getData();
                if (data != null)
                    result.add(data);
                //Only recurse if it is expanded - if
                //not then the children aren't visible
                internalCollectVisibleExpanded(result, item);
            }
        }
    }

    protected TreePath getTreePathFromItem(Item item) {
		LinkedList segments = new LinkedList();
		while(item!=null) {
			Object segment = item.getData();
			Assert.isNotNull(segment);
			segments.addFirst(segment);
			item = getParentItem(item);
		}
		return new TreePath(segments.toArray());
	}

	/**
	 * This implementation of getSelection() returns an instance of
	 * ITreeSelection.
	 * 
	 * @since 3.2
	 */
	public ISelection getSelection() {
		Control control = getControl();
		if (control == null || control.isDisposed()) {
			return TreeSelection.EMPTY;
		}
		Widget[] items = getSelection(getControl());
		ArrayList list = new ArrayList(items.length);
		for (int i = 0; i < items.length; i++) {
			Widget item = items[i];
			if (item.getData() != null) {
				list.add(getTreePathFromItem((Item) item));
			}
		}
		return new TreeSelection((TreePath[]) list.toArray(new TreePath[list
				.size()]));
	}
	
	protected void setSelectionToWidget(ISelection selection, boolean reveal) {
		if(selection instanceof ITreeSelection) {
			ITreeSelection treeSelection = (ITreeSelection) selection;
			setSelectionToWidget(Arrays.asList(treeSelection.getPaths()), reveal);
		} else {
			super.setSelectionToWidget(selection, reveal);
		}
	}

    /**
     * Returns a list of tree paths corresponding to expanded nodes in this
     * viewer's tree, including currently hidden ones that are marked as
     * expanded but are under a collapsed ancestor.
     * <p>
     * This method is typically used when preserving the interesting state of a
     * viewer; <code>setExpandedElements</code> is used during the restore.
     * </p>
     * 
     * @return the array of expanded tree paths
     * @see #setExpandedElements
     */
    public TreePath[] getExpandedTreePaths() {
        ArrayList items = new ArrayList();
        internalCollectExpandedItems(items, getControl());
        ArrayList result = new ArrayList(items.size());
        for(Iterator it = items.iterator(); it.hasNext();) {
        	Item item = (Item) it.next();
        	TreePath treePath = getTreePathFromItem(item);
        	if (treePath != null) {
        		result.add(treePath);
        	}
        }
        return (TreePath[]) result.toArray(new TreePath[items.size()]);
    }

}
