blob: 8f887c23e08b4eabe5e4ad5ca7c53cca808c974e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 Wind River Systems 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:
* Wind River Systems - initial API and implementation
* Dorin Ciuca - Top index fix (Bug 324100)
*******************************************************************************/
package org.eclipe.debug.tests.viewer.model;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.eclipe.debug.tests.viewer.model.TestModel.TestElement;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
/**
* @since 3.6
*/
public class JFaceViewerTopIndexTests extends TestCase implements ITestModelUpdatesListenerConstants {
Display fDisplay;
Shell fShell;
TreeModelViewer fViewer;
TestModelUpdatesListener fListener;
public JFaceViewerTopIndexTests(String name) {
super(name);
}
/**
* @throws java.lang.Exception
*/
protected void setUp() throws Exception {
fDisplay = PlatformUI.getWorkbench().getDisplay();
fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/);
fShell.setSize(300, 100);
fShell.setLayout(new FillLayout());
fViewer = createViewer(fDisplay, fShell);
fListener = new TestModelUpdatesListener(fViewer, false, false);
fShell.open ();
}
/**
* @throws java.lang.Exception
*/
protected void tearDown() throws Exception {
fListener.dispose();
fViewer.getPresentationContext().dispose();
// Close the shell and exit.
fShell.close();
while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
}
protected void runTest() throws Throwable {
try {
super.runTest();
} catch (Throwable t) {
throw new ExecutionException("Test failed: " + t.getMessage() + "\n fListener = " + fListener.toString(), t);
}
}
protected ITreeModelContentProviderTarget getCTargetViewer() {
return (ITreeModelContentProviderTarget)fViewer;
}
protected TreeModelViewer createViewer(Display display, Shell shell) {
return new TreeModelViewer(fShell, SWT.VIRTUAL | SWT.MULTI, new PresentationContext("TestViewer"));
}
/**
* Restore REVEAL on simple model with elements without children.
*
*/
public void testRestoreTopIndex() {
TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
TestModel model = new TestModel();
TestElement[] elements = new TestElement[8];
for (int i = 0; i < elements.length; i++) {
String text = Integer.toString(i + 1);
// elements don't have children
elements[i] =
new TestElement(model, text, new TestElement[0] );
}
model.setRoot(new TestElement(model, "root", elements));
// Create the listener, only check the first level
fListener.reset(TreePath.EMPTY, model.getRootElement(), 1, false, false);
// Set the input into the view and update the view.
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
model.validateData(fViewer, TreePath.EMPTY, true);
// Stop forcing view updates.
autopopulateAgent.dispose();
// scroll to the 5th element
int indexRevealElem = 4;
getCTargetViewer().reveal(TreePath.EMPTY, indexRevealElem);
while(fDisplay.readAndDispatch()) {}
final TreePath originalTopPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", originalTopPath);
// Bug 116105: On a Mac the reveal call is not reliable. Use the viewer returned path instead.
// Assert.assertEquals(elements[indexRevealElem], originalTopPath.getLastSegment());
// Extract the original state from viewer
ModelDelta originalState = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
fViewer.saveElementState(TreePath.EMPTY, originalState, IModelDelta.EXPAND | IModelDelta.SELECT);
// Set the viewer input to null. This will trigger the view to save the viewer state.
fListener.reset(true, false);
fListener.addStateUpdates(getCTargetViewer(), originalState, IModelDelta.EXPAND | IModelDelta.SELECT | IModelDelta.REVEAL);
fViewer.setInput(null);
while (!fListener.isFinished(STATE_SAVE_COMPLETE | STATE_UPDATES))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Set the viewer input back to the model to trigger RESTORE operation.
fListener.reset(false, false);
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished(ALL_UPDATES_COMPLETE | STATE_RESTORE_COMPLETE)) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
while (fDisplay.readAndDispatch ()) {}
// check if REVEAL was restored OK
final TreePath topPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", topPath);
TreePathWrapper.assertEqual(originalTopPath, topPath);
}
/**
* Restore REVEAL when having also to restore an expanded element
* that is just above the REVEAL element.
*
* See bug 324100
*/
public void testRestoreTopAndExpand() {
TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
TestModel model = new TestModel();
TestElement[] elements = new TestElement[10];
for (int i = 0; i < elements.length; i++) {
String text = Integer.toString(i + 1);
// first element has 2 children
if (i == 0) {
elements[i] =
new TestElement(model, text, new TestElement[] {
new TestElement(model, text + ".1", new TestElement[0] ),
new TestElement(model, text + ".2", new TestElement[0] )
});
} else {
// rest of elements don't have children
elements[i] =
new TestElement(model, text, new TestElement[0] );
}
}
model.setRoot(new TestElement(model, "root", elements));
// Create the listener, only check the first level
fListener.reset(TreePath.EMPTY, model.getRootElement(), 1, false, false);
// Set the input into the view and update the view.
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
model.validateData(fViewer, TreePath.EMPTY, true);
// Expand first element
fListener.reset();
fListener.setFailOnRedundantUpdates(false);
int indexFirstElem = 0;
TestElement firstElem = elements[indexFirstElem];
ModelDelta rootDelta = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
ModelDelta delta = model.getBaseDelta(rootDelta);
TreePath firstElemPath = model.findElement(firstElem.getLabel());
fListener.addUpdates(
firstElemPath, firstElem, 1,
CHILD_COUNT_UPDATES | CHILDREN_UPDATES );
delta.addNode(firstElem, indexFirstElem, IModelDelta.EXPAND, firstElem.getChildren().length);
model.postDelta(rootDelta);
while (!fListener.isFinished(CONTENT_UPDATES_COMPLETE | MODEL_CHANGED_COMPLETE))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Validate that the first node is expanded
Assert.assertTrue(getCTargetViewer().getExpandedState(firstElemPath) == true);
// Stop forcing view updates.
autopopulateAgent.dispose();
// scroll to the 2nd element
getCTargetViewer().reveal(TreePath.EMPTY, 1);
while(fDisplay.readAndDispatch()) {}
final TreePath originalTopPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", originalTopPath);
// Bug 116105: On a Mac the reveal call is not reliable. Use the viewer returned path instead.
//Assert.assertEquals(elements[1], originalTopPath.getLastSegment());
// Extract the original state from viewer
ModelDelta originalState = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
fViewer.saveElementState(TreePath.EMPTY, originalState, IModelDelta.EXPAND | IModelDelta.SELECT);
// Set the viewer input to null. This will trigger the view to save the viewer state.
fListener.reset(true, false);
fListener.addStateUpdates(getCTargetViewer(), originalState, IModelDelta.EXPAND | IModelDelta.SELECT | IModelDelta.REVEAL);
fViewer.setInput(null);
while (!fListener.isFinished(STATE_SAVE_COMPLETE)) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Set the viewer input back to the model
fListener.reset(false, false);
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished(ALL_UPDATES_COMPLETE | STATE_RESTORE_COMPLETE)) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
while (fDisplay.readAndDispatch ()) {}
// check if REVEAL was restored OK
final TreePath topPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", topPath);
TreePathWrapper.assertEqual(originalTopPath, topPath);
}
/**
* Restore REVEAL when this operation triggers restoring of an expanded
* element.
*
* See bug 324100
*/
public void testRestoreTopTriggersExpand() {
TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
TestModel model = new TestModel();
TestElement[] elements = new TestElement[10];
for (int i = 0; i < elements.length; i++) {
String text = Integer.toString(i + 1);
// last element has 2 children
if (i == elements.length - 1) {
elements[i] =
new TestElement(model, text, new TestElement[] {
new TestElement(model, text + ".1", new TestElement[0] ),
new TestElement(model, text + ".2", new TestElement[0] )
});
} else {
// rest of elements don't have children
elements[i] =
new TestElement(model, text, new TestElement[0] );
}
}
fViewer.setAutoExpandLevel(-1);
model.setRoot(new TestElement(model, "root", elements));
// Create the listener, only check the first level
fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false);
// Set the input into the view and update the view.
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
model.validateData(fViewer, TreePath.EMPTY, true);
int indexLastElem = elements.length-1;
TestElement lastElem = elements[indexLastElem];
TreePath lastElemePath = model.findElement(lastElem.getLabel());
// Validate that the last node is expanded
Assert.assertTrue(getCTargetViewer().getExpandedState(lastElemePath) == true);
// Stop forcing view updates.
fViewer.setAutoExpandLevel(0);
autopopulateAgent.dispose();
// scroll to the element before last element
getCTargetViewer().reveal(TreePath.EMPTY, indexLastElem-1);
while(fDisplay.readAndDispatch()) {}
final TreePath originalTopPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", originalTopPath);
// Extract the original state from viewer
ModelDelta originalState = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
fViewer.saveElementState(TreePath.EMPTY, originalState, IModelDelta.EXPAND | IModelDelta.SELECT);
// Set the viewer input to null. This will trigger the view to save the viewer state.
fListener.reset(true, false);
fListener.addStateUpdates(getCTargetViewer(), originalState, IModelDelta.EXPAND | IModelDelta.SELECT | IModelDelta.REVEAL);
fViewer.setInput(null);
while (!fListener.isFinished(STATE_SAVE_COMPLETE | STATE_UPDATES))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Set the viewer input back to the model.
fListener.reset(false, false);
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished(ALL_UPDATES_COMPLETE | STATE_RESTORE_COMPLETE)) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
while (fDisplay.readAndDispatch ()) {}
// check if REVEAL was restored OK
final TreePath topPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", topPath);
TreePathWrapper.assertEqual(originalTopPath, topPath);
}
/**
* Test for bug 326965.<br>
* This test verifies that canceling a reveal pending state delta is
* properly handled when a new reveal delta is received from the model.
*/
public void testRestoreRevealAfterRevealCancel() {
TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
TestModel model = TestModel.simpleMultiLevel();
// Expand all
fViewer.setAutoExpandLevel(-1);
// Create the listener.
fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false);
// Set the input into the view and update the view.
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
model.validateData(fViewer, TreePath.EMPTY, true);
// Stop autopopulating the view.
autopopulateAgent.dispose();
// Set top index of view to element "3" and wait for view to repaint.
getCTargetViewer().reveal(TreePath.EMPTY, 2);
while(fDisplay.readAndDispatch()) {}
// Trigger save of state.
fListener.reset();
fViewer.setInput(null);
while (!fListener.isFinished(STATE_SAVE_COMPLETE)) fDisplay.sleep ();
// Set input back to root element.
// Note: Wait only for the processing of the delta and the start of state restore, not for all updates
fListener.reset();
TreePath elementPath = model.findElement("3");
fListener.addUpdates(fViewer, elementPath, model.getElement(elementPath), 1, STATE_UPDATES);
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished(MODEL_CHANGED_COMPLETE | STATE_UPDATES))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Update the viewer with new selection delta to something new in the view
ModelDelta revealDelta = model.makeElementDelta(model.findElement("2.1"), IModelDelta.REVEAL);
// Wait for the second model delta to process
fListener.reset();
model.postDelta(revealDelta);
while (!fListener.isFinished(MODEL_CHANGED_COMPLETE | CONTENT_UPDATES_COMPLETE))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Clear view then reset it again.
fListener.reset();
fViewer.setInput(null);
while (!fListener.isFinished(STATE_SAVE_COMPLETE)) fDisplay.sleep ();
autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished(STATE_RESTORE_COMPLETE))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
autopopulateAgent.dispose();
}
/**
* Test for bug 326965.<br>
* This test verifies that canceling a reveal pending state delta is
* properly handled when a new reveal delta is received from the model.
*/
public void testRestoreRevealAfterRevealCancel2() {
if (Platform.getOS().equals(Platform.OS_MACOSX)) {
// skip this test on Mac - see bug 327557
return;
}
TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
TestModel model = TestModel.simpleMultiLevel();
// Expand all
fViewer.setAutoExpandLevel(-1);
// Create the listener.
fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false);
// Set the input into the view and update the view.
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
model.validateData(fViewer, TreePath.EMPTY, true);
// Stop auto-populating and auto-expanding the view.
fViewer.setAutoExpandLevel(0);
autopopulateAgent.dispose();
// Set top index of view to element "3" and wait for view to repaint.
getCTargetViewer().reveal(TreePath.EMPTY, 2);
while(fDisplay.readAndDispatch()) {}
// Trigger save of state.
fListener.reset();
fViewer.setInput(null);
while (!fListener.isFinished(STATE_SAVE_COMPLETE)) fDisplay.sleep ();
// Set input back to root element.
// Note: Wait only for the processing of the delta and the start of state restore, not for all updates
fListener.reset();
TreePath elementPath = model.findElement("2");
fListener.addUpdates(fViewer, elementPath, model.getElement(elementPath), 1, STATE_UPDATES | CHILDREN_UPDATES | LABEL_UPDATES);
elementPath = model.findElement("3");
fListener.addUpdates(fViewer, elementPath, model.getElement(elementPath), 0, STATE_UPDATES);
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished(STATE_UPDATES))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Update the viewer with new selection delta to something new in the view
TreePath pathToBeRevealed = model.findElement("2.1");
ModelDelta revealDelta = model.makeElementDelta(pathToBeRevealed, IModelDelta.REVEAL);
revealDelta.accept(new IModelDeltaVisitor() {
public boolean visit(IModelDelta delta, int depth) {
((ModelDelta)delta).setFlags(delta.getFlags() | IModelDelta.EXPAND);
return true;
}
});
// Wait for the second model delta to process
model.postDelta(revealDelta);
while (!fListener.isFinished(MODEL_CHANGED_COMPLETE | CHILDREN_UPDATES | LABEL_UPDATES))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// check if REVEAL was triggered by the delta and not by the
// state restore operation
TreePath topPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", topPath);
TreePathWrapper.assertEqual(pathToBeRevealed, topPath);
}
/**
* Restore REVEAL when having also to restore an expanded element
* that is just above the REVEAL element.
*
* See bug 324100
*/
public void testRestoreDeepTreeAndReveal() {
TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
TestModel model = TestModel.simpleDeepMultiLevel();
fViewer.setAutoExpandLevel(-1);
// Create the listener, only check the first level
fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false);
// Set the input into the view and update the view.
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
model.validateData(fViewer, TreePath.EMPTY, true);
// Stop forcing view updates.
autopopulateAgent.dispose();
// Scroll down to the last part of the tree.
getCTargetViewer().reveal(model.findElement("3.6.3.16.16.16.16.16"), 1);
while(fDisplay.readAndDispatch()) {}
final TreePath originalTopPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", originalTopPath);
// Extract the original state from viewer
ModelDelta originalState = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
fViewer.saveElementState(TreePath.EMPTY, originalState, IModelDelta.EXPAND | IModelDelta.SELECT);
// Set the viewer input to null. This will trigger the view to save the viewer state.
fListener.reset(true, false);
fListener.addStateUpdates(getCTargetViewer(), originalState, IModelDelta.EXPAND | IModelDelta.SELECT | IModelDelta.REVEAL);
fViewer.setInput(null);
while (!fListener.isFinished(STATE_SAVE_COMPLETE)) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Set the viewer input back to the model
fListener.reset(false, false);
fListener.addUpdates(getCTargetViewer(), originalTopPath, (TestElement)originalTopPath.getLastSegment(), 0, STATE_UPDATES);
fViewer.setInput(model.getRootElement());
while (!fListener.isFinished(STATE_UPDATES | CONTENT_UPDATES_COMPLETE)) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
while (fDisplay.readAndDispatch ()) {}
// check if REVEAL was restored OK
final TreePath topPath = getCTargetViewer().getTopElementPath();
Assert.assertNotNull("Top item should not be null!", topPath);
TreePathWrapper.assertEqual(originalTopPath, topPath);
}
}