/*******************************************************************************
* Copyright (c) 2006, 2007 Wind River Systems, Inc. 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:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.viewsupport;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.internal.ui.viewsupport.AsyncTreeContentProvider;
import org.eclipse.cdt.internal.ui.viewsupport.AsyncTreeWorkInProgressNode;
import org.eclipse.cdt.internal.ui.viewsupport.ExtendedTreeViewer;
public class AsyncViewerTest extends BaseUITestCase {
private class Node {
private String fLabel;
private Node[] fChildren;
private int fAsync;
Node(String label, Node[] children, int async) {
fLabel= label;
fChildren= children;
fAsync= async;
}
public Node(String label) {
this(label, new Node[0], 0);
}
public String toString() {
return fLabel;
}
public int hashCode() {
return fLabel.hashCode();
}
public boolean equals(Object rhs) {
if (rhs instanceof Node) {
return fLabel.equals(((Node) rhs).fLabel);
}
return false;
}
}
private class ContentProvider extends AsyncTreeContentProvider {
public ContentProvider(Display disp) {
super(disp);
}
protected Object[] asyncronouslyComputeChildren(Object parentElement, IProgressMonitor monitor) {
Node n= (Node) parentElement;
try {
Thread.sleep(n.fAsync);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return n.fChildren;
}
protected Object[] syncronouslyComputeChildren(Object parentElement) {
Node n= (Node) parentElement;
if (n.fAsync != 0) {
return null;
}
return n.fChildren;
}
};
private class MyLabelProvider extends LabelProvider {
public String getText(Object element) {
if (element instanceof AsyncTreeWorkInProgressNode) {
return "...";
}
return ((Node) element).fLabel;
}
}
private class TestDialog extends Dialog {
private TreeViewer fViewer;
private ContentProvider fContentProvider;
private boolean fUseExtendedViewer;
protected TestDialog(Shell parentShell, boolean useExtendedViewer) {
super(parentShell);
fUseExtendedViewer= useExtendedViewer;
}
protected Control createDialogArea(Composite parent) {
fContentProvider= new ContentProvider(getShell().getDisplay());
Composite comp= (Composite) super.createDialogArea(parent);
fViewer= fUseExtendedViewer ? new ExtendedTreeViewer(comp) : new TreeViewer(comp);
fViewer.setContentProvider(fContentProvider);
fViewer.setLabelProvider(new MyLabelProvider());
return comp;
}
}
private TestDialog fDialog;
protected void tearDown() throws Exception {
if (fDialog != null) {
fDialog.close();
}
super.tearDown();
}
public void testSyncPopulation() {
createTestDialog(false);
doTestSyncPopulation(fDialog);
}
public void testSyncPopulationEx() {
createTestDialog(true);
doTestSyncPopulation(fDialog);
}
private void doTestSyncPopulation(TestDialog dlg) {
Node a,b,c;
Node root= new Node("", new Node[] {
a= new Node("a"),
b= new Node("b", new Node[] {
c= new Node("c")
}, 0)
}, 0);
dlg.fViewer.setInput(root);
assertEquals(2, countVisibleItems(dlg.fViewer));
dlg.fViewer.setExpandedState(a, true);
assertEquals(2, countVisibleItems(dlg.fViewer));
dlg.fViewer.setExpandedState(b, true);
assertEquals(3, countVisibleItems(dlg.fViewer));
}
private void createTestDialog(boolean useExtendedViewer) {
fDialog= new TestDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), useExtendedViewer);
fDialog.setBlockOnOpen(false);
fDialog.open();
}
private int countVisibleItems(TreeViewer viewer) {
return countVisibleItems(viewer.getTree().getItems());
}
private int countVisibleItems(TreeItem[] items) {
int count= items.length;
for (int i = 0; i < items.length; i++) {
TreeItem item = items[i];
if (item.getExpanded()) {
count+= countVisibleItems(item.getItems());
}
}
return count;
}
public void testAsyncPopulation() throws InterruptedException {
createTestDialog(false);
doTestAsyncPopulation(fDialog);
}
public void testAsyncPopulationEx() throws InterruptedException {
createTestDialog(true);
doTestAsyncPopulation(fDialog);
}
private void doTestAsyncPopulation(TestDialog dlg) throws InterruptedException {
Node a,b,c;
Node root= new Node("", new Node[] {
a= new Node("a", new Node[0], 200),
b= new Node("b", new Node[] {
new Node("c"), new Node("d")
}, 200)
}, 0);
// + a
// + b
dlg.fViewer.setInput(root);
waitForItems(dlg.fViewer, 2);
// - a
// - ...
// + b
dlg.fViewer.setExpandedState(a, true);
waitForItems(dlg.fViewer, 3);
assertEquals("...", dlg.fViewer.getTree().getItem(0).getItem(0).getText());
// - a
// + b
runEventQueue(600);
assertEquals(2, countVisibleItems(dlg.fViewer));
// + a
// + b
dlg.fViewer.setInput(null);
dlg.fViewer.setInput(root);
waitForItems(dlg.fViewer, 2);
// expand async with two children
// + a
// - b
// - ...
dlg.fViewer.setExpandedState(b, true);
waitForItems(dlg.fViewer, 3);
assertEquals("...", dlg.fViewer.getTree().getItem(1).getItem(0).getText());
// - a
// - b
// - c
// - d
runEventQueue(600);
assertEquals(4, countVisibleItems(dlg.fViewer));
// + a
// + b
dlg.fViewer.setInput(null);
dlg.fViewer.setInput(root);
waitForItems(dlg.fViewer, 2);
// wait until children are computed (for the sake of the +-sign)
runEventQueue(800);
assertEquals(2, countVisibleItems(dlg.fViewer));
dlg.fViewer.setExpandedState(a, true);
waitForItems(dlg.fViewer, 2);
dlg.fViewer.setExpandedState(b, true);
waitForItems(dlg.fViewer, 4);
}
private void waitForItems(TreeViewer viewer, int count) {
for (int i=0; i<100 && countVisibleItems(viewer) < count; i++) {
runEventQueue(10);
}
assertEquals(count, countVisibleItems(viewer));
}
public void testRecompute() throws InterruptedException {
createTestDialog(true);
Node a,b,c;
Node root=
new Node("", new Node[] {
a= new Node("a"),
b= new Node("b", new Node[] {
c= new Node("c", new Node[] {
new Node("c1"), new Node("c2")}, 150),
new Node("d")
}, 150)
}, 0);
fDialog.fViewer.setInput(root); runEventQueue(50);
assertEquals(2, countVisibleItems(fDialog.fViewer));
fDialog.fContentProvider.recompute();
assertEquals(2, countVisibleItems(fDialog.fViewer));
fDialog.fViewer.setExpandedState(b, true);
runEventQueue(200);
assertEquals(4, countVisibleItems(fDialog.fViewer));
runEventQueue(200);
root.fChildren= new Node[] {
a= new Node("a1"),
b= new Node("b", new Node[] {
c= new Node("c", new Node[] {
new Node("c3"), new Node("c4")}, 150),
new Node("d")
}, 150)
};
fDialog.fContentProvider.recompute();
assertEquals(3, countVisibleItems(fDialog.fViewer));
runEventQueue(200);
assertEquals(4, countVisibleItems(fDialog.fViewer));
fDialog.fViewer.setExpandedState(c, true);
assertEquals(5, countVisibleItems(fDialog.fViewer));
runEventQueue(200);
assertEquals(6, countVisibleItems(fDialog.fViewer));
fDialog.fViewer.setSelection(new StructuredSelection(c));
fDialog.fContentProvider.recompute();
runEventQueue(200);
assertEquals(5, countVisibleItems(fDialog.fViewer));
runEventQueue(200);
assertEquals(6, countVisibleItems(fDialog.fViewer));
assertEquals(1, fDialog.fViewer.getTree().getSelectionCount());
assertEquals("c", fDialog.fViewer.getTree().getSelection()[0].getText());
}
}