⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstracttreeviewer.java

📁 jfa2ce 源码帮助开发人员更好的理解运用
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: *     IBM Corporation - initial API and implementation *******************************************************************************/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.SelectionEvent;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> * As of 3.2, AbstractTreeViewer 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 abstract tree viewers must implement one of the * interfaces <code>ITreeContentProvider</code> or (as of 3.2, to support * multiple equal elements) <code>ITreePathContentProvider</code>. * </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 parentElementOrTreePath     *           the parent element     * @param childElements     *           the child elements to add     */    public void add(Object parentElementOrTreePath, Object[] childElements) {        Assert.isNotNull(parentElementOrTreePath);        assertElementsNotNull(childElements);        Widget[] widgets = internalFindItems(parentElementOrTreePath);        // 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], parentElementOrTreePath, childElements);		}            }    /**     * Find the items for the given element of tree path     * @param parentElementOrTreePath the element or tree path     * @return the items for that element     */	private Widget[] internalFindItems(Object parentElementOrTreePath) {		Widget[] widgets = findItems(parentElementOrTreePath);        if (parentElementOrTreePath instanceof TreePath) {			TreePath path = (TreePath) parentElementOrTreePath;			Widget w = internalFindItem(path);			if (w == null) {				widgets = new Widget[] { };			} else {				widgets = new Widget[] { w };			}		} else {			widgets = findItems(parentElementOrTreePath);		}		return widgets;	}	/**	 * Return the item at the given path or <code>null</code>	 * @param path the path	 * @return the item at that path	 * TODO could probably do better than this	 */	private Widget internalFindItem(TreePath path) {		Widget[] widgets = findItems(path.getLastSegment());		for (int i = 0; i < widgets.length; i++) {			Widget widget = widgets[i];			if (widget instanceof Item) {				Item item = (Item) widget;				TreePath p = getTreePathFromItem(item);				if (p.equals(path)) {					return widget;				}						}		}		return null;	}	/**     * 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 parentElementOrTreePath     *           the parent element     * @param childElements     *           the child elements to add     * @since 3.1     */    protected void internalAdd(Widget widget, Object parentElementOrTreePath, Object[] childElements) {    	Object parent;    	TreePath path;    	if (parentElementOrTreePath instanceof TreePath) {			path = (TreePath) parentElementOrTreePath;			parent = path.getLastSegment();		} else {			parent = parentElementOrTreePath;			path = null;		}    			// 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(ti, path, 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();                        }                    }                }                // append a dummy if necessary                if (needDummy && !haveDummy) {					newItem(ti, SWT.NULL, -1);				}                return;            }        }        if (childElements.length > 0) {        	// TODO: Add filtering back?            Object[] filtered = filter(parentElementOrTreePath, childElements);			ViewerComparator comparator = getComparator();			if(comparator != null) {				if (comparator instanceof TreePathViewerSorter) {					TreePathViewerSorter tpvs = (TreePathViewerSorter) comparator;					if (path == null) {						path = internalGetSorterParentPath(widget, comparator);					}					tpvs.sort(this, path, filtered);				} else {					comparator.sort(this,filtered);				}			}            createAddedElements(widget, filtered);        }	}	/**	 * Filter the children elements.	 * @param parentElementOrTreePath the parent element or path	 * @param elements the child elements	 * @return the filter list of children	 */	private Object[] filter(Object parentElementOrTreePath, Object[] elements) {		ViewerFilter[] filters = getFilters();		if (filters != null) {			ArrayList filtered = new ArrayList(elements.length);			for (int i = 0; i < elements.length; i++) {				boolean add = true;				for (int j = 0; j < filters.length; j++) {					add = filters[j].select(this, parentElementOrTreePath, elements[i]);					if (!add) {						break;					}				}				if (add) {					filtered.add(elements[i]);				}			}			return filtered.toArray();		}		return elements;	}	/**     * 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;			}		}				ViewerComparator comparator = getComparator();		TreePath parentPath = internalGetSorterParentPath(widget, comparator);		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(comparator == null){				if(itemExists(items,element)){					refresh(element);					newItem = false;				}				index = -1;			}			else{				lastInsertion = insertionPosition(items,comparator,lastInsertion, element, parentPath);				//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 && internalCompare(comparator,parentPath,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()) {			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.     * @param parentPath the tree path for the element's parent or <code>null</code>     * if the element is a root element or the sorter is not a {@link TreePathViewerSorter}     * @return the index to use when inserting the element.     * 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -