/*******************************************************************************
 * 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
 *     Gunnar Wagenknecht - fix for bug 21756 [PropertiesView] property view sorting
 *******************************************************************************/

package org.eclipse.ui.views.properties;

import java.util.ArrayList;
import java.util.Arrays;
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.core.runtime.ListenerList;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellEditorListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TreeEditor;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TreeEvent;
import org.eclipse.swt.events.TreeListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.internal.views.properties.PropertiesMessages;

/**
 * The PropertySheetViewer displays the properties of objects. The model for the
 * viewer consists of a hierarchy of <code>IPropertySheetEntry</code>.
 * <p>
 * This viewer also supports the optional catogorization of the first level
 * <code>IPropertySheetEntry</code> s by using instances of
 * <code>PropertySheetCategory</code>.
 *  
 */
/* package */
class PropertySheetViewer extends Viewer {
    // The input objects for the viewer
    private Object[] input;

    // The root entry of the viewer
    private IPropertySheetEntry rootEntry;

    // The current categories
    private PropertySheetCategory[] categories;

    // SWT widgets
    private Tree tree;

    /**
     * Maintain a map from the PropertySheet entry to its
     * corresponding TreeItem. This is used in 'findItem' to
     * greatly increase the performance.
     */
    private HashMap entryToItemMap = new HashMap();
    
    private TreeEditor treeEditor;

    private static String[] columnLabels = {
            PropertiesMessages.PropertyViewer_property, PropertiesMessages.PropertyViewer_value };

    private static String MISCELLANEOUS_CATEGORY_NAME = PropertiesMessages.PropertyViewer_misc;

    // Cell editor support.
    private int columnToEdit = 1;

    private CellEditor cellEditor;

    private IPropertySheetEntryListener entryListener;

    private ICellEditorListener editorListener;

    // Flag to indicate if categories (if any) should be shown
    private boolean isShowingCategories = true;

    // Flag to indicate expert properties should be shown
    private boolean isShowingExpertProperties = false;

    // The status line manager for showing messages
    private IStatusLineManager statusLineManager;

    // Cell editor activation listeners
    private ListenerList activationListeners = new ListenerList();
    
    // the property sheet sorter
    private PropertySheetSorter sorter = new PropertySheetSorter();

    /**
     * Creates a property sheet viewer on a newly-created tree control
     * under the given parent. The viewer has no input, and no root entry.
     * 
     * @param parent
     *            the parent control
     */
    public PropertySheetViewer(Composite parent) {
        tree = new Tree(parent, SWT.FULL_SELECTION | SWT.SINGLE
                | SWT.HIDE_SELECTION);

        // configure the widget
        tree.setLinesVisible(true);
        tree.setHeaderVisible(true);

        // configure the columns
        addColumns();

        // add our listeners to the widget
        hookControl();

        // create a new tree editor
        treeEditor = new TreeEditor(tree);

        // create the entry and editor listener
        createEntryListener();
        createEditorListener();
    }

    /**
     * Activate a cell editor for the given selected tree item.
     * 
     * @param item
     *            the selected tree item
     */
    private void activateCellEditor(TreeItem item) {
        // ensure the cell editor is visible
        tree.showSelection();

        // Get the entry for this item
        IPropertySheetEntry activeEntry = (IPropertySheetEntry) item.getData();

        // Get the cell editor for the entry.
        // Note that the editor parent must be the Tree control
        cellEditor = activeEntry.getEditor(tree);

        if (cellEditor == null) {
			// unable to create the editor
            return;
		}

        // activate the cell editor
        cellEditor.activate();

        // if the cell editor has no control we can stop now
        Control control = cellEditor.getControl();
        if (control == null) {
            cellEditor.deactivate();
            cellEditor = null;
            return;
        }

        // add our editor listener
        cellEditor.addListener(editorListener);

        // set the layout of the tree editor to match the cell editor
        CellEditor.LayoutData layout = cellEditor.getLayoutData();
        treeEditor.horizontalAlignment = layout.horizontalAlignment;
        treeEditor.grabHorizontal = layout.grabHorizontal;
        treeEditor.minimumWidth = layout.minimumWidth;
        treeEditor.setEditor(control, item, columnToEdit);

        // set the error text from the cel editor
        setErrorMessage(cellEditor.getErrorMessage());

        // give focus to the cell editor
        cellEditor.setFocus();

        // notify of activation
        fireCellEditorActivated(cellEditor);
    }

    /**
     * Adds a cell editor activation listener. Has no effect if an identical
     * activation listener is already registered.
     * 
     * @param listener
     *            a cell editor activation listener
     */
    /* package */
    void addActivationListener(ICellEditorActivationListener listener) {
        activationListeners.add(listener);
    }

    /**
     * Add columns to the tree and set up the layout manager accordingly.
     */
    private void addColumns() {

        // create the columns
        TreeColumn[] columns = tree.getColumns();
        for (int i = 0; i < columnLabels.length; i++) {
            String string = columnLabels[i];
            if (string != null) {
                TreeColumn column;
                if (i < columns.length) {
					column = columns[i];
				} else {
					column = new TreeColumn(tree, 0);
				}
                column.setText(string);
            }
        }

        tree.addControlListener(new ControlAdapter() {
            public void controlResized(ControlEvent e) {
                Rectangle area = tree.getClientArea();
                TreeColumn[] columns = tree.getColumns();
                if (area.width > 0) {
                    columns[0].setWidth(area.width * 40 / 100);
                    columns[1].setWidth(area.width - columns[0].getWidth() - 4);
                    tree.removeControlListener(this);
                }
            }
        });

    }

    /**
     * Asks the entry currently being edited to apply its current cell editor
     * value.
     */
    private void applyEditorValue() {
        TreeItem treeItem = treeEditor.getItem();
        // treeItem can be null when view is opened
        if (treeItem == null || treeItem.isDisposed()) {
			return;
		}
        IPropertySheetEntry entry = (IPropertySheetEntry) treeItem.getData();
        entry.applyEditorValue();
    }

    /**
     * Creates the child items for the given widget (item or tree). This
     * method is called when the item is expanded for the first time or when an
     * item is assigned as the root of the tree.
     * @param widget TreeItem or Tree to create the children in.
     */
    private void createChildren(Widget widget) {
        // get the current child items
        TreeItem[] childItems = getChildItems(widget);

        if (childItems.length > 0) {
            Object data = childItems[0].getData();
            if (data != null) {
				// children already there!
                return;
			}
            // remove the dummy
            childItems[0].dispose();
        }

        // get the children and create their tree items
        Object node = widget.getData();
        List children = getChildren(node);
        if (children.isEmpty()) {
			// this item does't actually have any children
            return;
		}
        for (int i = 0; i < children.size(); i++) {
            // create a new tree item
            createItem(children.get(i), widget, i);
        }
    }

    /**
     * Creates a new cell editor listener.
     */
    private void createEditorListener() {
        editorListener = new ICellEditorListener() {
            public void cancelEditor() {
                deactivateCellEditor();
            }

            public void editorValueChanged(boolean oldValidState,
                    boolean newValidState) {
                //Do nothing
            }

            public void applyEditorValue() {
                //Do nothing
            }
        };
    }

    /**
     * Creates a new property sheet entry listener.
     */
    private void createEntryListener() {
        entryListener = new IPropertySheetEntryListener() {
            public void childEntriesChanged(IPropertySheetEntry entry) {
                // update the children of the given entry
                if (entry == rootEntry) {
					updateChildrenOf(entry, tree);
				} else {
                    TreeItem item = findItem(entry);
                    if (item != null) {
						updateChildrenOf(entry, item);
					}
                }
            }

            public void valueChanged(IPropertySheetEntry entry) {
                // update the given entry
                TreeItem item = findItem(entry);
                if (item != null) {
					updateEntry(entry, item);
				}
            }

            public void errorMessageChanged(IPropertySheetEntry entry) {
                // update the error message
                setErrorMessage(entry.getErrorText());
            }
        };
    }

