### Eclipse Workspace Patch 1.0 #P org.eclipse.jface Index: src/org/eclipse/jface/viewers/CheckboxTableViewer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface/src/org/eclipse/jface/viewers/CheckboxTableViewer.java,v retrieving revision 1.23 diff -u -r1.23 CheckboxTableViewer.java --- src/org/eclipse/jface/viewers/CheckboxTableViewer.java 27 May 2008 18:24:04 -0000 1.23 +++ src/org/eclipse/jface/viewers/CheckboxTableViewer.java 12 Nov 2008 19:53:33 -0000 @@ -13,8 +13,8 @@ import java.util.ArrayList; import java.util.List; -import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; @@ -27,6 +27,9 @@ /** * A concrete viewer based on an SWT Table * control with checkboxes on each node. + *

This class supports setting an {@link ICheckStateProvider} to + * set the checkbox states. To see standard SWT behavior, view + * SWT Snippet274.

*

* This class is not intended to be subclassed outside the viewer framework. * It is designed to be instantiated with a pre-existing SWT table control and configured @@ -41,6 +44,11 @@ * List of check state listeners (element type: ICheckStateListener). */ private ListenerList checkStateListeners = new ListenerList(); + + /** + * Provides the desired state of the check boxes. + */ + private ICheckStateProvider checkStateProvider; /** * Creates a table viewer on a newly-created table control under the given parent. @@ -139,8 +147,34 @@ public void addCheckStateListener(ICheckStateListener listener) { checkStateListeners.add(listener); } - + /** + * Sets the {@link ICheckStateProvider} for this {@link CheckboxTreeViewer}. + * The check state provider will supply the logic for deciding whether the + * check box associated with each item should be checked, grayed or + * unchecked. + * @param checkStateProvider The provider. + * @since 3.5 + */ + public void setCheckStateProvider(ICheckStateProvider checkStateProvider) { + this.checkStateProvider = checkStateProvider; + refresh(); + } + + /* + * Extends this method to update check box states. + */ + protected void doUpdateItem(Widget widget, Object element, boolean fullMap) { + super.doUpdateItem(widget, element, fullMap); + if(!widget.isDisposed()) { + if(checkStateProvider != null) { + setChecked(element, checkStateProvider.isChecked(element)); + setGrayed(element, checkStateProvider.isGrayed(element)); + } + } + } + + /** * Creates a new table control with one column. * * @param parent the parent control @@ -275,7 +309,16 @@ * Method declared on Viewer. */ protected void preservingSelection(Runnable updateCode) { - + //If a check provider is present, it determines the state across input + //changes. + if(checkStateProvider != null) { + //Try to preserve the selection, let the ICheckProvider manage + //the check states + super.preservingSelection(updateCode); + return; + } + + //Preserve checked items TableItem[] children = getTable().getItems(); CustomHashtable checked = newHashtable(children.length * 2 + 1); CustomHashtable grayed = newHashtable(children.length * 2 + 1); Index: src/org/eclipse/jface/viewers/CheckboxTreeViewer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface/src/org/eclipse/jface/viewers/CheckboxTreeViewer.java,v retrieving revision 1.26 diff -u -r1.26 CheckboxTreeViewer.java --- src/org/eclipse/jface/viewers/CheckboxTreeViewer.java 27 May 2008 18:24:04 -0000 1.26 +++ src/org/eclipse/jface/viewers/CheckboxTreeViewer.java 12 Nov 2008 19:53:33 -0000 @@ -13,8 +13,8 @@ import java.util.ArrayList; import java.util.List; -import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; @@ -28,6 +28,9 @@ /** * A concrete tree-structured viewer based on an SWT Tree * control with checkboxes on each node. + *

This class supports setting an {@link ICheckStateProvider} to + * set the checkbox states. To see standard SWT behavior, view + * SWT Snippet274.

*

* This class is not intended to be subclassed outside the viewer framework. * It is designed to be instantiated with a pre-existing SWT tree control and configured @@ -42,6 +45,11 @@ * List of check state listeners (element type: ICheckStateListener). */ private ListenerList checkStateListeners = new ListenerList(); + + /** + * Provides the desired state of the check boxes. + */ + private ICheckStateProvider checkStateProvider; /** * Last item clicked on, or null if none. @@ -91,8 +99,32 @@ public void addCheckStateListener(ICheckStateListener listener) { checkStateListeners.add(listener); } - + /** + * Sets the {@link ICheckStateProvider} for this {@link CheckboxTreeViewer}. + * The check state provider will supply the logic for deciding whether the + * check box associated with each item should be checked, grayed or + * unchecked. + * @param checkStateProvider The provider. + * @since 3.5 + */ + public void setCheckStateProvider(ICheckStateProvider checkStateProvider) { + this.checkStateProvider = checkStateProvider; + refresh(); + } + + /* + * Extends this method to update check box states. + */ + protected void doUpdateItem(Item item, Object element) { + super.doUpdateItem(item, element); + if(!item.isDisposed() && checkStateProvider != null) { + setChecked(element, checkStateProvider.isChecked(element)); + setGrayed(element, checkStateProvider.isGrayed(element)); + } + } + + /** * Applies the checked and grayed states of the given widget and its * descendents. * @@ -362,7 +394,16 @@ * Method declared on Viewer. */ protected void preservingSelection(Runnable updateCode) { - + //If a check provider is present, it determines the state across input + //changes. + if(checkStateProvider != null) { + //Try to preserve the selection, let the ICheckProvider manage + //the check states + super.preservingSelection(updateCode); + return; + } + + //Preserve checked items int n = getItemCount(getControl()); CustomHashtable checkedNodes = newHashtable(n * 2 + 1); CustomHashtable grayedNodes = newHashtable(n * 2 + 1); Index: src/org/eclipse/jface/viewers/ICheckStateProvider.java =================================================================== RCS file: src/org/eclipse/jface/viewers/ICheckStateProvider.java diff -N src/org/eclipse/jface/viewers/ICheckStateProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jface/viewers/ICheckStateProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 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 org.eclipse.jface.viewers; + +/** + * Interface to provide checked and grayed state information about data in trees + * or tables. The following chart determines the checkbox state: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
+ * + * isGrayed()
+ * + * falsetrue
isChecked()falseunchecked
truecheckedgrayed
+ * @since 3.5 + */ +public interface ICheckStateProvider { + + /** + * Indicates if an element's representation should appear as checked or + * gray instead of unchecked. If this method returns true + * the {@link ICheckStateProvider#isGrayed(Object)} method will determine + * whether the check box displays a check mark ("checked") or a box + * ("grayed"). + * @param element + * @return true if the element should be checked or grayed, false if it + * should be unchecked + */ + public boolean isChecked(Object element); + + /** + * Indicates whether the check box associated with an element, when checked + * as indicated by the {@link ICheckStateProvider#isChecked(Object)} method, + * should display the gray (boxed) state instead of the check mark. + * @param element + * @return true if the element should be gray + */ + public boolean isGrayed(Object element); +} #P org.eclipse.ui.tests Index: Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckboxTreeViewerTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.tests/Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckboxTreeViewerTest.java,v retrieving revision 1.10 diff -u -r1.10 CheckboxTreeViewerTest.java --- Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckboxTreeViewerTest.java 16 Mar 2007 18:00:00 -0000 1.10 +++ Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckboxTreeViewerTest.java 12 Nov 2008 19:53:34 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2006, 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 @@ -10,11 +10,20 @@ *******************************************************************************/ package org.eclipse.jface.tests.viewers; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.tests.viewers.CheckStateProviderTestsUtil.TestCheckStateProvider; +import org.eclipse.jface.tests.viewers.CheckStateProviderTestsUtil.TestMethodsInvokedCheckStateProvider; import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ICheckStateProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TreeItem; public class CheckboxTreeViewerTest extends TreeViewerTest { public static class CheckboxTableTestLabelProvider extends @@ -105,4 +114,221 @@ assertTrue(elements[2] == firstfirstfirst); ctv.setParentsGrayed(firstfirstfirst, false); } + + public void testWithoutCheckProvider() { + //Check that without a provider, no exceptions are thrown + CheckboxTreeViewer ctv = (CheckboxTreeViewer)fViewer; + ctv.expandAll(); + ctv.refresh(); + } + + public void testCheckProviderInvoked() { + //Check that a refresh successfully causes the provider's + //setChecked and setGrayed methods to be invoked. + CheckboxTreeViewer ctv = (CheckboxTreeViewer)fViewer; + + TestMethodsInvokedCheckStateProvider provider = new TestMethodsInvokedCheckStateProvider(); + + ctv.setCheckStateProvider(provider); + assertTrue("isChecked should be invoked on a refresh", (!provider.isCheckedInvokedOn.isEmpty())); + assertTrue("isGrayed should be invoked on a refresh", (!provider.isGrayedInvokedOn.isEmpty())); + + provider.reset(); + ctv.refresh(); + assertTrue("isChecked should be invoked on a refresh", (!provider.isCheckedInvokedOn.isEmpty())); + assertTrue("isGrayed should be invoked on a refresh", (!provider.isGrayedInvokedOn.isEmpty())); + + } + + public void testCheckProviderLazilyInvoked() { + //Check that a refresh successfully causes the provider's + //setChecked and setGrayed methods to be invoked. + CheckboxTreeViewer ctv = (CheckboxTreeViewer)fViewer; + + TestMethodsInvokedCheckStateProvider provider = new TestMethodsInvokedCheckStateProvider(); + + ctv.setCheckStateProvider(provider); + ctv.refresh(); + + TestElement[] expected = fRootElement.getChildren(); + + for (Iterator i = provider.isCheckedInvokedOn.iterator(); i.hasNext();) { + TestElement element = (TestElement) i.next(); + boolean firstLevelElement = false; + for (int j = 0; j < expected.length && !firstLevelElement; j++) { + firstLevelElement = element.equals(expected[j]); + } + assertTrue("The check provider should only be invoked with visible elements", firstLevelElement); + } + + for (Iterator i = provider.isGrayedInvokedOn.iterator(); i.hasNext();) { + TestElement element = (TestElement) i.next(); + boolean firstLevelElement = false; + for (int j = 0; j < expected.length && !firstLevelElement; j++) { + firstLevelElement = element.equals(expected[j]); + } + assertTrue("The check provider should only be invoked with visible elements", firstLevelElement); + } + } + + public void testCheckedFalseGrayedFalse() { + testSpecificState(false, false); + } + + public void testCheckedFalseGrayedTrue() { + testSpecificState(false, true); + } + + public void testCheckedTrueGrayedFalse() { + testSpecificState(true, false); + } + + public void testCheckedTrueGrayedTrue() { + testSpecificState(true, true); + } + + private void testSpecificState(final boolean isChecked, final boolean isGrayed) { + CheckboxTreeViewer ctv = (CheckboxTreeViewer)fViewer; + + ctv.setCheckStateProvider(new ICheckStateProvider() { + public boolean isChecked(Object element) { return isChecked; } + public boolean isGrayed(Object element) { return isGrayed; } + }); + + TreeItem item = ctv.getTree().getItem(0); + + assertEquals(item.getChecked(), isChecked); + assertEquals(item.getGrayed(), isGrayed); + } + + public void testSetCheckProviderRefreshesItems() { + CheckboxTreeViewer ctv = (CheckboxTreeViewer) fViewer; + + //First provider + //Should cause visible items' check state adhere to provider + ctv.setCheckStateProvider(new TestCheckStateProvider(0)); + + ctv.expandAll(); + + //Check that all states are properly set + checkAllStates("Testing checkbox state after refresh", ctv, 0); + + //Remove the check state provider + ctv.setCheckStateProvider(null); + + //Test that an update doesn't fail + TestElement update = fRootElement.getFirstChild().getChildAt(5); + ctv.update(update, null); + + //Test that a refresh doesn't fail + ctv.refresh(); + } + + public void testCheckProviderWithSorter() { + CheckboxTreeViewer ctv = (CheckboxTreeViewer) fViewer; + + ctv.setSorter(new CheckStateProviderTestsUtil.Sorter()); + + //First provider + //Should cause visible items' check state adhere to provider + ctv.setCheckStateProvider(new TestCheckStateProvider(0)); + ctv.expandAll(); + + //Check that all states are properly set + checkAllStates("Testing checkbox state with a sorter", ctv, 0); + } + + public void testCheckProviderWithFilter() { + CheckboxTreeViewer ctv = (CheckboxTreeViewer) fViewer; + + final CheckStateProviderTestsUtil.Filter filter = new CheckStateProviderTestsUtil.Filter(); + ctv.addFilter(filter); + + //First provider + //Should cause visible items' check state adhere to provider + final TestCheckStateProvider checkStateProvider = new TestCheckStateProvider(0); + ctv.setCheckStateProvider(checkStateProvider); + ctv.expandAll(); + + //Check that all states are properly set + checkAllStates("Testing checkbox state with a sorter", ctv, 0); + + //Check that the provider is only invoked on elements which pass the filter + for (Iterator i = checkStateProvider.isCheckedInvokedOn.iterator(); i.hasNext();) { + TestElement element = (TestElement) i.next(); + assertTrue("The check provider should not be invoked on elements which did not get through the filter", filter.select(ctv, null, element)); + } + + for (Iterator i = checkStateProvider.isGrayedInvokedOn.iterator(); i.hasNext();) { + TestElement element = (TestElement) i.next(); + assertTrue("The check provider should not be invoked on elements which did not get through the filter", filter.select(ctv, null, element)); + } + } + + public void testSetNewCheckProvider() { + CheckboxTreeViewer ctv = (CheckboxTreeViewer) fViewer; + + //First provider + //Should cause visible items' check state to adhere to provider + ctv.setCheckStateProvider(new TestCheckStateProvider(0)); + ctv.expandAll(); + + checkAllStates("Testing checkbox state after first refresh", ctv, 0); + + //Put in a new check state provider + ctv.setCheckStateProvider(new TestCheckStateProvider(1)); + + //Check that setting a new check provider caused a refresh, + //and thus all the items have their new appropriate check + //states. + checkAllStates("Testing checkbox state after setting new check provider", ctv, 1); + } + + private void collectElementsInBranch(TreeItem item, Collection treeItems, Collection testElements) { + treeItems.add(item); + testElements.add(item.getData()); + TreeItem[] children = item.getItems(); + for (int i = 0; i < children.length; i++) { + collectElementsInBranch(children[i], treeItems, testElements); + } + } + + private void checkAllStates(String comment, CheckboxTreeViewer ctv, int shift) { + List items = new ArrayList(); + List elements = new ArrayList(); + collectElementsInBranch(ctv.getTree().getItem(0), items, elements); + + //Check that actual states were set properly + for (Iterator i = items.iterator(), j = elements.iterator(); i.hasNext();) { + TreeItem item = (TreeItem)i.next(); + TestElement element = (TestElement)j.next(); + + checkState(comment, element, item, shift); //check in Tree + checkState(comment, element, ctv, shift); //check in Viewer + } + } + + /** + * Invokes the appropriate asserts to verify the state + * of a TestElement. + * @param te + * @param viewer the viewer te is in. + * @param shift the shift parameter being used + */ + private void checkState(String comment, TestElement te, CheckboxTreeViewer viewer, int shift) { + assertEquals(comment, CheckStateProviderTestsUtil.shouldBeChecked(te, shift), viewer.getChecked(te)); + assertEquals(comment, CheckStateProviderTestsUtil.shouldBeGrayed(te, shift), viewer.getGrayed(te)); + } + + /** + * Invokes the appropriate asserts to verify the state + * of a TestElement's associated TreeItem + * @param te + * @param item the item representing te + * @param shift the shift parameter being used + */ + private void checkState(String comment, TestElement te, TreeItem item, int shift) { + assertEquals("Wrong checkstate: " + comment, CheckStateProviderTestsUtil.shouldBeChecked(te, shift), item.getChecked()); + assertEquals("Wrong checkstate: " + comment, CheckStateProviderTestsUtil.shouldBeGrayed(te, shift), item.getGrayed()); + } } Index: Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckboxTableViewerTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.tests/Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckboxTableViewerTest.java,v retrieving revision 1.8 diff -u -r1.8 CheckboxTableViewerTest.java --- Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckboxTableViewerTest.java 16 Mar 2007 18:00:00 -0000 1.8 +++ Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckboxTableViewerTest.java 12 Nov 2008 19:53:34 -0000 @@ -10,9 +10,14 @@ *******************************************************************************/ package org.eclipse.jface.tests.viewers; +import java.util.Iterator; + +import org.eclipse.jface.tests.viewers.CheckStateProviderTestsUtil.TestCheckStateProvider; +import org.eclipse.jface.tests.viewers.CheckStateProviderTestsUtil.TestMethodsInvokedCheckStateProvider; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ColumnLayoutData; import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ICheckStateProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TableLayout; @@ -22,6 +27,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; public class CheckboxTableViewerTest extends TableViewerTest { public static class CheckboxTableTestLabelProvider extends @@ -142,4 +148,172 @@ ctv.setAllGrayed(false); } + + public void testWithoutCheckProvider() { + //Check that without a provider, no exceptions are thrown + CheckboxTableViewer ctv = (CheckboxTableViewer)fViewer; + ctv.refresh(); + } + + public void testCheckProviderInvoked() { + //Check that a refresh successfully causes the provider's + //setChecked and setGrayed methods to be invoked. + CheckboxTableViewer ctv = (CheckboxTableViewer)fViewer; + + TestMethodsInvokedCheckStateProvider provider = new TestMethodsInvokedCheckStateProvider(); + + ctv.setCheckStateProvider(provider); + assertTrue("isChecked should be invoked on a refresh", (!provider.isCheckedInvokedOn.isEmpty())); + assertTrue("isGrayed should be invoked on a refresh", (!provider.isGrayedInvokedOn.isEmpty())); + + provider.reset(); + ctv.refresh(); + assertTrue("isChecked should be invoked on a refresh", (!provider.isCheckedInvokedOn.isEmpty())); + assertTrue("isGrayed should be invoked on a refresh", (!provider.isGrayedInvokedOn.isEmpty())); + } + + public void testCheckedFalseGrayedFalse() { + testSpecificState(false, false); + } + + public void testCheckedFalseGrayedTrue() { + testSpecificState(false, true); + } + + public void testCheckedTrueGrayedFalse() { + testSpecificState(true, false); + } + + public void testCheckedTrueGrayedTrue() { + testSpecificState(true, true); + } + + private void testSpecificState(final boolean isChecked, final boolean isGrayed) { + CheckboxTableViewer ctv = (CheckboxTableViewer)fViewer; + + ctv.setCheckStateProvider(new ICheckStateProvider() { + public boolean isChecked(Object element) { return isChecked; } + public boolean isGrayed(Object element) { return isGrayed; } + }); + + TableItem item = ctv.getTable().getItem(0); + + assertEquals(item.getChecked(), isChecked); + assertEquals(item.getGrayed(), isGrayed); + } + + public void testSetCheckProviderRefreshesItems() { + CheckboxTableViewer ctv = (CheckboxTableViewer)fViewer; + + //First provider + //Should cause visible items' check state to adhere to provider + ctv.setCheckStateProvider(new TestCheckStateProvider(0)); + + //Check that all states are properly set + checkAllStates("Testing checkbox state after refresh", ctv, 0); + + //Remove the check state provider + ctv.setCheckStateProvider(null); + + //Test that an update doesn't fail + TestElement update = fRootElement.getChildAt(5); + ctv.update(update, null); + + //Test that a refresh doesn't fail + ctv.refresh(); + } + + public void testCheckProviderWithSorter() { + CheckboxTableViewer ctv = (CheckboxTableViewer) fViewer; + + ctv.setSorter(new CheckStateProviderTestsUtil.Sorter()); + + //First provider + //Should cause visible items' check state adhere to provider + ctv.setCheckStateProvider(new TestCheckStateProvider(0)); + + //Check that all states are properly set + checkAllStates("Testing checkbox state with a sorter", ctv, 0); + } + + public void testCheckProviderWithFilter() { + CheckboxTableViewer ctv = (CheckboxTableViewer) fViewer; + + final CheckStateProviderTestsUtil.Filter filter = new CheckStateProviderTestsUtil.Filter(); + ctv.addFilter(filter); + + //First provider + //Should cause visible items' check state adhere to provider + final TestCheckStateProvider checkStateProvider = new TestCheckStateProvider(0); + ctv.setCheckStateProvider(checkStateProvider); + + //Check that all states are properly set + checkAllStates("Testing checkbox state with a sorter", ctv, 0); + + //Check that the provider is only invoked on elements which pass the filter + for (Iterator i = checkStateProvider.isCheckedInvokedOn.iterator(); i.hasNext();) { + TestElement element = (TestElement) i.next(); + assertTrue("The check provider should not be invoked on elements which did not get through the filter", filter.select(ctv, null, element)); + } + + for (Iterator i = checkStateProvider.isGrayedInvokedOn.iterator(); i.hasNext();) { + TestElement element = (TestElement) i.next(); + assertTrue("The check provider should not be invoked on elements which did not get through the filter", filter.select(ctv, null, element)); + } + } + + public void testCheckProviderUpdate() { + CheckboxTableViewer ctv = (CheckboxTableViewer)fViewer; + + //First provider + //Should cause visible items' check state to adhere to provider + ctv.setCheckStateProvider(new TestCheckStateProvider(0)); + + checkAllStates("Testing checkbox state after refresh", ctv, 0); + + //Put in a new check state provider + ctv.setCheckStateProvider(new TestCheckStateProvider(1)); + + //Check that setting a new check provider caused a refresh, + //and thus all the items have their new appropriate check + //states. + checkAllStates("Testing checkbox state after refresh", ctv, 1); + } + + private void checkAllStates(String comment, CheckboxTableViewer ctv, int shift) { + TableItem[] items = ctv.getTable().getItems(); + + //Check that actual states were set properly + for (int i = 0; i < items.length; i++) { + TableItem item = items[i]; + TestElement element = (TestElement)items[i].getData(); + + checkState(comment, element, item, shift); //check in Table + checkState(comment, element, ctv, shift); //check in Viewer + } + } + + /** + * Invokes the appropriate asserts to verify the state + * of a TestElement. + * @param te + * @param viewer the viewer te is in. + * @param shift the shift parameter being used + */ + private void checkState(String comment, TestElement te, CheckboxTableViewer viewer, int shift) { + assertEquals(comment, CheckStateProviderTestsUtil.shouldBeChecked(te, shift), viewer.getChecked(te)); + assertEquals(comment, CheckStateProviderTestsUtil.shouldBeGrayed(te, shift), viewer.getGrayed(te)); + } + + /** + * Invokes the appropriate asserts to verify the state + * of a TestElement's associated TableItem + * @param te + * @param item the item representing te + * @param shift the shift parameter being used + */ + private void checkState(String comment, TestElement te, TableItem item, int shift) { + assertEquals("Wrong checkstate: " + comment, CheckStateProviderTestsUtil.shouldBeChecked(te, shift), item.getChecked()); + assertEquals("Wrong checkstate: " + comment, CheckStateProviderTestsUtil.shouldBeGrayed(te, shift), item.getGrayed()); + } } Index: Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckStateProviderTestsUtil.java =================================================================== RCS file: Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckStateProviderTestsUtil.java diff -N Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckStateProviderTestsUtil.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Eclipse JFace Tests/org/eclipse/jface/tests/viewers/CheckStateProviderTestsUtil.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 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 org.eclipse.jface.tests.viewers; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.viewers.ICheckStateProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.jface.viewers.ViewerSorter; + +/** + * Utilities for testing ICheckStateProviders. + * @since 3.5 + */ +public class CheckStateProviderTestsUtil { + private static final int NUMBER_OF_STATES = 4; + + /** + * An ICheckStateProvider which records whether + * its isChecked and isGrayed methods are invoked. + * @since 3.5 + */ + public static class TestMethodsInvokedCheckStateProvider implements ICheckStateProvider { + public List isCheckedInvokedOn = new ArrayList(); + public List isGrayedInvokedOn = new ArrayList(); + + public boolean isChecked(Object element) { + isCheckedInvokedOn.add(element); + return true; + } + + public boolean isGrayed(Object element) { + isGrayedInvokedOn.add(element); + return true; + } + + public void reset() { + isCheckedInvokedOn = new ArrayList(); + isGrayedInvokedOn = new ArrayList(); + } + } + + /** + * An ICheckStateProvider which provides a consistent + * variety of states for input elements based on the + * parameter provided in the constructor. + * @since 3.5 + */ + public static final class TestCheckStateProvider extends TestMethodsInvokedCheckStateProvider { + private int shift; + + /** + * A value from 0 to 2 which will change the + * checkstate assignments. + * @param shift + */ + public TestCheckStateProvider(int shift) { + this.shift = shift; + } + + public boolean isChecked(Object element) { + super.isChecked(element); + return shouldBeChecked((TestElement)element, shift); + } + + public boolean isGrayed(Object element) { + super.isGrayed(element); + return shouldBeGrayed((TestElement)element, shift); + } + } + + /** + * A sorter for TestElements. + * @since 3.5 + */ + public static final class Sorter extends ViewerSorter { + public int compare(Viewer viewer, Object e1, Object e2) { + return constructNumber((TestElement)e1) - constructNumber((TestElement)e2); + } + } + + /** + * A filter for TestElements. + * @since 3.5 + */ + public static final class Filter extends ViewerFilter { + public boolean select(Viewer viewer, Object parentElement, Object element) { + return (constructNumber((TestElement)element) % (NUMBER_OF_STATES * 2 - 1)) == (NUMBER_OF_STATES - 1); + } + } + /** + * @param te + * @return a number between 0 and 3 based on te. + * Given the same TestElement, this function always returns the + * same value. + */ + public static int constructNumber(TestElement te) { + String id = te.getID(); + int number = Integer.parseInt(id.substring(id.lastIndexOf('-') + 1)) + id.length(); + return number % NUMBER_OF_STATES; + } + + /** + * @param te + * @param shift a parameter to change all check states + * to be different (use to simulate different + * providers over time) + * @return true iff te should be checked + */ + public static boolean shouldBeChecked(TestElement te, int shift) { + return ((constructNumber(te) + shift) % NUMBER_OF_STATES) > 1; + } + + /** + * @param te + * @param shift a parameter to change all check states + * to be different (use to simulate different + * providers over time) + * @return true iff te should be grayed + */ + public static boolean shouldBeGrayed(TestElement te, int shift) { + return ((constructNumber(te) + shift) % NUMBER_OF_STATES) % 2 == 1; + } +}