### Eclipse Workspace Patch 1.0 #P org.eclipse.pde.ui Index: src/org/eclipse/pde/internal/ui/launcher/OSGiBundleBlock.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/launcher/OSGiBundleBlock.java,v retrieving revision 1.14 diff -u -r1.14 OSGiBundleBlock.java --- src/org/eclipse/pde/internal/ui/launcher/OSGiBundleBlock.java 12 Feb 2008 15:48:21 -0000 1.14 +++ src/org/eclipse/pde/internal/ui/launcher/OSGiBundleBlock.java 19 Feb 2008 02:44:56 -0000 @@ -32,8 +32,8 @@ public class OSGiBundleBlock extends AbstractPluginBlock { - private HashMap levelColumnCache = null; - private HashMap autoColumnCache = null; + private HashMap levelColumnCache = new HashMap(); + private HashMap autoColumnCache = new HashMap(); private TreeEditor levelColumnEditor = null; private TreeEditor autoColumnEditor = null; @@ -141,6 +141,7 @@ if (item.getChecked()) { item.setText(2, combo.getText()); fTab.updateLaunchConfigurationDialog(); + autoColumnCache.put(item.getData(), item.getText(2)); } } }); @@ -181,11 +182,13 @@ for (int i = 0; i < selected.length; i++) { if (selected[i] instanceof IPluginModelBase) { IPluginModelBase model = (IPluginModelBase) selected[i]; - TreeItem item = (TreeItem) fPluginTreeViewer.testFindItem(model); + //TreeItem item = (TreeItem) fPluginTreeViewer.testFindItem(model); if (model.getUnderlyingResource() == null) { - appendToBuffer(tBuffer, model, item); + //appendToBuffer(tBuffer, model, item); + appendToBuffer(tBuffer, model); } else { - appendToBuffer(wBuffer, model, item); + //appendToBuffer(wBuffer, model, item); + appendToBuffer(wBuffer, model); } } } @@ -196,18 +199,19 @@ if (fAddWorkspaceButton.getSelection()) { for (int i = 0; i < fWorkspaceModels.length; i++) { if (!fPluginTreeViewer.getChecked(fWorkspaceModels[i])) { - appendToBuffer(buffer, fWorkspaceModels[i], null); + appendToBuffer(buffer, fWorkspaceModels[i]); } } } config.setAttribute(IPDELauncherConstants.DESELECTED_WORKSPACE_PLUGINS, buffer.length() > 0 ? buffer.toString() : (String) null); } - private void appendToBuffer(StringBuffer buffer, IPluginModelBase model, TreeItem item) { + private void appendToBuffer(StringBuffer buffer, IPluginModelBase model) { if (buffer.length() > 0) - buffer.append(","); //$NON-NLS-1$ - String startLevel = item != null ? item.getText(1) : null; - String autoStart = item != null ? item.getText(2) : null; + buffer.append(","); //$NON-NLS-1$ + + String startLevel = levelColumnCache.get(model) != null ? levelColumnCache.get(model).toString() : null; + String autoStart = autoColumnCache.get(model) != null ? autoColumnCache.get(model).toString() : null; String value = BundleLauncherHelper.writeBundles(model, startLevel, autoStart); buffer.append(value); } @@ -237,6 +241,7 @@ } private void resetGroup(NamedElement group) { + /* Widget widget = fPluginTreeViewer.testFindItem(group); if (widget instanceof TreeItem) { TreeItem[] items = ((TreeItem) widget).getItems(); @@ -246,6 +251,19 @@ } } } + */ + Object[] children = group.getChildren(); + if (children == null) + return; + for (int i = 0; i < children.length; i++) { + Object child = children[i]; + if (child instanceof IPluginModelBase) { + if (fPluginTreeViewer.getChecked(child)) { + resetText((IPluginModelBase) child); + } + } + } + } private void initWorkspacePluginsState(ILaunchConfiguration configuration) throws CoreException { @@ -266,13 +284,27 @@ protected void handleGroupStateChanged(Object group, boolean checked) { super.handleGroupStateChanged(group, checked); - Widget item = fPluginTreeViewer.testFindItem(group); - if (item instanceof TreeItem) { - TreeItem[] items = ((TreeItem) item).getItems(); - for (int i = 0; i < items.length; i++) { - TreeItem child = items[i]; - if (child.getChecked() == (child.getText(1).length() == 0)) - resetText(items[i]); +// Widget item = fPluginTreeViewer.testFindItem(group); +// if (item instanceof TreeItem) { +// TreeItem[] items = ((TreeItem) item).getItems(); +// for (int i = 0; i < items.length; i++) { +// TreeItem child = items[i]; +// if (child.getChecked() == (child.getText(1).length() == 0)) +// resetText(items[i]); +// } +// } + if (group instanceof NamedElement) { + NamedElement namedElement = (NamedElement) group; + Object[] children = namedElement.getChildren(); + if (children == null) + return; + for (int i = 0; i < children.length; i++) { + Object child = children[i]; + if (child instanceof IPluginModelBase) { + if (fPluginTreeViewer.getChecked(child) == (((String) (levelColumnCache.get(child))).length() == 0)) { + resetText((IPluginModelBase) child); + } + } } } } @@ -294,6 +326,7 @@ } private void updateGroup(Object group) { + /* Widget item = fPluginTreeViewer.testFindItem(group); if (item instanceof TreeItem) { TreeItem[] items = ((TreeItem) item).getItems(); @@ -303,6 +336,23 @@ resetText(items[i]); } } + */ + if (group instanceof NamedElement) { + NamedElement namedElement = (NamedElement) group; + Object[] children = namedElement.getChildren(); + if (children == null) { + return; + } + for (int i = 0; i < children.length; i++) { + Object child = children[i]; + if (child instanceof IPluginModelBase) { + if (fPluginTreeViewer.getChecked(child) == (((String) (levelColumnCache.get(child))).length() == 0)) { + resetText((IPluginModelBase) child); + } + } + + } + } } private void setText(IPluginModelBase model, String value) { @@ -310,15 +360,57 @@ if (widget instanceof TreeItem) { TreeItem item = (TreeItem) widget; int index = value == null ? -1 : value.indexOf(':'); - item.setText(1, index == -1 ? "" : value.substring(0, index)); //$NON-NLS-1$ + String levelValue = index == -1 ? "" : value.substring(0, index); //$NON-NLS-1$ + String autoValue = null; + item.setText(1, levelValue); if (model.isFragmentModel()) { - item.setText(2, "false"); //$NON-NLS-1$ + autoValue = "false"; //$NON-NLS-1$ + item.setText(2, autoValue); } else { - item.setText(2, index == -1 ? "" : value.substring(index + 1)); //$NON-NLS-1$ + autoValue = index == -1 ? "" : value.substring(index + 1); //$NON-NLS-1$ + item.setText(2, autoValue); + } + levelColumnCache.put(model, levelValue); + autoColumnCache.put(model, autoValue); + } + } + + private void resetText(IPluginModelBase model) { + String levelText = null; + String autoText = null; + Widget widget = fPluginTreeViewer.testFindItem(model); + if (fPluginTreeViewer.getChecked(model)) { + boolean isSystemBundle = "org.eclipse.osgi".equals(model.getPluginBase().getId()); //$NON-NLS-1$ + if (!"default".equals(levelColumnCache.get(model))) //$NON-NLS-1$ + levelText = isSystemBundle ? "" : "default"; //$NON-NLS-1$ //$NON-NLS-2$ + if (!"default".equals(autoColumnCache.get(model))) //$NON-NLS-1$ + autoText = isSystemBundle ? "" : "default"; //$NON-NLS-1$ //$NON-NLS-2$ + } else { + if (((String) levelColumnCache.get(model)).length() > 0) { + levelText = ""; //$NON-NLS-1$ + } + if (((String) autoColumnCache.get(model)).length() > 0) { + autoText = ""; //$NON-NLS-1$ + } + } + if (model.isFragmentModel()) { + autoText = "false"; //$NON-NLS-1$ + } + if (levelText != null) { + levelColumnCache.put(model, levelText); + if (widget instanceof TreeItem) { + ((TreeItem) widget).setText(1, levelText); + } + } + if (autoText != null) { + autoColumnCache.put(model, autoText); + if (widget instanceof TreeItem) { + ((TreeItem) widget).setText(2, autoText); } } } + /* private void resetText(IPluginModelBase model) { Widget widget = fPluginTreeViewer.testFindItem(model); if (widget instanceof TreeItem) { @@ -344,6 +436,7 @@ item.setText(2, ""); //$NON-NLS-1$ } } + */ protected void handleRestoreDefaults() { Object[] selected = fPluginTreeViewer.getCheckedElements(); @@ -384,33 +477,33 @@ autoColumnEditor.getEditor().dispose(); } - // Cache the current text - levelColumnCache = new HashMap(); - autoColumnCache = new HashMap(); - ArrayList allTreeItems = getAllTreeItems(treeView.getTree().getItems()); - for (Iterator iterator = allTreeItems.iterator(); iterator.hasNext();) { - TreeItem item = (TreeItem) iterator.next(); - levelColumnCache.put(item.getData(), item.getText(1)); - autoColumnCache.put(item.getData(), item.getText(2)); - } - } - - /** - * This gets all the tree items from a tree. - * - * This method must exist in some SWT util library, so it can probably be - * removed when I find it. - * - * @param roots - */ - private ArrayList getAllTreeItems(TreeItem[] roots) { - ArrayList list = new ArrayList(); - for (int i = 0; i < roots.length; i++) { - TreeItem item = roots[i]; - list.add(item); - list.addAll(getAllTreeItems(item.getItems())); - } - return list; - } +// // Cache the current text +// levelColumnCache = new HashMap(); +// autoColumnCache = new HashMap(); +// ArrayList allTreeItems = getAllTreeItems(treeView.getTree().getItems()); +// for (Iterator iterator = allTreeItems.iterator(); iterator.hasNext();) { +// TreeItem item = (TreeItem) iterator.next(); +// levelColumnCache.put(item.getData(), item.getText(1)); +// autoColumnCache.put(item.getData(), item.getText(2)); +// } + } + +// /** +// * This gets all the tree items from a tree. +// * +// * This method must exist in some SWT util library, so it can probably be +// * removed when I find it. +// * +// * @param roots +// */ +// private ArrayList getAllTreeItems(TreeItem[] roots) { +// ArrayList list = new ArrayList(); +// for (int i = 0; i < roots.length; i++) { +// TreeItem item = roots[i]; +// list.add(item); +// list.addAll(getAllTreeItems(item.getItems())); +// } +// return list; +// } } Index: src/org/eclipse/pde/internal/ui/launcher/AbstractPluginBlock.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/launcher/AbstractPluginBlock.java,v retrieving revision 1.28 diff -u -r1.28 AbstractPluginBlock.java --- src/org/eclipse/pde/internal/ui/launcher/AbstractPluginBlock.java 16 Jan 2008 17:08:31 -0000 1.28 +++ src/org/eclipse/pde/internal/ui/launcher/AbstractPluginBlock.java 19 Feb 2008 02:44:56 -0000 @@ -27,6 +27,8 @@ import org.eclipse.pde.internal.ui.*; import org.eclipse.pde.internal.ui.elements.DefaultContentProvider; import org.eclipse.pde.internal.ui.elements.NamedElement; +import org.eclipse.pde.internal.ui.launcher.FilteredCheckboxTree.FilterableCheckboxTreeViewer; +import org.eclipse.pde.internal.ui.launcher.FilteredCheckboxTree.PreRefreshNotifier; import org.eclipse.pde.internal.ui.util.PersistablePluginObject; import org.eclipse.pde.internal.ui.util.SWTUtil; import org.eclipse.pde.internal.ui.wizards.ListUtil; @@ -42,11 +44,13 @@ import org.eclipse.swt.widgets.*; import org.eclipse.ui.*; import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog; +import org.eclipse.ui.dialogs.PatternFilter; public abstract class AbstractPluginBlock { protected AbstractLauncherTab fTab; + private FilteredCheckboxTree fPluginFilteredTree; protected CheckboxTreeViewer fPluginTreeViewer; protected NamedElement fWorkspacePlugins; protected NamedElement fExternalPlugins; @@ -249,7 +253,17 @@ } protected void createPluginViewer(Composite composite, int span, int indent) { - fPluginTreeViewer = new CheckboxTreeViewer(composite, getTreeViewerStyle()); + + //fPluginTreeViewer = new CheckboxTreeViewer(composite, getTreeViewerStyle()); + fPluginFilteredTree = new FilteredCheckboxTree(composite, getTreeViewerStyle(), new PatternFilter()); + fPluginTreeViewer = (CheckboxTreeViewer) fPluginFilteredTree.getViewer(); + ((FilterableCheckboxTreeViewer) fPluginTreeViewer).addPerRefreshNotifier(new PreRefreshNotifier() { + public void preRefresh(FilterableCheckboxTreeViewer viewer) { + refreshTreeView(fPluginTreeViewer); + + } + }); + fPluginTreeViewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { @@ -299,13 +313,16 @@ GridData gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = span; gd.horizontalIndent = indent; - fPluginTreeViewer.getTree().setLayoutData(gd); + fPluginFilteredTree.setLayoutData(gd); Image siteImage = PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_SITE_OBJ); fWorkspacePlugins = new NamedElement(PDEUIMessages.AdvancedLauncherTab_workspacePlugins, siteImage); fExternalPlugins = new NamedElement(PDEUIMessages.PluginsTab_target, siteImage); + fWorkspacePlugins.setChildren(fWorkspaceModels); + fExternalPlugins.setChildren(fExternalModels); + fPluginTreeViewer.addFilter(new Filter()); } @@ -395,7 +412,6 @@ } protected void handleFilterButton() { - refreshTreeView(fPluginTreeViewer); fPluginTreeViewer.refresh(); fPluginTreeViewer.expandAll(); } @@ -548,6 +564,7 @@ public void enableViewer(boolean enable) { fPluginTreeViewer.getTree().setEnabled(enable); + fPluginFilteredTree.getFilterControl().setEnabled(enable); fAddRequiredButton.setEnabled(enable); fDefaultsButton.setEnabled(enable); fWorkingSetButton.setEnabled(enable); Index: src/org/eclipse/pde/internal/ui/elements/NamedElement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/elements/NamedElement.java,v retrieving revision 1.7 diff -u -r1.7 NamedElement.java --- src/org/eclipse/pde/internal/ui/elements/NamedElement.java 3 May 2006 13:31:06 -0000 1.7 +++ src/org/eclipse/pde/internal/ui/elements/NamedElement.java 19 Feb 2008 02:44:56 -0000 @@ -18,6 +18,8 @@ private String name; private IPDEElement parent; + + private Object[] children; public NamedElement(String name) { this(name, null, null); @@ -33,6 +35,21 @@ this.parent = parent; } + /** + * Sets the children of this element. The children are not copied + * @param children + */ + public void setChildren(Object[] children) { + this.children = children; + } + + /** + * Gets the children of this element. The children are not copied + */ + public Object[] getChildren() { + return children; + } + public Image getImage() { return image; } Index: src/org/eclipse/pde/internal/ui/launcher/FilteredCheckboxTree.java =================================================================== RCS file: src/org/eclipse/pde/internal/ui/launcher/FilteredCheckboxTree.java diff -N src/org/eclipse/pde/internal/ui/launcher/FilteredCheckboxTree.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/pde/internal/ui/launcher/FilteredCheckboxTree.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,352 @@ +/******************************************************************************* + * 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: + * Ian Bull - initial API and implementation (Bug #207064) + *******************************************************************************/ +package org.eclipse.pde.internal.ui.launcher; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.swt.widgets.Widget; +import org.eclipse.ui.dialogs.FilteredTree; +import org.eclipse.ui.dialogs.PatternFilter; + +/** + * A FilteredChecboxTree. This tree stores all the tree elements internally, and keeps the + * check state in sync. This way, even if an element is filtered, the caller can get and set the + * checked state. + * + * The internal representation is additive. That is, elements are never removed from the internal + * representation. This is OK since the PDE launch Dialog never changes the elements once + * the view is opened. If any other tree is based on this code, they may want to address this issue. + * + * This is not public because it was customized for the Launch Dialog. + * + * @author Ian Bull + */ +class FilteredCheckboxTree extends FilteredTree { + + /** + * The FilteredCheckboxTree Constructor. + * @param parent The parent composite where this Tree will be placed. + * @param treeStyle Tree styles + * @param filter The pattern filter that wil be used to filter elements + */ + public FilteredCheckboxTree(Composite parent, int treeStyle, PatternFilter filter) { + super(parent, treeStyle, filter); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.dialogs.FilteredTree#doCreateTreeViewer(org.eclipse.swt.widgets.Composite, int) + */ + protected TreeViewer doCreateTreeViewer(Composite parent, int style) { + return new FilterableCheckboxTreeViewer(parent, style); + } + + /** + * Classes which implement this interface deal with notifications from the + * filtered checkbox tree viewer. The notifications are fired before a refresh + * happens. + */ + interface PreRefreshNotifier { + public void preRefresh(FilterableCheckboxTreeViewer viewer); + } + + /** + * A CheckboxTreeViewer that maintains an internal representation of all the nodes. + * + */ + class FilterableCheckboxTreeViewer extends CheckboxTreeViewer { + static final String NONE = "none"; + static final String CHECKED = "checked"; + static final String GREYED = "greyed"; + static final String CHECKED_GREYED = "checked_greyed"; + + /** + * The internal node for the FilterableCheckboxTreeViewer + */ + class FilteredCheckboxTreeItem { + Object data; // Data element + String state; // Checked State + List children = new ArrayList(); + public FilteredCheckboxTreeItem(Object data, String state, Map itemCache, FilteredCheckboxTreeItem parent) { + this.data = data; + this.state = state; + itemCache.put(data, this); + if ( parent != null ) { + parent.children.add(this); + } + } + } + + /* A cache of all the nodes */ + Map itemCache = new HashMap(); + + /* The preRefresh Listeners */ + List refreshingListeners = new ArrayList(); + + /** + * FilterableCheckboxTreeViewer constructor. This creates the tree part of the filtered tree. + */ + public FilterableCheckboxTreeViewer(Composite parent, int style) { + super(parent, style); + addCheckStateListener(new ICheckStateListener() { + + public void checkStateChanged(CheckStateChangedEvent event) { + FilteredCheckboxTreeItem item = (FilteredCheckboxTreeItem) itemCache.get(event.getElement()); + if ( item != null ) { + item.state = event.getChecked() ? CHECKED : NONE; + } + } + }); + } + + + /** + * Allows clients to listen to the tree refresh. + */ + public void addPerRefreshNotifier(PreRefreshNotifier notifier) { + if (refreshingListeners.contains(notifier))return; + refreshingListeners.add(notifier); + } + + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.CheckboxTreeViewer#getChecked(java.lang.Object) + */ + public boolean getChecked(Object element) { + Widget testFindItem = getViewer().testFindItem(element); + testFindItem = null; + if ( testFindItem == null ) { + if ( itemCache.containsKey(element)) { + FilteredCheckboxTreeItem item = (FilteredCheckboxTreeItem) itemCache.get(element); + if ( item.state.equals(CHECKED)) return true; + if ( item.state.equals(CHECKED_GREYED )) return true; + if ( item.state.equals(GREYED)) return true; + else if ( item.state.equals(NONE)) return false; + } + } + return super.getChecked(element); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.CheckboxTreeViewer#getCheckedElements() + */ + public Object[] getCheckedElements() { + Iterator iterator = itemCache.values().iterator(); + List checkedElements = new LinkedList(); + while(iterator.hasNext()) { + FilteredCheckboxTreeItem item = (FilteredCheckboxTreeItem) iterator.next(); + Widget testFindItem = getViewer().testFindItem(item.data); + testFindItem = null; + if ( testFindItem == null ) { + if ( item.state.equals(CHECKED) || item.state.equals(CHECKED_GREYED) || item.state.equals(GREYED)) { + checkedElements.add(item.data); + } + } + else { + if (((TreeItem)testFindItem).getChecked()) { + checkedElements.add(testFindItem.getData()); + } + } + } + return checkedElements.toArray(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.CheckboxTreeViewer#setChecked(java.lang.Object, boolean) + */ + public boolean setChecked(Object element, boolean state) { + if ( itemCache.containsKey(element) ) { + FilteredCheckboxTreeItem item = (FilteredCheckboxTreeItem) itemCache.get(element); + item.state = state ? CHECKED : NONE; + } + return super.setChecked(element, state); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.CheckboxTreeViewer#setCheckedElements(java.lang.Object[]) + */ + public void setCheckedElements(Object[] elements) { + Set s = new HashSet(itemCache.keySet()); + s.removeAll(new HashSet(Arrays.asList(elements))); + for (int i = 0; i < elements.length; i++) { + FilteredCheckboxTreeItem item = (FilteredCheckboxTreeItem) itemCache.get(elements[i]); + if ( item != null ) { + item.state = CHECKED; + } + } + for (Iterator iterator = s.iterator(); iterator.hasNext();) { + Object object = iterator.next(); + FilteredCheckboxTreeItem item = (FilteredCheckboxTreeItem) itemCache.get(object); + if ( item != null ) { + item.state = NONE; + } + } + super.setCheckedElements(elements); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.CheckboxTreeViewer#setSubtreeChecked(java.lang.Object, boolean) + */ + public boolean setSubtreeChecked(Object element, boolean state) { + String newState = state ? CHECKED : NONE; + FilteredCheckboxTreeItem filteredCheckboxTreeItem = (FilteredCheckboxTreeItem) itemCache.get(element); + if ( filteredCheckboxTreeItem != null ) { + filteredCheckboxTreeItem.state = newState; + List children = filteredCheckboxTreeItem.children; + for (Iterator iterator = children.iterator(); iterator.hasNext();) { + FilteredCheckboxTreeItem child = (FilteredCheckboxTreeItem) iterator.next(); + child.state = newState; + } + } + return super.setSubtreeChecked(element, state); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.CheckboxTreeViewer#preservingSelection(java.lang.Runnable) + */ + protected void preservingSelection(Runnable updateCode) { + super.preservingSelection(updateCode); + + // Re-apply the checked state + ArrayList allTreeItems = getAllTreeItems(treeViewer.getTree().getItems()); + for (Iterator iterator = allTreeItems.iterator(); iterator.hasNext();) { + TreeItem item = (TreeItem) iterator.next(); + doApplyCheckedState(item, item.getData()); + } + } + + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.AbstractTreeViewer#internalRefresh(java.lang.Object, boolean) + */ + protected void internalRefresh(Object element, boolean updateLabels) { + // Notify anybody who is listening for the refresh + for (Iterator iterator = refreshingListeners.iterator(); iterator.hasNext();) { + PreRefreshNotifier notifier = (PreRefreshNotifier) iterator.next(); + notifier.preRefresh(FilterableCheckboxTreeViewer.this); + } + saveCheckedState(); + super.internalRefresh(element, updateLabels); + treeViewer.expandAll(); + } + + + /* + * Set the checked state + */ + private void doApplyCheckedState(Item item, Object element) { + // update the item first + super.doUpdateItem(item, element); + + // Update the checked state + TreeItem treeItem = (TreeItem) item; + if (itemCache.containsKey(element)) { + String state = ((FilteredCheckboxTreeItem)itemCache.get(element)).state; + if (state.equals(CHECKED_GREYED)) { + treeItem.setGrayed(true); + treeItem.setChecked(true); + } else if (state.equals(CHECKED)) { + treeItem.setChecked(true); + treeItem.setGrayed(false); + } else if (state.equals(GREYED)) { + treeItem.setGrayed(true); + treeItem.setChecked(false); + } else { + treeItem.setGrayed(false); + treeItem.setChecked(false); + } + } + } + + /* + * A helper method to get all the items in the tree + */ + private ArrayList getAllTreeItems(TreeItem[] roots) { + ArrayList list = new ArrayList(); + for (int i = 0; i < roots.length; i++) { + TreeItem item = roots[i]; + list.add(item); + list.addAll(getAllTreeItems(item.getItems())); + } + return list; + } + + /** + * Saves the checked state of all the elements in the tree + */ + private void saveCheckedState() { + TreeItem[] items = treeViewer.getTree().getItems(); + for (int i = 0; i < items.length; i++) { + TreeItem item = items[i]; + if (!itemCache.containsKey(item.getData())) { + new FilteredCheckboxTreeItem(item.getData(), getItemState(item), itemCache, null); + } + FilteredCheckboxTreeItem filteredCheckboxTreeItem = (FilteredCheckboxTreeItem) itemCache.get(item.getData()); + filteredCheckboxTreeItem.state = getItemState(item); + saveCheckedState(filteredCheckboxTreeItem, item); + } + } + + /** + * Saves the checked state of an item and all its children + */ + private void saveCheckedState(FilteredCheckboxTreeItem parent, TreeItem parentItem) { + TreeItem[] items = parentItem.getItems(); + for (int i = 0; i < items.length; i++) { + TreeItem item = items[i]; + if (!itemCache.containsKey(item.getData())) { + new FilteredCheckboxTreeItem(item.getData(), getItemState(item), itemCache, parent); + } + FilteredCheckboxTreeItem filteredCheckboxTreeItem = (FilteredCheckboxTreeItem) itemCache.get(item.getData()); + filteredCheckboxTreeItem.state = getItemState(item); + saveCheckedState(filteredCheckboxTreeItem, item); + } + } + + /** + * Computes the checked state from a tree item + */ + private String getItemState(TreeItem item) { + if (item.getChecked() && item.getGrayed()) { + return CHECKED_GREYED; + } else if (item.getChecked()) { + return CHECKED; + } else if (item.getGrayed()) { + return GREYED; + } else { + return NONE; + } + } + + } // end of FilterableCheckboxTreeViewer + +}