    /**
     * Creates a new tree item, sets the given entry or category (node)in
     * its user data field, and adds a listener to the node if it is an entry.
     * 
     * @param node
     *            the entry or category associated with this item
     * @param parent
     *            the parent widget
     * @param index
     *            indicates the position to insert the item into its parent
     */
    private void createItem(Object node, Widget parent, int index) {
        // create the item
        TreeItem item;
        if (parent instanceof TreeItem) {
			item = new TreeItem((TreeItem) parent, SWT.NONE, index);
		} else {
			item = new TreeItem((Tree) parent, SWT.NONE, index);
		}

        // set the user data field
        item.setData(node);
        
        // Cache the entry <-> tree item relationship 
        entryToItemMap.put(node, item);
        
        // Always ensure that if the tree item goes away that it's
        // removed from the cache
        item.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				Object possibleEntry = e.widget.getData();
				if (possibleEntry != null)
					entryToItemMap.remove(possibleEntry);
			}
        });        

        // add our listener
        if (node instanceof IPropertySheetEntry) {
			((IPropertySheetEntry) node)
                    .addPropertySheetEntryListener(entryListener);
		}

        // update the visual presentation
        if (node instanceof IPropertySheetEntry) {
			updateEntry((IPropertySheetEntry) node, item);
		} else {
			updateCategory((PropertySheetCategory) node, item);
		}
    }

    /**
     * Deactivate the currently active cell editor.
     */
    /* package */
    void deactivateCellEditor() {
        treeEditor.setEditor(null, null, columnToEdit);
        if (cellEditor != null) {
            cellEditor.deactivate();
            fireCellEditorDeactivated(cellEditor);
            cellEditor.removeListener(editorListener);
            cellEditor = null;
        }
        // clear any error message from the editor
        setErrorMessage(null);
    }

    /**
     * Sends out a selection changed event for the entry tree to all registered
     * listeners.
     */
    private void entrySelectionChanged() {
        SelectionChangedEvent changeEvent = new SelectionChangedEvent(this,
                getSelection());
        fireSelectionChanged(changeEvent);
    }

    /**
     * Return a tree item in the property sheet that has the same entry in
     * its user data field as the supplied entry. Return <code>null</code> if
     * there is no such item.
     * 
     * @param entry
     *            the entry to serach for
     * @return the TreeItem for the entry or <code>null</code> if
     * there isn't one.
     */
    private TreeItem findItem(IPropertySheetEntry entry) {
        // Iterate through treeItems to find item
        TreeItem[] items = tree.getItems();
        for (int i = 0; i < items.length; i++) {
            TreeItem item = items[i];
            TreeItem findItem = findItem(entry, item);
            if (findItem != null) {
				return findItem;
			}
        }
        return null;
    }

    /**
     * Return a tree item in the property sheet that has the same entry in
     * its user data field as the supplied entry. Return <code>null</code> if
     * there is no such item.
     * 
     * @param entry
     *            the entry to search for
     * @param item
     *            the item look in
     * @return the TreeItem for the entry or <code>null</code> if
     * there isn't one.
     */
    private TreeItem findItem(IPropertySheetEntry entry, TreeItem item) {
    	// If we can find the TreeItem in the cache, just return it
    	Object mapItem = entryToItemMap.get(entry);
    	if (mapItem != null && mapItem instanceof TreeItem)
    		return (TreeItem) mapItem;
    	
        // compare with current item
        if (entry == item.getData()) {
			return item;
		}

        // recurse over children
        TreeItem[] items = item.getItems();
        for (int i = 0; i < items.length; i++) {
            TreeItem childItem = items[i];
            TreeItem findItem = findItem(entry, childItem);
            if (findItem != null) {
				return findItem;
			}
        }
        return null;
    }

    /**
     * Notifies all registered cell editor activation listeners of a cell editor
     * activation.
     * 
     * @param activatedCellEditor
     *            the activated cell editor
     */
    private void fireCellEditorActivated(CellEditor activatedCellEditor) {
        Object[] listeners = activationListeners.getListeners();
        for (int i = 0; i < listeners.length; ++i) {
            ((ICellEditorActivationListener) listeners[i])
                    .cellEditorActivated(activatedCellEditor);
        }
    }

    /**
     * Notifies all registered cell editor activation listeners of a cell editor
     * deactivation.
     * 
     * @param activatedCellEditor
     *            the deactivated cell editor
     */
    private void fireCellEditorDeactivated(CellEditor activatedCellEditor) {
        Object[] listeners = activationListeners.getListeners();
        for (int i = 0; i < listeners.length; ++i) {
            ((ICellEditorActivationListener) listeners[i])
                    .cellEditorDeactivated(activatedCellEditor);
        }
    }

    /**
     * Returns the active cell editor of this property sheet viewer or
     * <code>null</code> if no cell editor is active.
     * 
     * @return the active cell editor
     */
    public CellEditor getActiveCellEditor() {
        return cellEditor;
    }

    private TreeItem[] getChildItems(Widget widget) {
        if (widget instanceof Tree) {
            return ((Tree) widget).getItems();
        }
        else if (widget instanceof TreeItem) {
            return ((TreeItem) widget).getItems();
        }
        // shouldn't happen
        return new TreeItem[0];
    }
    
    /**
     * Returns the sorted children of the given category or entry
     *
     * @param node a category or entry
     * @return the children of the given category or entry
     *  (element type <code>IPropertySheetEntry</code> or 
     *  <code>PropertySheetCategory</code>)
     */
    private List getChildren(Object node) {
        // cast the entry or category
        IPropertySheetEntry entry = null;
        PropertySheetCategory category = null;
        if (node instanceof IPropertySheetEntry) {
			entry = (IPropertySheetEntry) node;
		} else {
			category = (PropertySheetCategory) node;
		}

        // get the child entries or categories
        List children;
        if (category == null) {
			children = getChildren(entry);
		} else {
			children = getChildren(category);
		}

        return children;
    }

    /**
     * Returns the child entries of the given entry
     * @param entry The entry to search
     * 
     * @return the children of the given entry (element type
     *         <code>IPropertySheetEntry</code>)
     */
    private List getChildren(IPropertySheetEntry entry) {
        // if the entry is the root and we are showing categories, and we have
        // more than the
        // defualt category, return the categories
        if (entry == rootEntry && isShowingCategories) {
            if (categories.length > 1
                    || (categories.length == 1 && !categories[0]
                            .getCategoryName().equals(
                                    MISCELLANEOUS_CATEGORY_NAME))) {
				return Arrays.asList(categories);
			}
        }

        // return the sorted & filtered child entries
        return getSortedEntries(getFilteredEntries(entry.getChildEntries()));
    }

    /**
     * Returns the child entries of the given category
     * 
     * @param category The category to search
     * 
     * @return the children of the given category (element type
     *         <code>IPropertySheetEntry</code>)
     */
    private List getChildren(PropertySheetCategory category) {
        return getSortedEntries(getFilteredEntries(category.getChildEntries()));
    }

    /*
     * (non-Javadoc) Method declared on Viewer.
     */
    public Control getControl() {
        return tree;
    }

    /**
     * Returns the entries which match the current filter.
     *
     * @param entries the entries to filter
     * @return the entries which match the current filter
     *  (element type <code>IPropertySheetEntry</code>)
     */
    private List getFilteredEntries(IPropertySheetEntry[] entries) {
        // if no filter just return all entries
        if (isShowingExpertProperties) {
			return Arrays.asList(entries);
		}

        // check each entry for the filter
        List filteredEntries = new ArrayList(entries.length);
        for (int i = 0; i < entries.length; i++) {
            IPropertySheetEntry entry = entries[i];
            if (entry != null) {
                String[] filters = entry.getFilters();
                boolean expert = false;
                if (filters != null) {
                    for (int j = 0; j < filters.length; j++) {
                        if (filters[j].equals(IPropertySheetEntry.FILTER_ID_EXPERT)) {
                            expert = true;
                            break;
                        }
                    }
                }
                if (!expert) {
					filteredEntries.add(entry);
				}
            }
        }
        return filteredEntries;
    }
    
    /**
	 * Returns a sorted list of <code>IPropertySheetEntry</code> entries.
	 * 
	 * @param unsortedEntries
	 *            unsorted list of <code>IPropertySheetEntry</code>
	 * @return a sorted list of the specified entries
	 */
	private List getSortedEntries(List unsortedEntries) {
		IPropertySheetEntry[] propertySheetEntries = (IPropertySheetEntry[]) unsortedEntries
				.toArray(new IPropertySheetEntry[unsortedEntries.size()]);
		sorter.sort(propertySheetEntries);
		return Arrays.asList(propertySheetEntries);
	}
    

    /**
	 * The <code>PropertySheetViewer</code> implementation of this method
	 * declared on <code>IInputProvider</code> returns the objects for which
	 * the viewer is currently showing properties. It returns an
	 * <code>Object[]</code> or <code>null</code>.
	 */
    public Object getInput() {
        return input;
    }

    /**
     * Returns the root entry for this property sheet viewer. The root entry is
     * not visible in the viewer.
     * 
     * @return the root entry or <code>null</code>.
     */
    public IPropertySheetEntry getRootEntry() {
        return rootEntry;
    }

    /**
     * The <code>PropertySheetViewer</code> implementation of this
     * <code>ISelectionProvider</code> method returns the result as a
     * <code>StructuredSelection</code>.
     * <p>
     * Note that this method only includes <code>IPropertySheetEntry</code> in
     * the selection (no categories).
     * </p>
     */
    public ISelection getSelection() {
        if (tree.getSelectionCount() == 0) {
			return StructuredSelection.EMPTY;
		}
        TreeItem[] sel = tree.getSelection();
        List entries = new ArrayList(sel.length);
        for (int i = 0; i < sel.length; i++) {
            TreeItem ti = sel[i];
            Object data = ti.getData();
            if (data instanceof IPropertySheetEntry) {
				entries.add(data);
			}
        }
        return new StructuredSelection(entries);
    }

    /**
     * Selection in the viewer occurred. Check if there is an active cell
     * editor. If yes, deactivate it and check if a new cell editor must be
     * activated.
     * 
     * @param selection
     *            the TreeItem that is selected
     */
    private void handleSelect(TreeItem selection) {
        // deactivate the current cell editor
        if (cellEditor != null) {
            applyEditorValue();
            deactivateCellEditor();
        }

        // get the new selection
        TreeItem[] sel = new TreeItem[] { selection };
        if (sel.length == 0) {
            setMessage(null);
            setErrorMessage(null);
        } else {
            Object object = sel[0].getData(); // assume single selection
            if (object instanceof IPropertySheetEntry) {
                // get the entry for this item
                IPropertySheetEntry activeEntry = (IPropertySheetEntry) object;

                // display the description for the item
                setMessage(activeEntry.getDescription());

                // activate a cell editor on the selection
                activateCellEditor(sel[0]);
            }
        }
        entrySelectionChanged();
    }

    /**
     * The expand icon for a node in this viewer has been selected to collapse a
     * subtree. Deactivate the cell editor
     * 
     * @param event
     *            the SWT tree event
     */
    private void handleTreeCollapse(TreeEvent event) {
        if (cellEditor != null) {
            applyEditorValue();
            deactivateCellEditor();
        }
    }

    /**
     * The expand icon for a node in this viewer has been selected to expand the
     * subtree. Create the children 1 level deep.
     * <p>
     * Note that we use a "dummy" item (no user data) to show a "+" icon beside
     * an item which has children before the item is expanded now that it is
     * being expanded we have to create the real child items
     * </p>
     * 
     * @param event
     *            the SWT tree event
     */
    private void handleTreeExpand(TreeEvent event) {
        createChildren(event.item);
    }

    /**
     * Hides the categories.
     */
    /* package */
    void hideCategories() {
        isShowingCategories = false;
        categories = null;
        refresh();
    }

    /**
     * Hides the expert properties.
     */
    /* package */
    void hideExpert() {
        isShowingExpertProperties = false;
        refresh();
    }

    /**
     * Establish this viewer as a listener on the control
     */
    private void hookControl() {
        // Handle selections in the Tree
        // Part1: Double click only (allow traversal via keyboard without
        // activation
        tree.addSelectionListener(new SelectionAdapter() {
            /* (non-Javadoc)
             * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
             */
            public void widgetSelected(SelectionEvent e) {
            	// The viewer only owns the status line when there is
            	// no 'active' cell editor
            	if (cellEditor == null || !cellEditor.isActivated()) {
					updateStatusLine(e.item);
				}
			}

			/* (non-Javadoc)
			 * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
			 */
			public void widgetDefaultSelected(SelectionEvent e) {
                handleSelect((TreeItem) e.item);
            }
        });
        // Part2: handle single click activation of cell editor
        tree.addMouseListener(new MouseAdapter() {
            public void mouseDown(MouseEvent event) {
                // only activate if there is a cell editor
                Point pt = new Point(event.x, event.y);
                TreeItem item = tree.getItem(pt);
                if (item != null) {
                    handleSelect(item);
                }
            }
        });

        // Add a tree listener to expand and collapse which
        // allows for lazy creation of children
        tree.addTreeListener(new TreeListener() {
            public void treeExpanded(final TreeEvent event) {
                handleTreeExpand(event);
            }

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

        // Refresh the tree when F5 pressed
        tree.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent e) {
                if (e.character == SWT.ESC) {
					deactivateCellEditor();
				} else if (e.keyCode == SWT.F5) {
					// The following will simulate a reselect
                    setInput(getInput());
				}
            }
        });
    }

    /**
     * Update the status line based on the data of item.
     * @param item
     */
    protected void updateStatusLine(Widget item) {
    	setMessage(null);
    	setErrorMessage(null);
    	
    	// Update the status line
    	if (item != null) {
    		if (item.getData() instanceof PropertySheetEntry) {
    			PropertySheetEntry psEntry = (PropertySheetEntry) item.getData();
    			
    			// For entries, show the description if any, else show the label
    			String desc = psEntry.getDescription();
    			if (desc != null && desc.length() > 0) {
					setMessage(psEntry.getDescription());
				} else {
					setMessage(psEntry.getDisplayName());
				}
    		}
    			
    		else if (item.getData() instanceof PropertySheetCategory) {
    			PropertySheetCategory psCat = (PropertySheetCategory) item.getData();
    			setMessage(psCat.getCategoryName());
    		}
    	}
	}

    /**
     * Updates all of the items in the tree.
     * <p>
     * Note that this means ensuring that the tree items reflect the state of
     * the model (entry tree) it does not mean telling the model to update
     * itself.
     * </p>
     */
    public void refresh() {
        if (rootEntry != null) {
            updateChildrenOf(rootEntry, tree);
        }
    }

    /**
     * Removes the given cell editor activation listener from this viewer. Has
     * no effect if an identical activation listener is not registered.
     * 
     * @param listener
     *            a cell editor activation listener
     */
    /* package */
    void removeActivationListener(ICellEditorActivationListener listener) {
        activationListeners.remove(listener);
    }

    /**
     * Remove the given item from the tree. Remove our listener if the
     * item's user data is a an entry then set the user data to null
     * 
     * @param item
     *            the item to remove
     */
    private void removeItem(TreeItem item) {
        Object data = item.getData();
        if (data instanceof IPropertySheetEntry) {
			((IPropertySheetEntry) data)
                    .removePropertySheetEntryListener(entryListener);
		}
        item.setData(null);
        
        // We explicitly remove the entry from the map since it's data has been null'd
        entryToItemMap.remove(data);

        item.dispose();
    }

    /**
     * Reset the selected properties to their default values.
     */
    public void resetProperties() {
        // Determine the selection
        IStructuredSelection selection = (IStructuredSelection) getSelection();

        // Iterate over entries and reset them
        Iterator itr = selection.iterator();
        while (itr.hasNext()) {
			((IPropertySheetEntry) itr.next()).resetPropertyValue();
		}
    }

    /**
     * Sets the error message to be displayed in the status line.
     * 
     * @param errorMessage
     *            the message to be displayed, or <code>null</code>
     */
    private void setErrorMessage(String errorMessage) {
        // show the error message
        if (statusLineManager != null) {
			statusLineManager.setErrorMessage(errorMessage);
		}
    }

    /**
     * The <code>PropertySheetViewer</code> implementation of this method
     * declared on <code>Viewer</code> method sets the objects for which the
     * viewer is currently showing properties.
     * <p>
     * The input must be an <code>Object[]</code> or <code>null</code>.
     * </p>
     * 
     * @param newInput
     *            the input of this viewer, or <code>null</code> if none
     */
    public void setInput(Object newInput) {
        // need to save any changed value when user clicks elsewhere
        applyEditorValue();
        // deactivate our cell editor
        deactivateCellEditor();

        // set the new input to the root entry
        input = (Object[]) newInput;
        if (input == null) {
			input = new Object[0];
		}

        if (rootEntry != null) {
            rootEntry.setValues(input);
            // ensure first level children are visible
            updateChildrenOf(rootEntry, tree);
        }
        
        // Clear any previous StatusLine messages
    	updateStatusLine(null);
    }

    /**
     * Sets the message to be displayed in the status line. This message is
     * displayed when there is no error message.
     * 
     * @param message
     *            the message to be displayed, or <code>null</code>
     */
    private void setMessage(String message) {
        // show the message
        if (statusLineManager != null) {
			statusLineManager.setMessage(message);
		}
    }

    /**
     * Sets the root entry for this property sheet viewer. The root entry is not
     * visible in the viewer.
     * 
     * @param root
     *            the root entry
     */
    public void setRootEntry(IPropertySheetEntry root) {
        // If we have a root entry, remove our entry listener
        if (rootEntry != null) {
			rootEntry.removePropertySheetEntryListener(entryListener);
		}

        rootEntry = root;

        // Set the root as user data on the tree
        tree.setData(rootEntry);

        // Add an IPropertySheetEntryListener to listen for entry change
        // notifications
        rootEntry.addPropertySheetEntryListener(entryListener);

        // Pass our input to the root, this will trigger entry change
        // callbacks to update this viewer
        setInput(input);
    }

    /*
     *  (non-Javadoc)
     * @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection, boolean)
     */
    public void setSelection(ISelection selection, boolean reveal) {
        //Do nothing by default
    }

    /**
	 * Sets the sorter for this viewer.
	 * <p>
	 * The default sorter sorts categories and entries alphabetically. 
	 * A viewer update needs to be triggered after the sorter has changed.
	 * </p>
	 * @param sorter the sorter to set (<code>null</code> will reset to the
	 * default sorter)
     * @since 3.1
	 */
	public void setSorter(PropertySheetSorter sorter) {
		if (null == sorter) {
			sorter = new PropertySheetSorter();
		}
		this.sorter = sorter;
	}

    /**
     * Sets the status line manager this view will use to show messages.
     * 
     * @param manager
     *            the status line manager
     */
    public void setStatusLineManager(IStatusLineManager manager) {
        statusLineManager = manager;
    }

    /**
     * Shows the categories.
     */
    /* package */
    void showCategories() {
        isShowingCategories = true;
        refresh();
    }

    /**
     * Shows the expert properties.
     */
    /* package */
    void showExpert() {
        isShowingExpertProperties = true;
        refresh();
    }

    /**
     * Updates the categories. Reuses old categories if possible.
     */
    private void updateCategories() {
        // lazy initialize
        if (categories == null) {
			categories = new PropertySheetCategory[0];
		}

        // get all the filtered child entries of the root
        List childEntries = getFilteredEntries(rootEntry.getChildEntries());

        // if the list is empty, just set an empty categories array
        if (childEntries.size() == 0) {
            categories = new PropertySheetCategory[0];
            return;
        }

        // cache old categories by their descriptor name
        Map categoryCache = new HashMap(categories.length * 2 + 1);
        for (int i = 0; i < categories.length; i++) {
            categories[i].removeAllEntries();
            categoryCache.put(categories[i].getCategoryName(), categories[i]);
        }

        // create a list of categories to get rid of
        List categoriesToRemove = new ArrayList(Arrays.asList(categories));

        // Determine the categories
        PropertySheetCategory misc = (PropertySheetCategory) categoryCache
                .get(MISCELLANEOUS_CATEGORY_NAME);
        if (misc == null) {
			misc = new PropertySheetCategory(MISCELLANEOUS_CATEGORY_NAME);
		}
        boolean addMisc = false;

        for (int i = 0; i < childEntries.size(); i++) {
            IPropertySheetEntry childEntry = (IPropertySheetEntry) childEntries
                    .get(i);
            String categoryName = childEntry.getCategory();
            if (categoryName == null) {
                misc.addEntry(childEntry);
                addMisc = true;
                categoriesToRemove.remove(misc);
            } else {
                PropertySheetCategory category = (PropertySheetCategory) categoryCache
                        .get(categoryName);
                if (category == null) {
                    category = new PropertySheetCategory(categoryName);
                    categoryCache.put(categoryName, category);
                } else {
                    categoriesToRemove.remove(category);
                }
                category.addEntry(childEntry);
            }
        }

        // Add the PSE_MISC category if it has entries
        if (addMisc) {
			categoryCache.put(MISCELLANEOUS_CATEGORY_NAME, misc);
		}
        
        // Sort the categories.
        // Rather than just sorting categoryCache.values(), we'd like the original order to be preserved
        // (with misc added at the end, if needed) before passing to the sorter.
        ArrayList categoryList = new ArrayList();
        Set seen = new HashSet(childEntries.size());
        for (int i = 0; i < childEntries.size(); i++) {
            IPropertySheetEntry childEntry = (IPropertySheetEntry) childEntries
                    .get(i);
            String categoryName = childEntry.getCategory();
            if (categoryName != null && !seen.contains(categoryName)) {
                seen.add(categoryName);
                PropertySheetCategory category = (PropertySheetCategory) categoryCache
                        .get(categoryName);
                if (category != null) { 
                    categoryList.add(category);
                }
            }
        }
        if (addMisc && !seen.contains(MISCELLANEOUS_CATEGORY_NAME)) {
            categoryList.add(misc);
        }
        
        PropertySheetCategory[] categoryArray = (PropertySheetCategory[]) categoryList
        	.toArray(new PropertySheetCategory[categoryList.size()]);
        sorter.sort(categoryArray);
        categories = categoryArray;
    }

    /**
     * Update the category (but not its parent or children).
     * 
     * @param category
     *            the category to update
     * @param item
     *            the tree item for the given entry
     */
    private void updateCategory(PropertySheetCategory category,
            TreeItem item) {
        // ensure that backpointer is correct
        item.setData(category);
        
        // Update the map accordingly
        entryToItemMap.put(category, item);

        // Update the name and value columns
        item.setText(0, category.getCategoryName());
        item.setText(1, ""); //$NON-NLS-1$

        // update the "+" icon
        if (category.getAutoExpand()) {
            // we auto expand categories when they first appear
            createChildren(item);
            item.setExpanded(true);
            category.setAutoExpand(false);
        } else {
            // we do not want to auto expand categories if the user has
            // collpased them
            updatePlus(category, item);
        }
    }

    /**
     * Update the child entries or categories of the given entry or category. If
     * the given node is the root entry and we are showing categories then the
     * child entries are categories, otherwise they are entries.
     * 
     * @param node
     *            the entry or category whose children we will update
     * @param widget
     *            the widget for the given entry, either a
     *            <code>TableTree</code> if the node is the root node or a
     *            <code>TreeItem</code> otherwise.
     */
    private void updateChildrenOf(Object node, Widget widget) {
        // cast the entry or category
        IPropertySheetEntry entry = null;
        PropertySheetCategory category = null;
        if (node instanceof IPropertySheetEntry) {
			entry = (IPropertySheetEntry) node;
		} else {
			category = (PropertySheetCategory) node;
		}

        // get the current child tree items
        TreeItem[] childItems = getChildItems(widget);

        // optimization! prune collapsed subtrees
        TreeItem item = null;
        if (widget instanceof TreeItem) {
            item = (TreeItem) widget;
        }
        if (item != null && !item.getExpanded()) {
            // remove all children
            for (int i = 0; i < childItems.length; i++) {
                if (childItems[i].getData() != null) {
                    removeItem(childItems[i]);
                }
            }

            // append a dummy if necessary
            if (category != null || entry.hasChildEntries()) {
                // may already have a dummy
                // It is either a category (which always has at least one child)
                // or an entry with chidren.
                // Note that this test is not perfect, if we have filtering on
                // then there in fact may be no entires to show when the user
                // presses the "+" expand icon. But this is an acceptable
                // compromise.
                childItems = getChildItems(widget);
                if (childItems.length == 0) {
                    new TreeItem(item, SWT.NULL);
                }
            }
            return;
        }

        // get the child entries or categories
        if (node == rootEntry && isShowingCategories) {
			// update the categories
            updateCategories();
		}
        List children = getChildren(node);

        // remove items
        Set set = new HashSet(childItems.length * 2 + 1);

        for (int i = 0; i < childItems.length; i++) {
            Object data = childItems[i].getData();
            if (data != null) {
                Object e = data;
                int ix = children.indexOf(e);
                if (ix < 0) { // not found
                    removeItem(childItems[i]);
                } else { // found
                    set.add(e);
                }
            } else if (data == null) { // the dummy
                childItems[i].dispose();
            }
        }

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

        // add new items
        int newSize = children.size();
        for (int i = 0; i < newSize; i++) {
            Object el = children.get(i);
            if (!set.contains(el)) {
				createItem(el, widget, i);
			}
        }

        // WORKAROUND
        if (widget == tree && oldCnt == 0 && tree.getItemCount() == 1) {
            tree.setRedraw(false);
            tree.setRedraw(true);
        }

        // get the child tree items after our changes
        childItems = getChildItems(widget);

        // update the child items
        // This ensures that the children are in the correct order
        // are showing the correct values.
        for (int i = 0; i < newSize; i++) {
            Object el = children.get(i);
            if (el instanceof IPropertySheetEntry) {
				updateEntry((IPropertySheetEntry) el, childItems[i]);
			} else {
                updateCategory((PropertySheetCategory) el, childItems[i]);
                updateChildrenOf(el, childItems[i]);
            }
        }
        // The tree's original selection may no longer apply after the update,
        // so fire the selection changed event.
        entrySelectionChanged();
    }

    /**
     * Update the given entry (but not its children or parent)
     * 
     * @param entry
     *            the entry we will update
     * @param item
     *            the tree item for the given entry
     */
    private void updateEntry(IPropertySheetEntry entry, TreeItem item) {
        // ensure that backpointer is correct
        item.setData(entry);
        
        // update the map accordingly
        entryToItemMap.put(entry, item);

        // update the name and value columns
        item.setText(0, entry.getDisplayName());
        item.setText(1, entry.getValueAsString());
        Image image = entry.getImage();
        if (item.getImage(1) != image) {
			item.setImage(1, image);
		}

        // update the "+" icon
        updatePlus(entry, item);
    }

    /**
     * Updates the "+"/"-" icon of the tree item from the given entry
     * or category.
     *
     * @param node the entry or category
     * @param item the tree item being updated
     */
    private void updatePlus(Object node, TreeItem item) {
        // cast the entry or category
        IPropertySheetEntry entry = null;
        PropertySheetCategory category = null;
        if (node instanceof IPropertySheetEntry) {
			entry = (IPropertySheetEntry) node;
		} else {
			category = (PropertySheetCategory) node;
		}

        boolean hasPlus = item.getItemCount() > 0;
        boolean needsPlus = category != null || entry.hasChildEntries();
        boolean removeAll = false;
        boolean addDummy = false;

        if (hasPlus != needsPlus) {
            if (needsPlus) {
                addDummy = true;
            } else {
                removeAll = true;
            }
        }
        if (removeAll) {
            // remove all children
            TreeItem[] items = item.getItems();
            for (int i = 0; i < items.length; i++) {
                removeItem(items[i]);
            }
        }

        if (addDummy) {
            new TreeItem(item, SWT.NULL); // append a dummy to create the
            // plus sign
        }
    }
}
