com.ebmwebsourcing.petals.common.internal.provisional.ui.jdt.CheckboxTreeAndListGroup.java Source code

Java tutorial

Introduction

Here is the source code for com.ebmwebsourcing.petals.common.internal.provisional.ui.jdt.CheckboxTreeAndListGroup.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2008 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 com.ebmwebsourcing.petals.common.internal.provisional.ui.jdt;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Tree;

/**
 * Combines a CheckboxTreeViewer and CheckboxListViewer.
 * <p>
 * All viewer selection-driven interactions are handled within this viewer.
 * </p>
 * <p>
 * Comes from the plug-in "org.eclipse.jdt.ui".
 * </p>
 * 
 * @contributor Vincent Zurczak - EBM WebSourcing
 * <ul>
 *       <li>Added the method "refresh" to refresh the viewers.</li>
 *       <li>Improved performances with the items map.</li>
 *       <li>Added a "dispose()" method.</li>
 * </ul>
 * 
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class CheckboxTreeAndListGroup
        implements ICheckStateListener, ISelectionChangedListener, ITreeViewerListener {

    private Object fRoot;
    private Object fCurrentTreeSelection;
    private final List fExpandedTreeNodes = new ArrayList();
    private final Map fCheckedStateStore = new HashMap(9);
    private final List fWhiteCheckedTreeItems = new ArrayList();
    private final List fListeners = new ArrayList();

    private final ITreeContentProvider fTreeContentProvider;
    private final IStructuredContentProvider fListContentProvider;
    private final ILabelProvider fTreeLabelProvider;
    private final ILabelProvider fListLabelProvider;

    // widgets
    private CheckboxTreeViewer fTreeViewer;
    private CheckboxTableViewer fListViewer;

    /**
     *   Creates an instance of this class.  Use this constructor if you wish to specify
     *   the width and/or height of the combined widget (to only hardcode one of the
     *   sizing dimensions, specify the other dimension's value as -1)
     * @param parent parent composite
     * @param rootObject
     * @param treeContentProvider
     * @param treeLabelProvider
     * @param listContentProvider
     * @param listLabelProvider
     * @param style
     * @param width the width
     * @param height the height
     */
    public CheckboxTreeAndListGroup(Composite parent, Object rootObject, ITreeContentProvider treeContentProvider,
            ILabelProvider treeLabelProvider, IStructuredContentProvider listContentProvider,
            ILabelProvider listLabelProvider, int style, int width, int height) {
        this.fRoot = rootObject;
        this.fTreeContentProvider = treeContentProvider;
        this.fListContentProvider = listContentProvider;
        this.fTreeLabelProvider = treeLabelProvider;
        this.fListLabelProvider = listLabelProvider;
        createContents(parent, width, height, style);
    }

    /**
     * This method must be called just before this window becomes visible.
     */
    public void aboutToOpen() {
        determineWhiteCheckedDescendents(this.fRoot);
        checkNewTreeElements(getTreeChildren(this.fRoot));
        this.fCurrentTreeSelection = null;

        //select the first element in the list
        Object[] elements = getTreeChildren(this.fRoot);
        Object primary = elements.length > 0 ? elements[0] : null;
        if (primary != null) {
            this.fTreeViewer.setSelection(new StructuredSelection(primary));
        }
        this.fTreeViewer.getControl().setFocus();
    }

    /**
     *   Adds the passed listener to self's collection of clients
     *   that listen for changes to element checked states
     *
     *   @param listener ICheckStateListener
     */
    public void addCheckStateListener(ICheckStateListener listener) {
        this.fListeners.add(listener);
    }

    /**
     * Adds the receiver and all of it's ancestors to the checkedStateStore if they
     * are not already there.
     * @param treeElement
     */
    private void addToHierarchyToCheckedStore(Object treeElement) {

        // if this tree element is already gray then its ancestors all are as well
        if (!this.fCheckedStateStore.containsKey(treeElement))
            this.fCheckedStateStore.put(treeElement, new ArrayList());

        Object parent = this.fTreeContentProvider.getParent(treeElement);
        if (parent != null)
            addToHierarchyToCheckedStore(parent);
    }

    /**
     *   Returns a boolean indicating whether all children of the passed tree element
     *   are currently white-checked
     *
     *   @return boolean
     *   @param treeElement java.lang.Object
     */
    protected boolean areAllChildrenWhiteChecked(Object treeElement) {
        Object[] children = getTreeChildren(treeElement);
        for (int i = 0; i < children.length; ++i) {
            if (!this.fWhiteCheckedTreeItems.contains(children[i]))
                return false;
        }

        return true;
    }

    /**
     *   Returns a boolean indicating whether all list elements associated with
     *   the passed tree element are currently checked
     *
     *   @return boolean
     *   @param treeElement java.lang.Object
     */
    protected boolean areAllElementsChecked(Object treeElement) {
        List checkedElements = (List) this.fCheckedStateStore.get(treeElement);
        if (checkedElements == null) // ie.- tree item not even gray-checked
            return false;

        return getListItemsSize(treeElement) == checkedElements.size();
    }

    /**
     *   Iterates through the passed elements which are being realized for the first
     *   time and check each one in the tree viewer as appropriate
     * @param elements
     */
    protected void checkNewTreeElements(Object[] elements) {
        for (int i = 0; i < elements.length; ++i) {
            Object currentElement = elements[i];
            boolean checked = this.fCheckedStateStore.containsKey(currentElement);
            this.fTreeViewer.setChecked(currentElement, checked);
            this.fTreeViewer.setGrayed(currentElement,
                    checked && !this.fWhiteCheckedTreeItems.contains(currentElement));
        }
    }

    /**
     *   An item was checked in one of self's two views.  Determine which
     *   view this occurred in and delegate appropriately
     *
     *   @param event CheckStateChangedEvent
     */
    public void checkStateChanged(final CheckStateChangedEvent event) {

        //Potentially long operation - show a busy cursor
        BusyIndicator.showWhile(this.fTreeViewer.getControl().getDisplay(), new Runnable() {
            public void run() {
                if (event.getCheckable().equals(CheckboxTreeAndListGroup.this.fTreeViewer))
                    treeItemChecked(event.getElement(), event.getChecked());
                else
                    listItemChecked(event.getElement(), event.getChecked(), true);

                notifyCheckStateChangeListeners(event);
            }
        });
    }

    /**
     *   Lay out and initialize self's visual components.
     *
     *   @param parent org.eclipse.swt.widgets.Composite
     *   @param width int
     *   @param height int
     * @param style
     */
    protected void createContents(Composite parent, int width, int height, int style) {
        // group pane
        Composite composite = new Composite(parent, style);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.makeColumnsEqualWidth = true;
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));

        createTreeViewer(composite, width / 2, height);
        createListViewer(composite, width / 2, height);

        initialize();
    }

    /**
     *   Creates this group's list viewer.
     * @param parent the parent composite
     * @param width the width
     * @param height the height
     */
    protected void createListViewer(Composite parent, int width, int height) {
        this.fListViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER);
        this.fListViewer.setUseHashlookup(true);
        GridData data = new GridData(GridData.FILL_BOTH);
        data.widthHint = width;
        data.heightHint = height;
        this.fListViewer.getTable().setLayoutData(data);
        this.fListViewer.setContentProvider(this.fListContentProvider);
        this.fListViewer.setLabelProvider(this.fListLabelProvider);
        this.fListViewer.addCheckStateListener(this);
    }

    /**
     *   Creates this group's tree viewer.
     * @param parent parent composite
     * @param width the width
     * @param height the height
     */
    protected void createTreeViewer(Composite parent, int width, int height) {
        Tree tree = new Tree(parent, SWT.CHECK | SWT.BORDER);
        GridData data = new GridData(GridData.FILL_BOTH);
        data.widthHint = width;
        data.heightHint = height;
        tree.setLayoutData(data);

        this.fTreeViewer = new CheckboxTreeViewer(tree);
        this.fTreeViewer.setUseHashlookup(true);
        this.fTreeViewer.setContentProvider(this.fTreeContentProvider);
        this.fTreeViewer.setLabelProvider(this.fTreeLabelProvider);
        this.fTreeViewer.addTreeListener(this);
        this.fTreeViewer.addCheckStateListener(this);
        this.fTreeViewer.addSelectionChangedListener(this);
    }

    /**
     * Returns a boolean indicating whether the passed tree element should be
     * at LEAST gray-checked.  Note that this method does not consider whether
     * it should be white-checked, so a specified tree item which should be
     * white-checked will result in a <code>true</code> answer from this method.
     * To determine whether a tree item should be white-checked use method
     * #determineShouldBeWhiteChecked(Object).
     *
     * @param treeElement java.lang.Object
     * @return boolean
     * @see #determineShouldBeWhiteChecked(java.lang.Object)
     */
    protected boolean determineShouldBeAtLeastGrayChecked(Object treeElement) {
        // if any list items associated with treeElement are checked then it
        // retains its gray-checked status regardless of its children
        List checked = (List) this.fCheckedStateStore.get(treeElement);
        if (checked != null && !checked.isEmpty())
            return true;

        // if any children of treeElement are still gray-checked then treeElement
        // must remain gray-checked as well
        Object[] children = getTreeChildren(treeElement);
        for (int i = 0; i < children.length; ++i) {
            if (this.fCheckedStateStore.containsKey(children[i]))
                return true;
        }

        return false;
    }

    /**
     * Returns a boolean indicating whether the passed tree item should be
     * white-checked.
     *
     * @return boolean
     * @param treeElement java.lang.Object
     */
    protected boolean determineShouldBeWhiteChecked(Object treeElement) {
        return areAllChildrenWhiteChecked(treeElement) && areAllElementsChecked(treeElement);
    }

    /**
     *   Recursively adds appropriate tree elements to the collection of
     *   known white-checked tree elements.
     *
     *   @param treeElement java.lang.Object
     */
    protected void determineWhiteCheckedDescendents(Object treeElement) {
        // always go through all children first since their white-checked
        // statuses will be needed to determine the white-checked status for
        // this tree element
        Object[] children = getTreeChildren(treeElement);
        for (int i = 0; i < children.length; ++i)
            determineWhiteCheckedDescendents(children[i]);

        // now determine the white-checked status for this tree element
        if (determineShouldBeWhiteChecked(treeElement))
            setWhiteChecked(treeElement, true);
    }

    /**
     * Causes the tree viewer to expand all its items
     */
    public void expandAll() {
        this.fTreeViewer.expandAll();
    }

    /**
     *   Answers a flat collection of all of the checked elements in the
     *   list portion of self
     *
     *   @return java.util.Vector
     */
    public Iterator getAllCheckedListItems() {
        Set result = new HashSet();
        Iterator listCollectionsEnum = this.fCheckedStateStore.values().iterator();
        while (listCollectionsEnum.hasNext())
            result.addAll((List) listCollectionsEnum.next());
        return result.iterator();
    }

    /**
     *   Answer a collection of all of the checked elements in the tree portion
     *   of self
     *
     *   @return java.util.Vector
     */
    public Set getAllCheckedTreeItems() {
        return new HashSet(this.fCheckedStateStore.keySet());
    }

    /**
     *   Answers the number of elements that have been checked by the
     *   user.
     *
     *   @return int
     */
    public int getCheckedElementCount() {
        return this.fCheckedStateStore.size();
    }

    /**
     *   Returns a count of the number of list items associated with a
     *   given tree item.
     *
     *   @return int
     *   @param treeElement java.lang.Object
     */
    protected int getListItemsSize(Object treeElement) {
        Object[] elements = getListElements(treeElement);
        return elements.length;
    }

    /**
     * Gets the table that displays the folder content
     *
     * @return the table used to show the list
     */
    public Table getTable() {
        return this.fListViewer.getTable();
    }

    /**
     * Gets the tree that displays the list for a folder
     *
     * @return the tree used to show the folders
     */
    public Tree getTree() {
        return this.fTreeViewer.getTree();
    }

    /**
     * Adds the given filter to the tree viewer and
     * triggers refiltering and resorting of the elements.
     *
     * @param filter a viewer filter
     */
    public void addTreeFilter(ViewerFilter filter) {
        this.fTreeViewer.addFilter(filter);
    }

    /**
     * Adds the given filter to the list viewer and
     * triggers refiltering and resorting of the elements.
     *
     * @param filter a viewer filter
     */
    public void addListFilter(ViewerFilter filter) {
        this.fListViewer.addFilter(filter);
    }

    /**
     *   Logically gray-check all ancestors of treeItem by ensuring that they
     *   appear in the checked table
     * @param treeElement
     */
    protected void grayCheckHierarchy(Object treeElement) {

        // if this tree element is already gray then its ancestors all are as well
        if (this.fCheckedStateStore.containsKey(treeElement))
            return; // no need to proceed upwards from here

        this.fCheckedStateStore.put(treeElement, new ArrayList());
        if (determineShouldBeWhiteChecked(treeElement)) {
            setWhiteChecked(treeElement, true);
        }
        Object parent = this.fTreeContentProvider.getParent(treeElement);
        if (parent != null)
            grayCheckHierarchy(parent);
    }

    /**
     *   Sets the initial checked state of the passed list element to true.
     * @param element
     */
    public void initialCheckListItem(Object element) {
        Object parent = this.fTreeContentProvider.getParent(element);
        this.fCurrentTreeSelection = parent;
        //As this is not done from the UI then set the box for updating from the selection to false
        listItemChecked(element, true, false);
        updateHierarchy(parent);
    }

    /**
     *   Sets the initial checked state of the passed element to true,
     *   as well as to all of its children and associated list elements
     * @param element
     */
    public void initialCheckTreeItem(Object element) {
        treeItemChecked(element, true);
    }

    /**
     *   Initializes this group's viewers after they have been laid out.
     */
    protected void initialize() {
        this.fTreeViewer.setInput(this.fRoot);
    }

    /**
     *   Callback that's invoked when the checked status of an item in the list
     *   is changed by the user. Do not try and update the hierarchy if we are building the
     *  initial list.
     * @param listElement
     * @param state
     * @param updatingFromSelection
     */
    protected void listItemChecked(Object listElement, boolean state, boolean updatingFromSelection) {
        List checkedListItems = (List) this.fCheckedStateStore.get(this.fCurrentTreeSelection);

        if (state) {
            if (checkedListItems == null) {
                // since the associated tree item has gone from 0 -> 1 checked
                // list items, tree checking may need to be updated
                grayCheckHierarchy(this.fCurrentTreeSelection);
                checkedListItems = (List) this.fCheckedStateStore.get(this.fCurrentTreeSelection);
            }
            checkedListItems.add(listElement);
        } else {
            checkedListItems.remove(listElement);
            if (checkedListItems.isEmpty()) {
                // since the associated tree item has gone from 1 -> 0 checked
                // list items, tree checking may need to be updated
                ungrayCheckHierarchy(this.fCurrentTreeSelection);
            }
        }

        if (updatingFromSelection)
            updateHierarchy(this.fCurrentTreeSelection);
    }

    /**
     *   Notifies all checked state listeners that the passed element has had
     *   its checked state changed to the passed state
     * @param event
     */
    protected void notifyCheckStateChangeListeners(CheckStateChangedEvent event) {
        Iterator listenersEnum = this.fListeners.iterator();
        while (listenersEnum.hasNext())
            ((ICheckStateListener) listenersEnum.next()).checkStateChanged(event);
    }

    /**
     *Sets the contents of the list viewer based upon the specified selected
     *tree element.  This also includes checking the appropriate list items.
     *
     *@param treeElement java.lang.Object
     */
    protected void populateListViewer(final Object treeElement) {
        if (treeElement == this.fCurrentTreeSelection)
            return;
        this.fCurrentTreeSelection = treeElement;
        this.fListViewer.setInput(treeElement);
        List listItemsToCheck = (List) this.fCheckedStateStore.get(treeElement);

        if (listItemsToCheck != null) {
            Iterator listItemsEnum = listItemsToCheck.iterator();
            while (listItemsEnum.hasNext())
                this.fListViewer.setChecked(listItemsEnum.next(), true);
        }
    }

    /**
     *   Removes the passed listener from self's collection of clients
     *   that listen for changes to element checked states
     *
     *   @param listener ICheckStateListener
     */
    public void removeCheckStateListener(ICheckStateListener listener) {
        this.fListeners.remove(listener);
    }

    /**
     *   Handles the selection of an item in the tree viewer
     *
     *   @param event ISelection
     */
    public void selectionChanged(final SelectionChangedEvent event) {
        BusyIndicator.showWhile(getTable().getShell().getDisplay(), new Runnable() {
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                Object selectedElement = selection.getFirstElement();
                if (selectedElement == null) {
                    CheckboxTreeAndListGroup.this.fCurrentTreeSelection = null;
                    CheckboxTreeAndListGroup.this.fListViewer
                            .setInput(CheckboxTreeAndListGroup.this.fCurrentTreeSelection);
                    return;
                }
                populateListViewer(selectedElement);
            }
        });
    }

    /**
     * Selects or deselect all of the elements in the tree depending on the value of the selection
     * boolean. Be sure to update the displayed files as well.
     * @param selection
     */
    public void setAllSelections(final boolean selection) {

        //Potentially long operation - show a busy cursor
        BusyIndicator.showWhile(this.fTreeViewer.getControl().getDisplay(), new Runnable() {
            public void run() {
                setTreeChecked(CheckboxTreeAndListGroup.this.fRoot, selection);
                CheckboxTreeAndListGroup.this.fListViewer.setAllChecked(selection);
            }
        });
    }

    /**
     *   Sets the list viewer's providers to those passed
     *
     *   @param contentProvider ITreeContentProvider
     *   @param labelProvider ILabelProvider
     */
    public void setListProviders(IStructuredContentProvider contentProvider, ILabelProvider labelProvider) {
        this.fListViewer.setContentProvider(contentProvider);
        this.fListViewer.setLabelProvider(labelProvider);
    }

    /**
     *   Sets the sorter that is to be applied to self's list viewer
     * @param comparator
     */
    public void setListComparator(ViewerComparator comparator) {
        this.fListViewer.setComparator(comparator);
    }

    /**
     * Sets the root of the widget to be new Root. Regenerate all of the tables and lists from this
     * value.
     *
     * @param newRoot
     */
    public void setRoot(Object newRoot) {
        this.fRoot = newRoot;
        initialize();
    }

    /**
     *   Sets the checked state of the passed tree element appropriately, and
     *   do so recursively to all of its child tree elements as well
     * @param treeElement
     * @param state
     */
    protected void setTreeChecked(Object treeElement, boolean state) {

        if (treeElement.equals(this.fCurrentTreeSelection)) {
            this.fListViewer.setAllChecked(state);
        }

        if (state) {
            Object[] listItems = getListElements(treeElement);
            List listItemsChecked = new ArrayList();
            for (int i = 0; i < listItems.length; ++i)
                listItemsChecked.add(listItems[i]);

            this.fCheckedStateStore.put(treeElement, listItemsChecked);
        } else
            this.fCheckedStateStore.remove(treeElement);

        setWhiteChecked(treeElement, state);
        this.fTreeViewer.setChecked(treeElement, state);
        this.fTreeViewer.setGrayed(treeElement, false);

        // now logically check/uncheck all children as well
        Object[] children = getTreeChildren(treeElement);
        for (int i = 0; i < children.length; ++i) {
            setTreeChecked(children[i], state);
        }
    }

    /**
     *   Sets the tree viewer's providers to those passed
     *
     *   @param contentProvider ITreeContentProvider
     *   @param labelProvider ILabelProvider
     */
    public void setTreeProviders(ITreeContentProvider contentProvider, ILabelProvider labelProvider) {
        this.fTreeViewer.setContentProvider(contentProvider);
        this.fTreeViewer.setLabelProvider(labelProvider);
    }

    /**
     *   Sets the sorter that is to be applied to self's tree viewer
     * @param sorter
     */
    public void setTreeComparator(ViewerComparator sorter) {
        this.fTreeViewer.setComparator(sorter);
    }

    /**
     *   Adjusts the collection of references to white-checked tree elements appropriately.
     *
     *   @param treeElement java.lang.Object
     *   @param isWhiteChecked boolean
     */
    protected void setWhiteChecked(Object treeElement, boolean isWhiteChecked) {
        if (isWhiteChecked) {
            if (!this.fWhiteCheckedTreeItems.contains(treeElement))
                this.fWhiteCheckedTreeItems.add(treeElement);
        } else
            this.fWhiteCheckedTreeItems.remove(treeElement);
    }

    /**
     *   Handle the collapsing of an element in a tree viewer
     * @param event
     */
    public void treeCollapsed(TreeExpansionEvent event) {
        // We don't need to do anything with this
    }

    /**
     *   Handles the expansionsion of an element in a tree viewer
     * @param event
     */
    public void treeExpanded(TreeExpansionEvent event) {

        Object item = event.getElement();

        // First see if the children need to be given their checked state at all.  If they've
        // already been realized then this won't be necessary
        if (!this.fExpandedTreeNodes.contains(item)) {
            this.fExpandedTreeNodes.add(item);
            checkNewTreeElements(getTreeChildren(item));
        }
    }

    /**
     *  Callback that's invoked when the checked status of an item in the tree
     *  is changed by the user.
     * @param treeElement
     * @param state
     */
    protected void treeItemChecked(Object treeElement, boolean state) {

        // recursively adjust all child tree elements appropriately
        setTreeChecked(treeElement, state);

        Object parent = this.fTreeContentProvider.getParent(treeElement);
        if (parent == null)
            return;

        // now update upwards in the tree hierarchy
        if (state)
            grayCheckHierarchy(parent);
        else
            ungrayCheckHierarchy(parent);

        updateHierarchy(treeElement);
    }

    /**
     *   Logically un-gray-check all ancestors of treeItem iff appropriate.
     * @param treeElement
     */
    protected void ungrayCheckHierarchy(Object treeElement) {
        if (!determineShouldBeAtLeastGrayChecked(treeElement))
            this.fCheckedStateStore.remove(treeElement);

        Object parent = this.fTreeContentProvider.getParent(treeElement);
        if (parent != null)
            ungrayCheckHierarchy(parent);
    }

    /**
     *   Sets the checked state of self and all ancestors appropriately
     * @param treeElement
     */
    protected void updateHierarchy(Object treeElement) {

        boolean whiteChecked = determineShouldBeWhiteChecked(treeElement);
        boolean shouldBeAtLeastGray = determineShouldBeAtLeastGrayChecked(treeElement);

        this.fTreeViewer.setChecked(treeElement, whiteChecked || shouldBeAtLeastGray);
        setWhiteChecked(treeElement, whiteChecked);
        if (whiteChecked)
            this.fTreeViewer.setGrayed(treeElement, false);
        else
            this.fTreeViewer.setGrayed(treeElement, shouldBeAtLeastGray);

        // proceed up the tree element hierarchy
        Object parent = this.fTreeContentProvider.getParent(treeElement);
        if (parent != null) {
            updateHierarchy(parent);
        }
    }

    /**
     * Update the selections of the tree elements in items to reflect the new
     * selections provided.
     *
     * @param items with keys of Object (the tree element) and values of List (the selected
     * list elements).
     */
    public void updateSelections(final Map items) {

        //Potentially long operation - show a busy cursor
        BusyIndicator.showWhile(this.fTreeViewer.getControl().getDisplay(), new Runnable() {
            public void run() {
                handleUpdateSelection(items);
            }
        });
    }

    /**
     * Returns the result of running the given elements through the filters.
     * @param filters
     *
     * @param elements the elements to filter
     * @return only the elements which all filters accept
     */
    protected Object[] filter(ViewerFilter[] filters, Object[] elements) {
        if (filters != null) {
            ArrayList filtered = new ArrayList(elements.length);
            for (Object element : elements) {
                boolean add = true;
                for (ViewerFilter filter : filters) {
                    add = filter.select(null, null, element);
                    if (!add)
                        break;
                }
                if (add)
                    filtered.add(element);
            }
            return filtered.toArray();
        }
        return elements;
    }

    private Object[] getTreeChildren(Object element) {
        return filter(this.fTreeViewer.getFilters(), this.fTreeContentProvider.getChildren(element));
    }

    private Object[] getListElements(Object element) {
        return filter(this.fListViewer.getFilters(), this.fListContentProvider.getElements(element));
    }

    public Set getWhiteCheckedTreeItems() {
        return new HashSet(this.fWhiteCheckedTreeItems);
    }

    private void handleUpdateSelection(Map items) {

        // VZ: use entry set instead of key / getKey
        //Update the store before the hierarchy to prevent updating parents before all of the children are done
        Set<Map.Entry> entrySet = items.entrySet();
        for (Map.Entry entry : entrySet) {

            //Replace the items in the checked state store with those from the supplied items
            List selections = (List) entry.getValue();
            if (selections.size() == 0)
                //If it is empty remove it from the list
                this.fCheckedStateStore.remove(entry.getKey());
            else {
                this.fCheckedStateStore.put(entry.getKey(), selections);
                // proceed up the tree element hierarchy
                Object parent = this.fTreeContentProvider.getParent(entry.getKey());
                if (parent != null) {
                    addToHierarchyToCheckedStore(parent);
                }
            }
        }

        // Now update hierarchies
        for (Map.Entry entry : entrySet) {
            updateHierarchy(entry.getKey());
            if (this.fCurrentTreeSelection != null && this.fCurrentTreeSelection.equals(entry.getKey())) {
                this.fListViewer.setAllChecked(false);
                this.fListViewer.setCheckedElements(((List) entry.getValue()).toArray());
            }
        }
        // VZ
    }

    /**
     * Checks if an element is grey checked.
     * @param object
     * @return if an element is grey checked.
     */
    public boolean isTreeItemGreyChecked(Object object) {
        return this.fTreeViewer.getGrayed(object);
    }

    /**
     * For a given element, expand its chidren to a level.
     * @param object
     * @param level
     */
    public void expandTreeToLevel(Object object, int level) {
        this.fTreeViewer.expandToLevel(object, level);
    }

    /**
     * @param selection
     */
    public void setTreeSelection(ISelection selection) {
        this.fTreeViewer.setSelection(selection);
    }

    /**
     * Refresh the viewers.
     */
    public void refresh() {
        if (this.fTreeViewer != null)
            this.fTreeViewer.refresh();
    }

    // VZ
    /**
     * Disposes the kept resources.
     */
    public void dispose() {

        if (this.fListLabelProvider != null)
            this.fListLabelProvider.dispose();

        if (this.fTreeLabelProvider != null)
            this.fTreeLabelProvider.dispose();
    }
    // VZ
}