Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Piech2009-11-09 23:12:41 +0000
committerPawel Piech2009-11-09 23:12:41 +0000
commit565144f327f94dea5cbbaf0bdea0cddc79280463 (patch)
tree5b1aef471f85a19121f453d8533ad1b78839d702
parentfd836696c57b45691efd5a3dff341cc962b81c6e (diff)
downloadeclipse.platform.debug-565144f327f94dea5cbbaf0bdea0cddc79280463.tar.gz
eclipse.platform.debug-565144f327f94dea5cbbaf0bdea0cddc79280463.tar.xz
eclipse.platform.debug-565144f327f94dea5cbbaf0bdea0cddc79280463.zip
Bug 291267 - [flex-hierarchy] Viewer does not preserve expansion state correctly when elements are inserted/removed due to IModelDelta.CONTENT
-rw-r--r--org.eclipse.debug.tests/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ChildrenUpdateTests.java10
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java114
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ITestModelUpdatesListenerConstants.java37
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerDeltaTests.java6
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerPerformanceTests.java36
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/PerformanceTests.java173
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java186
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java20
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java81
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerLazyModeTests.java95
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerPerformanceTests.java35
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java2
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/PerformanceSuite.java46
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenCountUpdate.java2
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenUpdate.java4
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementCompareRequest.java15
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/HasChildrenUpdate.java2
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProviderTarget.java21
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelViewer.java7
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalTreeModelViewer.java128
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalVirtualTreeModelViewer.java172
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java249
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/SubTreeModelViewer.java23
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java46
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/VirtualItem.java35
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelDelta.java1
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/ModelDelta.java3
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchViewBreadcrumb.java4
29 files changed, 1308 insertions, 248 deletions
diff --git a/org.eclipse.debug.tests/META-INF/MANIFEST.MF b/org.eclipse.debug.tests/META-INF/MANIFEST.MF
index 8a243b9d5..052406d6e 100644
--- a/org.eclipse.debug.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.debug.tests/META-INF/MANIFEST.MF
@@ -8,7 +8,8 @@ Require-Bundle: org.eclipse.ui;bundle-version="[3.6.0,4.0.0)",
org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
org.eclipse.debug.ui;bundle-version="[3.6.0,4.0.0)",
org.junit;bundle-version="3.8.2",
- org.eclipse.core.filesystem;bundle-version="[1.3.0,2.0.0)"
+ org.eclipse.core.filesystem;bundle-version="[1.3.0,2.0.0)",
+ org.eclipse.test.performance;bundle-version="3.6.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.4
Bundle-Vendor: %providerName
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ChildrenUpdateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ChildrenUpdateTests.java
index c0244be14..561104977 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ChildrenUpdateTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ChildrenUpdateTests.java
@@ -65,7 +65,7 @@ public class ChildrenUpdateTests extends TestCase {
public void setAutoExpandLevel(int level) {
}
- public void saveElementState(TreePath path, ModelDelta delta) {
+ public void saveElementState(TreePath path, ModelDelta delta, int flags) {
}
public void removeViewerUpdateListener(IViewerUpdateListener listener) {
@@ -163,6 +163,10 @@ public class ChildrenUpdateTests extends TestCase {
return null;
}
+ public boolean getHasChildren(Object elementOrTreePath) {
+ return false;
+ }
+
public int getChildCount(TreePath path) {
return 0;
}
@@ -176,6 +180,10 @@ public class ChildrenUpdateTests extends TestCase {
public void autoExpand(TreePath elementPath) {
}
+
+ public boolean getElementChildrenRealized(TreePath parentPath) {
+ return false;
+ }
};
}
}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java
index ec382c721..5f6886270 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java
@@ -121,9 +121,9 @@ abstract public class DeltaTests extends TestCase {
TestElement element = model.getRootElement().getChildren()[0];
TreePath elementPath = new TreePath(new Object[] { element });
TestElement[] newChildren = new TestElement[] {
- new TestElement(model, "1.1", new TestElement[0]),
- new TestElement(model, "1.2", new TestElement[0]),
- new TestElement(model, "1.3", new TestElement[0]),
+ new TestElement(model, "1.1 - new", new TestElement[0]),
+ new TestElement(model, "1.2 - new", new TestElement[0]),
+ new TestElement(model, "1.3 - new", new TestElement[0]),
};
ModelDelta delta = model.setElementChildren(elementPath, newChildren);
@@ -133,6 +133,56 @@ abstract public class DeltaTests extends TestCase {
model.validateData(fViewer, TreePath.EMPTY);
}
+ public void testRefreshStruct2() {
+ //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
+
+ TestModel model = TestModel.simpleMultiLevel();
+ fViewer.setAutoExpandLevel(-1);
+
+ // Create the listener
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, 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);
+
+ String prefix = "new - ";
+ model.setElementChildren(TreePath.EMPTY, new TestElement[] {
+ new TestElement(model, prefix + "1", new TestElement[0]),
+ new TestElement(model, prefix + "2", true, false, new TestElement[] {
+ new TestElement(model, prefix + "2.1", true, true, new TestElement[0]),
+ new TestElement(model, prefix + "2.2", false, true, new TestElement[0]),
+ new TestElement(model, prefix + "2.3", true, false, new TestElement[0]),
+ }),
+ new TestElement(model, prefix + "3", new TestElement[] {
+ new TestElement(model, prefix + "3.1", new TestElement[] {
+ new TestElement(model, prefix + "3.1.1", new TestElement[0]),
+ new TestElement(model, prefix + "3.1.2", new TestElement[0]),
+ new TestElement(model, prefix + "3.1.3", new TestElement[0]),
+ }),
+ new TestElement(model, prefix + "3.2", new TestElement[] {
+ new TestElement(model, prefix + "3.2.1", new TestElement[0]),
+ new TestElement(model, prefix + "3.2.2", new TestElement[0]),
+ new TestElement(model, prefix + "3.2.3", new TestElement[0]),
+ }),
+ new TestElement(model, prefix + "3.3", new TestElement[] {
+ new TestElement(model, prefix + "3.3.1", new TestElement[0]),
+ new TestElement(model, prefix + "3.3.2", new TestElement[0]),
+ new TestElement(model, prefix + "3.3.3", new TestElement[0]),
+ }),
+ })
+ });
+
+ TestElement element = model.getRootElement();
+ fListener.reset(TreePath.EMPTY, element, -1, false, false);
+
+ model.postDelta(new ModelDelta(element, IModelDelta.CONTENT));
+ while (!fListener.isFinished(TestModelUpdatesListener.ALL_UPDATES_COMPLETE | TestModelUpdatesListener.MODEL_CHANGED_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY);
+ }
+
public void testInsert() {
//TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
@@ -160,7 +210,7 @@ abstract public class DeltaTests extends TestCase {
fListener.addChildreUpdate(TreePath.EMPTY, 6);
fListener.addHasChildrenUpdate(elementPath);
fListener.addLabelUpdate(elementPath);
- // TODO: redundant updates on insert!
+ // TODO: redundant label updates on insert!
fListener.setFailOnRedundantUpdates(false);
model.postDelta(delta);
while (!fListener.isFinished(TestModelUpdatesListener.ALL_UPDATES_COMPLETE | TestModelUpdatesListener.MODEL_CHANGED_COMPLETE))
@@ -296,7 +346,7 @@ abstract public class DeltaTests extends TestCase {
}
- public void testRemoveElement() {
+ public void testRemove() {
//TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
TestModel model = TestModel.simpleSingleLevel();
@@ -465,4 +515,58 @@ abstract public class DeltaTests extends TestCase {
model.validateData(fViewer, TreePath.EMPTY);
}
+
+ public void testBug292322() {
+ //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
+ TestModel model = TestModel.simpleMultiLevel();
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), 1, true, 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);
+
+ // Update the model: remove one child of an un-expanded element, then
+ // make sure that the number of children is correct.
+ TreePath parentPath = model.findElement("2");
+ TestElement parentElement = model.getElement(parentPath);
+ ModelDelta delta = model.removeElementChild(parentPath, 0);
+
+ // Update the viewer
+ fListener.reset(parentPath, parentElement, 0, false, false);
+ //fListener.addChildreCountUpdate(parentPath);
+ model.postDelta(delta);
+ while (!fListener.isFinished(TestModelUpdatesListener.MODEL_CHANGED_COMPLETE | TestModelUpdatesListener.CONTENT_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+
+ // Validate the viewer data.
+ model.validateData(fViewer, TreePath.EMPTY, true);
+
+ // Update the model: remove the remaining children and make sure that
+ // the element children are updated to false.
+ model.removeElementChild(parentPath, 0);
+
+ // Update the viewer
+ fListener.reset(parentPath, parentElement, 0, false, false);
+ model.postDelta(delta);
+ while (!fListener.isFinished(TestModelUpdatesListener.MODEL_CHANGED_COMPLETE | TestModelUpdatesListener.CONTENT_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+
+ // Validate the viewer data.
+ model.validateData(fViewer, TreePath.EMPTY, true);
+
+ // Update the model: remove the remaining children and make sure that
+ // the element children are updated to false.
+ model.removeElementChild(parentPath, 0);
+
+ // Update the viewer
+ fListener.reset(parentPath, parentElement, 0, false, false);
+ model.postDelta(delta);
+ while (!fListener.isFinished(TestModelUpdatesListener.MODEL_CHANGED_COMPLETE | TestModelUpdatesListener.CONTENT_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+
+ // Validate the viewer data.
+ model.validateData(fViewer, TreePath.EMPTY, true);
+ }
+
}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ITestModelUpdatesListenerConstants.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ITestModelUpdatesListenerConstants.java
new file mode 100644
index 000000000..26570fc5f
--- /dev/null
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ITestModelUpdatesListenerConstants.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipe.debug.tests.viewer.model;
+
+/**
+ * Convenience interface with constants used by the test model update listener.
+ *
+ * @since 3.6
+ */
+public interface ITestModelUpdatesListenerConstants {
+
+ public static final int LABEL_UPDATES_COMPLETE = 0X0001;
+ public static final int CONTENT_UPDATES_COMPLETE = 0X0002;
+ public static final int LABEL_UPDATES = 0X0004;
+ public static final int HAS_CHILDREN_UPDATES = 0X0008;
+ public static final int CHILDREN_COUNT_UPDATES = 0X0010;
+ public static final int CHILDREN_UPDATES = 0X0020;
+ public static final int MODEL_CHANGED_COMPLETE = 0X0040;
+ public static final int MODEL_PROXIES_INSTALLED = 0X0080;
+
+ public static final int VIEWER_UPDATES_RUNNING = 0X0100;
+ public static final int LABEL_UPDATES_RUNNING = 0X0200;
+
+ public static final int LABEL_COMPLETE = LABEL_UPDATES_COMPLETE | LABEL_UPDATES;
+ public static final int CONTENT_COMPLETE =
+ CONTENT_UPDATES_COMPLETE | HAS_CHILDREN_UPDATES | CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES;
+
+ public static final int ALL_UPDATES_COMPLETE = LABEL_COMPLETE | CONTENT_COMPLETE | MODEL_PROXIES_INSTALLED | LABEL_UPDATES_RUNNING | VIEWER_UPDATES_RUNNING;
+}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerDeltaTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerDeltaTests.java
index f50a0587f..ed613bd6f 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerDeltaTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerDeltaTests.java
@@ -29,4 +29,10 @@ public class JFaceViewerDeltaTests extends DeltaTests {
protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell) {
return new TreeModelViewer(fShell, SWT.VIRTUAL, new PresentationContext("TestViewer"));
}
+
+ /**
+ * TODO: remove this method when bug 292322 gets fixed in TreeViewer
+ */
+ public void testBug292322() {
+ }
}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerPerformanceTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerPerformanceTests.java
new file mode 100644
index 000000000..865db9508
--- /dev/null
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerPerformanceTests.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipe.debug.tests.viewer.model;
+
+import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * @since 3.6
+ */
+public class JFaceViewerPerformanceTests extends PerformanceTests {
+
+ public JFaceViewerPerformanceTests(String name) {
+ super(name);
+ }
+
+ protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell) {
+ return new TreeModelViewer(fShell, SWT.VIRTUAL, new PresentationContext("TestViewer"));
+ }
+
+ protected int getTestModelDepth() {
+ return 5;
+ }
+}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/PerformanceTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/PerformanceTests.java
new file mode 100644
index 000000000..f4c0786c6
--- /dev/null
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/PerformanceTests.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipe.debug.tests.viewer.model;
+
+import junit.framework.TestCase;
+
+import org.eclipe.debug.tests.viewer.model.TestModel.TestElement;
+import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
+import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.test.performance.Performance;
+import org.eclipse.test.performance.PerformanceMeter;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Tests to measure the performance of the viewer updates.
+ */
+abstract public class PerformanceTests extends TestCase implements ITestModelUpdatesListenerConstants {
+ Display fDisplay;
+ Shell fShell;
+ ITreeModelViewer fViewer;
+ TestModelUpdatesListener fListener;
+
+ public PerformanceTests(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.setMaximized(true);
+ fShell.setLayout(new FillLayout());
+
+ fViewer = createViewer(fDisplay, fShell);
+
+ fListener = new TestModelUpdatesListener(false, false);
+ fViewer.addViewerUpdateListener(fListener);
+ fViewer.addLabelUpdateListener(fListener);
+ fViewer.addModelChangedListener(fListener);
+
+ fShell.open ();
+ }
+
+ abstract protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell);
+
+ /**
+ * @throws java.lang.Exception
+ */
+ protected void tearDown() throws Exception {
+ fViewer.removeLabelUpdateListener(fListener);
+ fViewer.removeViewerUpdateListener(fListener);
+ fViewer.removeModelChangedListener(fListener);
+
+ // Close the shell and exit.
+ fShell.close();
+ while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ }
+
+ /**
+ * Depth (size) of the test model to be used in the tests. This number allows
+ * the jface based tests to use a small enough model to fit on the screen, and
+ * for the virtual viewer to exercise the content provider to a greater extent.
+ */
+ abstract protected int getTestModelDepth();
+
+ public void testRefreshStruct() {
+ TestModel model = new TestModel();
+ model.setRoot( new TestElement(model, "root", new TestElement[0] ) );
+ model.setElementChildren(TreePath.EMPTY, makeModelElements(model, getTestModelDepth(), "model"));
+
+ fViewer.setAutoExpandLevel(-1);
+
+ // Create the listener
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, 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);
+
+ Performance perf = Performance.getDefault();
+ PerformanceMeter meter = perf.createPerformanceMeter(perf.getDefaultScenarioId(this));
+ try {
+ for (int i = 0; i < 100; i++) {
+ // Update the model
+ model.setAllAppendix(" - pass " + i);
+ //model.setElementChildren(TreePath.EMPTY, makeModelElements(model, getTestModelDepth(), "pass " + i));
+
+ TestElement element = model.getRootElement();
+ fListener.reset(TreePath.EMPTY, element, -1, false, false);
+
+ meter.start();
+ model.postDelta(new ModelDelta(element, IModelDelta.CONTENT));
+ while (!fListener.isFinished(ALL_UPDATES_COMPLETE | MODEL_CHANGED_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY);
+ meter.stop();
+ System.gc();
+ }
+
+ meter.commit();
+ perf.assertPerformance(meter);
+ } finally {
+ meter.dispose();
+ }
+ }
+
+ public void testRefreshStructReplaceElements() {
+ TestModel model = new TestModel();
+ model.setRoot( new TestElement(model, "root", new TestElement[0] ) );
+ model.setElementChildren(TreePath.EMPTY, makeModelElements(model, getTestModelDepth(), "model"));
+
+ fViewer.setAutoExpandLevel(-1);
+
+ // Create the listener
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, 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);
+
+ Performance perf = Performance.getDefault();
+ PerformanceMeter meter = perf.createPerformanceMeter(perf.getDefaultScenarioId(this));
+ try {
+ for (int i = 0; i < 2000; i++) {
+ // Update the model
+ model.setElementChildren(TreePath.EMPTY, makeModelElements(model, getTestModelDepth(), "pass " + i));
+
+ TestElement element = model.getRootElement();
+ fListener.reset(TreePath.EMPTY, element, -1, false, false);
+
+ meter.start();
+ model.postDelta(new ModelDelta(element, IModelDelta.CONTENT));
+ while (!fListener.isFinished(ALL_UPDATES_COMPLETE | MODEL_CHANGED_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY);
+ meter.stop();
+ System.gc();
+ }
+
+ meter.commit();
+ perf.assertPerformance(meter);
+ } finally {
+ meter.dispose();
+ }
+ }
+
+ private TestElement[] makeModelElements(TestModel model, int depth, String prefix) {
+ TestElement[] elements = new TestElement[depth];
+ for (int i = 0; i < depth; i++) {
+ String name = prefix + "." + i;
+ elements[i] = new TestElement(model, name, makeModelElements(model, i, name));
+ }
+ return elements;
+ }
+}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java
index f98c77a40..f19df2734 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java
@@ -14,6 +14,7 @@ import junit.framework.Assert;
import junit.framework.TestCase;
import org.eclipe.debug.tests.viewer.model.TestModel.TestElement;
+import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
@@ -29,7 +30,7 @@ import org.eclipse.ui.PlatformUI;
*
* @since 3.6
*/
-abstract public class StateTests extends TestCase {
+abstract public class StateTests extends TestCase implements ITestModelUpdatesListenerConstants {
Display fDisplay;
Shell fShell;
ITreeModelViewer fViewer;
@@ -123,12 +124,12 @@ abstract public class StateTests extends TestCase {
fListener.addHasChildrenUpdate(path3);
fListener.addLabelUpdate(path3);
- while (!fListener.isFinished(TestModelUpdatesListener.CONTENT_UPDATES_COMPLETE | TestModelUpdatesListener.LABEL_UPDATES))
+ while (!fListener.isFinished(CONTENT_UPDATES_COMPLETE | LABEL_UPDATES))
if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
// Extract the new state from viewer
ModelDelta savedDelta = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
- fViewer.saveElementState(path0, savedDelta);
+ fViewer.saveElementState(path0, savedDelta, IModelDelta.EXPAND | IModelDelta.SELECT);
Assert.assertTrue( deltaMatches(updateDelta, savedDelta) );
}
@@ -154,4 +155,183 @@ abstract public class StateTests extends TestCase {
return false;
}
+ private TestModel alternatingSubsreesModel() {
+ TestModel model = new TestModel();
+ model.setRoot( new TestElement(model, "root", new TestElement[] {
+ new TestElement(model, "1", new TestElement[] {
+ new TestElement(model, "1.1", new TestElement[] {
+ new TestElement(model, "1.1.1", new TestElement[0]),
+ }),
+ }),
+ new TestElement(model, "2", new TestElement[] {
+ new TestElement(model, "2.1", new TestElement[] {
+ new TestElement(model, "2.1.1", new TestElement[0]),
+ }),
+ }),
+ new TestElement(model, "3", new TestElement[] {
+ new TestElement(model, "3.1", new TestElement[] {
+ new TestElement(model, "3.1.1", new TestElement[0]),
+ }),
+ }),
+ new TestElement(model, "4", new TestElement[] {
+ new TestElement(model, "4.1", new TestElement[] {
+ new TestElement(model, "4.1.1", new TestElement[0]),
+ }),
+ }),
+ new TestElement(model, "5", new TestElement[] {
+ new TestElement(model, "5.1", new TestElement[] {
+ new TestElement(model, "5.1.1", new TestElement[0]),
+ }),
+ }),
+ new TestElement(model, "6", new TestElement[] {
+ new TestElement(model, "6.1", new TestElement[] {
+ new TestElement(model, "6.1.1", new TestElement[0]),
+ }),
+ })
+ }) );
+ return model;
+ }
+
+ private void expandAlternateElements(TestModel model) {
+ // Expand every other child
+ fListener.reset();
+ fListener.setFailOnRedundantUpdates(false);
+ ITreeModelContentProviderTarget viewer = (ITreeModelContentProviderTarget)fViewer;
+ TreePath path;
+ fListener.addUpdates(path = model.findElement("1"), (TestElement)path.getLastSegment(), 1, CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES);
+ viewer.setExpandedState(path, true);
+ fListener.addUpdates(path = model.findElement("3"), (TestElement)path.getLastSegment(), 1, CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES);
+ viewer.setExpandedState(path, true);
+ fListener.addUpdates(path = model.findElement("5"), (TestElement)path.getLastSegment(), 1, CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES);
+ viewer.setExpandedState(path, true);
+
+ while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY, true);
+
+ // Expand the sub-children as well (so that the expanded nodes go 2 levels down.
+ fListener.reset();
+ fListener.addUpdates(path = model.findElement("1.1"), (TestElement)path.getLastSegment(), 1, CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES);
+ viewer.setExpandedState(path, true);
+ fListener.addUpdates(path = model.findElement("3.1"), (TestElement)path.getLastSegment(), 1, CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES);
+ viewer.setExpandedState(path, true);
+ fListener.addUpdates(path = model.findElement("5.1"), (TestElement)path.getLastSegment(), 1, CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES);
+ viewer.setExpandedState(path, true);
+ while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY, true);
+
+ }
+
+ public void testPreserveExpandedOnRemove() {
+ //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
+ TestModel model = alternatingSubsreesModel();
+
+ // NOTE: WE ARE NOT EXPANDING ANY CHILDREN
+
+ // Create the listener, only check the first level
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), 1, true, 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);
+
+ expandAlternateElements(model);
+
+ // Update the model
+ ModelDelta delta = model.removeElementChild(TreePath.EMPTY, 0);
+
+ // Remove delta should not generate any new updates
+ fListener.reset();
+ model.postDelta(delta);
+ while (!fListener.isFinished(MODEL_CHANGED_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY, true);
+ ITreeModelContentProviderTarget viewer = (ITreeModelContentProviderTarget)fViewer;
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("2")) == false);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("3")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("3.1")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("4")) == false);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("5")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("5.1")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("6")) == false);
+ }
+
+ public void testPreserveExpandedOnInsert() {
+ //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
+ TestModel model = alternatingSubsreesModel();
+
+ // NOTE: WE ARE NOT EXPANDING ANY CHILDREN
+
+ // Create the listener, only check the first level
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), 1, true, 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);
+
+ expandAlternateElements(model);
+
+ // Update the model
+ ModelDelta delta = model.insertElementChild(TreePath.EMPTY, 0, new TestElement(model, "0 - new", new TestElement[0]));
+
+ // Insert delta should generate updates only for the new element
+ TreePath path = model.findElement("0 - new");
+ // Note: redundant label updates on insert.
+ fListener.reset(path, (TestElement)path.getLastSegment(), 0, false, false);
+ fListener.addChildreUpdate(TreePath.EMPTY, 0);
+ model.postDelta(delta);
+ while (!fListener.isFinished(MODEL_CHANGED_COMPLETE | ALL_UPDATES_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY, true);
+ ITreeModelContentProviderTarget viewer = (ITreeModelContentProviderTarget)fViewer;
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("1")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("1.1")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("2")) == false);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("3")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("3.1")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("4")) == false);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("5")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("5.1")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("6")) == false);
+ }
+
+
+ public void testPreserveExpandedOnContent() {
+ //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
+ TestModel model = alternatingSubsreesModel();
+
+ // NOTE: WE ARE NOT EXPANDING ANY CHILDREN
+
+ // Create the listener, only check the first level
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), 1, true, 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);
+
+ expandAlternateElements(model);
+
+ // Update the model
+ model.removeElementChild(TreePath.EMPTY, 0);
+
+ // Content delta should generate updates for the elements being re-expanded
+ ITreeModelContentProviderTarget viewer = (ITreeModelContentProviderTarget)fViewer;
+ // Note: Re-expanding nodes causes redundant updates.
+ fListener.reset(false, false);
+ fListener.addUpdates(viewer, TreePath.EMPTY, model.getRootElement(), -1, ALL_UPDATES_COMPLETE);
+ model.postDelta(new ModelDelta(model.getRootElement(), IModelDelta.CONTENT));
+ while (!fListener.isFinished(ALL_UPDATES_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY, true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("2")) == false);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("3")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("3.1")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("4")) == false);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("5")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("5.1")) == true);
+ Assert.assertTrue(viewer.getExpandedState(model.findElement("6")) == false);
+ }
+
}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java
index 11f7f983a..c4f5f348d 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java
@@ -152,7 +152,7 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
/**
* Constructor private. Use static factory methods instead.
*/
- private TestModel() {}
+ public TestModel() {}
public TestElement getRootElement() {
return fRoot;
@@ -264,7 +264,18 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
doSetExpanded(element.fChildren[i]);
}
}
+
+ public void setAllAppendix(String appendix) {
+ doSetAllAppendix(fRoot, appendix);
+ }
+ private void doSetAllAppendix(TestElement element, String appendix) {
+ element.setLabelAppendix(appendix);
+ for (int i = 0; i < element.fChildren.length; i++) {
+ doSetAllAppendix(element.fChildren[i], appendix);
+ }
+ }
+
public void validateData(ITreeModelViewer viewer, TreePath path) {
validateData(viewer, path, false);
@@ -287,10 +298,13 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
Assert.assertEquals(children[i], viewer.getChildElement(path, i));
validateData(viewer, path.createChildPath(children[i]), expandedElementsOnly);
}
+ } else if (!viewer.getExpandedState(path)) {
+ // If element not expanded, verify the plus sign.
+ Assert.assertEquals(viewer.getHasChildren(path), element.getChildren().length > 0);
}
}
- private void setRoot(TestElement root) {
+ public void setRoot(TestElement root) {
fRoot = root;
}
@@ -557,7 +571,7 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
}) );
return model;
}
-
+
public static TestModel compositeMultiLevel() {
TestModel m2 = new TestModel();
m2.setRoot( new TestElement(m2, "m2.root", new TestElement[] {
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java
index 928c7fa32..c694e1d1d 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java
@@ -20,6 +20,7 @@ import junit.framework.Assert;
import org.eclipe.debug.tests.viewer.model.TestModel.TestElement;
import org.eclipse.debug.internal.ui.viewers.model.ILabelUpdateListener;
+import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
@@ -31,27 +32,9 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
import org.eclipse.jface.viewers.TreePath;
-public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUpdateListener, IModelChangedListener {
-
- public static final int LABEL_UPDATES_COMPLETE = 0X0001;
- public static final int CONTENT_UPDATES_COMPLETE = 0X0002;
- public static final int LABEL_UPDATES = 0X0004;
- public static final int HAS_CHILDREN_UPDATES = 0X0008;
- public static final int CHILDREN_COUNT_UPDATES = 0X0010;
- public static final int CHILDREN_UPDATES = 0X0020;
- public static final int MODEL_CHANGED_COMPLETE = 0X0040;
- public static final int MODEL_PROXIES_INSTALLED = 0X0080;
-
- public static final int VIEWER_UPDATES_RUNNING = 0X0100;
- public static final int LABEL_UPDATES_RUNNING = 0X0200;
-
- public static final int LABEL_COMPLETE = LABEL_UPDATES_COMPLETE | LABEL_UPDATES;
- public static final int CONTENT_COMPLETE =
- CONTENT_UPDATES_COMPLETE | HAS_CHILDREN_UPDATES | CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES;
-
-
- public static final int ALL_UPDATES_COMPLETE = LABEL_COMPLETE | CONTENT_COMPLETE | MODEL_PROXIES_INSTALLED | LABEL_UPDATES_RUNNING | VIEWER_UPDATES_RUNNING;
-
+public class TestModelUpdatesListener
+ implements IViewerUpdateListener, ILabelUpdateListener, IModelChangedListener, ITestModelUpdatesListenerConstants
+{
private boolean fFailOnRedundantUpdates;
private boolean fFailOnMultipleUpdateSequences;
@@ -87,7 +70,13 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
setFailOnRedundantUpdates(failOnRedundantUpdates);
setFailOnMultipleUpdateSequences(failOnMultipleUpdateSequences);
}
-
+
+ public void reset(boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) {
+ reset();
+ setFailOnRedundantUpdates(failOnRedundantUpdates);
+ setFailOnMultipleUpdateSequences(failOnMultipleUpdateSequences);
+ }
+
public void reset() {
fHasChildrenUpdates.clear();
fChildrenUpdates.clear();
@@ -124,7 +113,7 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
childrenIndexes.add(new Integer(index));
}
- public void recurseremoveChildreUpdate(TreePath path, int index) {
+ public void removeChildrenUpdate(TreePath path, int index) {
Set childrenIndexes = (Set)fChildrenUpdates.get(path);
if (childrenIndexes != null) {
childrenIndexes.remove(new Integer(index));
@@ -143,27 +132,42 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
}
public void addUpdates(TreePath path, TestElement element, int levels) {
- TestElement[] children = element.getChildren();
-
+ addUpdates(path, element, levels, ALL_UPDATES_COMPLETE);
+ }
+
+ public void addUpdates(TreePath path, TestElement element, int levels, int flags) {
+ addUpdates(null, path, element, levels, flags);
+ }
+
+ public void addUpdates(ITreeModelContentProviderTarget viewer, TreePath path, TestElement element, int levels, int flags) {
if (!path.equals(TreePath.EMPTY)) {
- fLabelUpdates.add(path);
- fHasChildrenUpdates.add(path);
+ if ((flags & LABEL_UPDATES) != 0) {
+ fLabelUpdates.add(path);
+ }
+ if ((flags & HAS_CHILDREN_UPDATES) != 0) {
+ fHasChildrenUpdates.add(path);
+ }
}
- if (levels != 0) {
- levels--;
- if (children.length > 0) {
- fChildCountUpdates.add(path);
- Set childrenIndexes = new HashSet();
+ if (levels-- != 0) {
+ TestElement[] children = element.getChildren();
+ if (children.length > 0 && (viewer == null || path.getSegmentCount() == 0 || viewer.getExpandedState(path))) {
+ if ((flags & CHILDREN_COUNT_UPDATES) != 0) {
+ fChildCountUpdates.add(path);
+ }
+ if ((flags & CHILDREN_UPDATES) != 0) {
+ Set childrenIndexes = new HashSet();
+ for (int i = 0; i < children.length; i++) {
+ childrenIndexes.add(new Integer(i));
+ }
+ fChildrenUpdates.put(path, childrenIndexes);
+ }
+
for (int i = 0; i < children.length; i++) {
- childrenIndexes.add(new Integer(i));
+ addUpdates(viewer, path.createChildPath(children[i]), children[i], levels, flags);
}
- fChildrenUpdates.put(path, childrenIndexes);
}
- for (int i = 0; i < children.length; i++) {
- addUpdates(path.createChildPath(children[i]), children[i], levels);
- }
}
}
@@ -224,11 +228,9 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
synchronized (this) {
fViewerUpdatesRunning++;
}
- System.out.println("started: " + update);
}
public void updateComplete(IViewerUpdate update) {
- System.out.println("completed: " + update);
synchronized (this) {
fViewerUpdatesRunning--;
}
@@ -285,7 +287,6 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
synchronized (this) {
fLabelUpdatesRunning++;
}
- System.out.println("started: " + update);
}
public void labelUpdatesBegin() {
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerLazyModeTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerLazyModeTests.java
index 7977d286b..6afa8f6de 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerLazyModeTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerLazyModeTests.java
@@ -10,16 +10,11 @@
*******************************************************************************/
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.debug.internal.ui.viewers.model.ITreeModelViewer;
-import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
-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.VirtualTreeModelViewer;
-import org.eclipse.jface.viewers.TreePath;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
@@ -28,6 +23,8 @@ import org.eclipse.ui.PlatformUI;
/**
* Tests which verify the operation of the virtual viewer in the lazy mode.
+ * Note: the virtual viewer doesn't support lazy mode yet, so this class
+ * is really just a big place holder.
*
* @since 3.6
*/
@@ -77,91 +74,7 @@ public class VirtualViewerLazyModeTests extends TestCase {
while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
}
- public void testUpdateViewer() {
- //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
-
- TestModel model = TestModel.simpleMultiLevel();
-
- // Initialize the listener. In lazy mode, until a selection
- // is made, only the root element count should be updated.
- fListener.reset();
- fListener.addChildreCountUpdate(TreePath.EMPTY);
-
- // Set the input into the view and update the view.
- fViewer.setInput(model.getRootElement());
- while (!fListener.isFinished(TestModelUpdatesListener.CONTENT_UPDATES_COMPLETE))
- if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
-
- // Do not try to validate data, because the virtual viewer contains only
- // a subset of model.
-
- // Create the update delta
- TestElement element = model.getRootElement();
- TreePath path0 = TreePath.EMPTY;
- ModelDelta delta = new ModelDelta(model.getRootElement(), -1, IModelDelta.EXPAND, element.getChildren().length);
- ModelDelta updateDelta = delta;
- element = element.getChildren()[2];
- TreePath path1 = path0.createChildPath(element);
- delta = delta.addNode(element, 2, IModelDelta.EXPAND, element.fChildren.length);
- element = element.getChildren()[1];
- TreePath path2 = path1.createChildPath(element);
- delta = delta.addNode(element, 1, IModelDelta.EXPAND, element.fChildren.length);
- element = element.getChildren()[1];
- TreePath path3 = path2.createChildPath(element);
- delta = delta.addNode(element, 1, IModelDelta.SELECT);
-
- fViewer.updateViewer(updateDelta);
-
- // Viewer should update data and labels of items in selection
- fListener.reset();
- fListener.addChildreUpdate(path0, 2);
- fListener.addHasChildrenUpdate(path1);
- fListener.addChildreCountUpdate(path1);
- fListener.addLabelUpdate(path1);
- fListener.addChildreUpdate(path1, 1);
- fListener.addHasChildrenUpdate(path2);
- fListener.addChildreCountUpdate(path2);
- fListener.addLabelUpdate(path2);
- fListener.addHasChildrenUpdate(path2);
- fListener.addChildreCountUpdate(path2);
- fListener.addChildreUpdate(path2, 1);
- fListener.addHasChildrenUpdate(path3);
- fListener.addLabelUpdate(path3);
-
- // When processing expand and select deltas, the label may be requested
- // multiple times for the same element. So we have to set the fail for
- // redundant updates to false.
- fListener.setFailOnRedundantUpdates(false);
-
- while (!fListener.isFinished(TestModelUpdatesListener.CONTENT_UPDATES_COMPLETE | TestModelUpdatesListener.LABEL_UPDATES))
- if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
-
- // Extract the new state from viewer
- ModelDelta savedDelta = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
- fViewer.saveElementState(path0, savedDelta);
-
- Assert.assertTrue( deltaMatches(updateDelta, savedDelta) );
+ public void test() {
+ // TODO
}
-
- boolean deltaMatches(ModelDelta requested, ModelDelta received) {
- if ( requested.getElement().equals(received.getElement()) &&
- requested.getFlags() == received.getFlags() &&
- ( requested.getChildCount() == -1 || requested.getChildCount() == received.getChildCount() )&&
- ( requested.getIndex() == -1 || requested.getIndex() == received.getIndex()) &&
- ((requested.getReplacementElement() != null && requested.getReplacementElement().equals(received.getReplacementElement())) ||
- (requested.getReplacementElement() == null && received.getReplacementElement() == null)) &&
- requested.getChildDeltas().length == received.getChildDeltas().length)
- {
- for (int i = 0; i < requested.getChildDeltas().length; i++) {
- ModelDelta requestedChildDelta = (ModelDelta)requested.getChildDeltas()[i];
- ModelDelta receivedChildDelta = received.getChildDelta(requestedChildDelta.getElement());
- if ( receivedChildDelta == null || !deltaMatches(requestedChildDelta, receivedChildDelta) ) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
-
}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerPerformanceTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerPerformanceTests.java
new file mode 100644
index 000000000..2c4e6cd6b
--- /dev/null
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerPerformanceTests.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipe.debug.tests.viewer.model;
+
+import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * @since 3.6
+ */
+public class VirtualViewerPerformanceTests extends PerformanceTests {
+
+ public VirtualViewerPerformanceTests(String name) {
+ super(name);
+ }
+
+ protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell) {
+ return new VirtualTreeModelViewer(fDisplay, 0, new PresentationContext("TestViewer"));
+ }
+
+ protected int getTestModelDepth() {
+ return 7;
+ }
+}
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
index 34b728d04..8d60693fb 100644
--- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
@@ -36,7 +36,7 @@ import org.eclipe.debug.tests.viewer.model.VirtualViewerUpdateTests;
import org.eclipse.debug.tests.statushandlers.StatusHandlerTests;
/**
- * Tests for integration and nightly builds.
+ * Tests for integration and nightly builds.
*
* @since 3.6
*/
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/PerformanceSuite.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/PerformanceSuite.java
new file mode 100644
index 000000000..98fcfaca9
--- /dev/null
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/PerformanceSuite.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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
+ *******************************************************************************/
+package org.eclipse.debug.tests;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.eclipe.debug.tests.viewer.model.JFaceViewerPerformanceTests;
+import org.eclipe.debug.tests.viewer.model.VirtualViewerPerformanceTests;
+
+/**
+ * Tests for release builds.
+ *
+ * @since 3.6
+ */
+public class PerformanceSuite extends TestSuite {
+
+ /**
+ * Returns the suite. This is required to use the JUnit Launcher.
+ *
+ * @return the test suite
+ */
+ public static Test suite() {
+ return new PerformanceSuite();
+ }
+
+ /**
+ * Constructs the automated test suite. Adds all tests.
+ */
+ public PerformanceSuite() {
+ // JFace viewer tests
+ addTest(new TestSuite(JFaceViewerPerformanceTests.class));
+
+ // Virtual viewer tests
+ addTest(new TestSuite(VirtualViewerPerformanceTests.class));
+ }
+
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenCountUpdate.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenCountUpdate.java
index eb4da116d..19b0be07a 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenCountUpdate.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenCountUpdate.java
@@ -52,7 +52,7 @@ class ChildrenCountUpdate extends ViewerUpdateMonitor implements IChildrenCountU
System.out.println("setChildCount(" + getElement() + ", modelCount: " + fCount + " viewCount: " + viewCount + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
getContentProvider().getViewer().setChildCount(elementPath, viewCount);
- getContentProvider().doRestore(getElementPath(), -1, true, true);
+ getContentProvider().doRestore(getElementPath(), -1, true, true, false);
}
public void setChildCount(int numChildren) {
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenUpdate.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenUpdate.java
index bc17d93a1..21db89ddd 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenUpdate.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenUpdate.java
@@ -78,10 +78,12 @@ public class ChildrenUpdate extends ViewerUpdateMonitor implements IChildrenUpda
}
TreePath childPath = elementPath.createChildPath(element);
provider.updateHasChildren(childPath);
- provider.doRestore(childPath, modelIndex, false, false);
+ provider.doRestore(childPath, modelIndex, false, false, false);
}
}
}
+
+ provider.doRestore(elementPath, -1, true, true, true);
} else {
provider.updateHasChildren(elementPath);
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementCompareRequest.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementCompareRequest.java
index 66b44cc5f..2b3422ed2 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementCompareRequest.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementCompareRequest.java
@@ -30,6 +30,7 @@ class ElementCompareRequest extends MementoUpdate implements IElementCompareRequ
private ModelDelta fDelta;
private boolean fKnowsHasChildren;
private boolean fKnowsChildCount;
+ private boolean fCheckChildrenRealized;
/**
@@ -37,13 +38,17 @@ class ElementCompareRequest extends MementoUpdate implements IElementCompareRequ
* @param element
* @param memento
*/
- public ElementCompareRequest(ModelContentProvider provider, Object viewerInput, Object element, TreePath elementPath, IMemento memento, ModelDelta delta, int modelIndex, boolean hasChildren, boolean knowsChildCount) {
+ public ElementCompareRequest(ModelContentProvider provider, Object viewerInput, Object element,
+ TreePath elementPath, IMemento memento, ModelDelta delta, int modelIndex,
+ boolean hasChildren, boolean knowsChildCount, boolean checkChildrenRealized)
+ {
super(provider, viewerInput, provider.getPresentationContext(), element, elementPath, memento);
fProvider = provider;
fDelta = delta;
fModelIndex = modelIndex;
fKnowsHasChildren = hasChildren;
fKnowsChildCount = knowsChildCount;
+ fCheckChildrenRealized = checkChildrenRealized;
}
/* (non-Javadoc)
@@ -96,4 +101,12 @@ class ElementCompareRequest extends MementoUpdate implements IElementCompareRequ
boolean knowChildCount() {
return fKnowsChildCount;
}
+
+ void setCheckChildrenRealized(boolean checkChildrenRealized) {
+ fCheckChildrenRealized = checkChildrenRealized;
+ }
+
+ boolean checkChildrenRealized() {
+ return fCheckChildrenRealized;
+ }
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/HasChildrenUpdate.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/HasChildrenUpdate.java
index be08635b3..61bb05dc6 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/HasChildrenUpdate.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/HasChildrenUpdate.java
@@ -53,7 +53,7 @@ class HasChildrenUpdate extends ViewerUpdateMonitor implements IHasChildrenUpdat
contentProvider.getViewer().autoExpand(elementPath);
}
if (elementPath.getSegmentCount() > 0) {
- getContentProvider().doRestore(getElementPath(), -1, true, false);
+ getContentProvider().doRestore(getElementPath(), -1, true, false, false);
}
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProviderTarget.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProviderTarget.java
index 701ebca0d..dee5a1ec8 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProviderTarget.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProviderTarget.java
@@ -206,7 +206,16 @@ public interface ITreeModelContentProviderTarget extends ITreeModelViewer {
public boolean getExpandedState(Object elementOrTreePath);
/**
- * Returns the child count of the element at the given path.
+ * Returns whether the given element has children.
+ *
+ * @since 3.6
+ */
+ public boolean getHasChildren(Object elementOrTreePath);
+
+ /**
+ * Returns the child count of the element at the given path. <br>
+ * Note: The child count may be incorrect if the element is not
+ * expanded in the tree.
*/
public int getChildCount(TreePath path);
@@ -229,4 +238,14 @@ public interface ITreeModelContentProviderTarget extends ITreeModelViewer {
*/
public int findElementIndex(TreePath parentPath, Object element);
+ /**
+ * Returns a boolean indicating whether all the child elements of the
+ * given parent have been realized already.
+ *
+ * @param parentPath
+ * @return
+ *
+ * @since 3.6
+ */
+ public boolean getElementChildrenRealized(TreePath parentPath);
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelViewer.java
index f834b75d6..9e6198327 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelViewer.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelViewer.java
@@ -165,8 +165,13 @@ public interface ITreeModelViewer extends ISelectionProvider {
* as it parses the sub-tree.
* @param path Path where to start saving the state.
* @param delta The delta where the state is to be saved.
+ * @param flagsToSave The flags to preserve during the state save. The
+ * supported flags are <code>IModelDelta.SELECT</code>,
+ * <code>IModelDelta.EXPAND</code>, <code>IModelDelta.COLLAPSE</code>.
+ *
+ * @since 3.6
*/
- public void saveElementState(TreePath path, ModelDelta delta);
+ public void saveElementState(TreePath path, ModelDelta delta, int flagsToSave);
/**
* Causes the viewer to process the given delta as if it came from a
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalTreeModelViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalTreeModelViewer.java
index dd1e8e894..1a8bddf79 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalTreeModelViewer.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalTreeModelViewer.java
@@ -1948,6 +1948,54 @@ public class InternalTreeModelViewer extends TreeViewer
.updateElement(treePath, index);
}
+//**************************************************************************
+// Another couple of methods copied from TreeViewer to workaround the UI bug 266189.
+//
+ protected void createChildren(Widget widget) {
+ Object element = widget.getData();
+ if (element == null && widget instanceof TreeItem) {
+ // parent has not been materialized
+ virtualMaterializeItem((TreeItem) widget);
+ // try getting the element now that updateElement was called
+ element = widget.getData();
+ }
+ if (element == null) {
+ // give up because the parent is still not materialized
+ return;
+ }
+ Item[] children = getChildren(widget);
+ if (children.length == 1 && children[0].getData() == null) {
+ // found a dummy node
+ virtualLazyUpdateChildCount(widget, children.length);
+ children = getChildren(widget);
+ }
+ // DO NOT touch all children
+ return;
+ }
+
+ private void virtualMaterializeItem(TreeItem treeItem) {
+ if (treeItem.getData() != null) {
+ // already materialized
+ return;
+ }
+
+ int index;
+ Widget parent = treeItem.getParentItem();
+ if (parent == null) {
+ parent = treeItem.getParent();
+ }
+ Object parentElement = parent.getData();
+ if (parentElement != null) {
+ if (parent instanceof Tree) {
+ index = ((Tree) parent).indexOf(treeItem);
+ } else {
+ index = ((TreeItem) parent).indexOf(treeItem);
+ }
+ virtualLazyUpdateWidget(parent, index);
+ }
+ }
+
+
/**
* Performs auto expand on an element at the specified path if the auto expand
* level dictates the element should be expanded.
@@ -1978,6 +2026,19 @@ public class InternalTreeModelViewer extends TreeViewer
return -1;
}
+ public boolean getElementChildrenRealized(TreePath parentPath) {
+ Widget parentItem = findItem(parentPath);
+ if (parentItem != null) {
+ Item[] children = getChildren(parentItem);
+ for (int i = 0; i < children.length; i++) {
+ if (children[i].getData() == null) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
public Display getDisplay() {
Control control = getControl();
if (control != null) {
@@ -2193,7 +2254,7 @@ public class InternalTreeModelViewer extends TreeViewer
return null;
}
- public void saveElementState(TreePath path, ModelDelta delta) {
+ public void saveElementState(TreePath path, ModelDelta delta, int flagsToSave) {
Tree tree = (Tree) getControl();
TreeItem[] selection = tree.getSelection();
Set set = new HashSet();
@@ -2206,49 +2267,59 @@ public class InternalTreeModelViewer extends TreeViewer
if (w instanceof Tree) {
delta.setChildCount(
((ITreeModelContentProvider)getContentProvider()).viewToModelCount(path, tree.getItemCount()));
- delta.setFlags(delta.getFlags() | IModelDelta.EXPAND);
+ if ((flagsToSave & IModelDelta.EXPAND) != 0) {
+ delta.setFlags(delta.getFlags() | IModelDelta.EXPAND);
+ }
items = tree.getItems();
} else if (w instanceof TreeItem) {
TreeItem item = (TreeItem)w;
- delta.setChildCount(
- ((ITreeModelContentProvider)getContentProvider()).viewToModelCount(path, item.getItemCount()));
+ int itemCount = item.getItemCount();
+ delta.setChildCount(((ITreeModelContentProvider)getContentProvider()).viewToModelCount(path, itemCount));
if (item.getExpanded()) {
- delta.setFlags(delta.getFlags() | IModelDelta.EXPAND);
+ if ((flagsToSave & IModelDelta.EXPAND) != 0) {
+ delta.setFlags(delta.getFlags() | IModelDelta.EXPAND);
+ }
+ } else if ((flagsToSave & IModelDelta.COLLAPSE) != 0 && itemCount > 0){
+ delta.setFlags(delta.getFlags() | IModelDelta.COLLAPSE);
}
- if (set.contains(item)) {
+
+ if (set.contains(item) && (flagsToSave & IModelDelta.SELECT) != 0) {
delta.setFlags(delta.getFlags() | IModelDelta.SELECT);
}
items = ((TreeItem)w).getItems();
}
if (items != null) {
for (int i = 0; i < items.length; i++) {
- doSaveElementState(path, delta, items[i], set, i);
+ doSaveElementState(path, delta, items[i], set, i, flagsToSave);
}
}
}
- private void doSaveElementState(TreePath parentPath, ModelDelta delta, TreeItem item, Collection set, int index) {
+ private void doSaveElementState(TreePath parentPath, ModelDelta delta, TreeItem item, Collection set, int index, int flagsToSave) {
Object element = item.getData();
if (element != null) {
boolean expanded = item.getExpanded();
boolean selected = set.contains(item);
- if (expanded || selected) {
- int flags = IModelDelta.NO_CHANGE;
- if (expanded) {
- flags = flags | IModelDelta.EXPAND;
- }
- if (selected) {
- flags = flags | IModelDelta.SELECT;
- }
+ int itemCount = item.getItemCount();
+ int flags = IModelDelta.NO_CHANGE;
+ if (expanded && (flagsToSave & IModelDelta.EXPAND) != 0) {
+ flags = flags | IModelDelta.EXPAND;
+ }
+ if (!expanded && (flagsToSave & IModelDelta.COLLAPSE) != 0 && itemCount > 0) {
+ flags = flags | IModelDelta.COLLAPSE;
+ }
+ if (selected && (flagsToSave & IModelDelta.SELECT) != 0) {
+ flags = flags | IModelDelta.SELECT;
+ }
+ if (expanded || flags != IModelDelta.NO_CHANGE) {
int modelIndex = ((ITreeModelContentProvider)getContentProvider()).viewToModelIndex(parentPath, index);
TreePath elementPath = parentPath.createChildPath(element);
- int numChildren = ((ITreeModelContentProvider)getContentProvider()).
- viewToModelCount(elementPath, item.getItemCount());
+ int numChildren = ((ITreeModelContentProvider)getContentProvider()).viewToModelCount(elementPath, itemCount);
ModelDelta childDelta = delta.addNode(element, modelIndex, flags, numChildren);
if (expanded) {
TreeItem[] items = item.getItems();
for (int i = 0; i < items.length; i++) {
- doSaveElementState(elementPath, childDelta, items[i], set, i);
+ doSaveElementState(elementPath, childDelta, items[i], set, i, flagsToSave);
}
}
}
@@ -2302,6 +2373,25 @@ public class InternalTreeModelViewer extends TreeViewer
return false;
}
+ public boolean getHasChildren(Object elementOrTreePath) {
+ if (elementOrTreePath instanceof TreePath &&
+ ((TreePath)elementOrTreePath).getSegmentCount() == 0)
+ {
+ return getTree().getItemCount() > 0;
+ }
+
+ Widget[] items = internalFindItems(elementOrTreePath);
+ if (items != null && items.length > 0) {
+ if (items[0] instanceof TreeItem) {
+ return ((TreeItem)items[0]).getItemCount() > 0;
+ } else {
+ return ((Tree)items[0]).getItemCount() > 0;
+ }
+ }
+
+ return false;
+ }
+
/*
* (non-Javadoc)
* @see org.eclipse.jface.viewers.StructuredViewer#handleSelect(org.eclipse.swt.events.SelectionEvent)
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalVirtualTreeModelViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalVirtualTreeModelViewer.java
index 2b42fb480..427d49b59 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalVirtualTreeModelViewer.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalVirtualTreeModelViewer.java
@@ -22,6 +22,9 @@ import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
import org.eclipse.debug.internal.ui.viewers.model.VirtualItem.Index;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
@@ -51,6 +54,7 @@ import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IMemento;
+import org.eclipse.ui.progress.UIJob;
/**
* A tree model viewer without a UI component.
@@ -170,6 +174,8 @@ public class InternalVirtualTreeModelViewer extends Viewer
*/
private Map fShowColumns = new HashMap();
+ private UIJob fValidateJob;
+
public InternalVirtualTreeModelViewer(Display display, int style, IPresentationContext context) {
fDisplay = display;
fContext = context;
@@ -237,6 +243,10 @@ public class InternalVirtualTreeModelViewer extends Viewer
//Object oldData = item.getData();
associate(element, item);
doUpdate(item);
+ VirtualItem[] children = item.getItems();
+ for (int j = 0; j < children.length; j++) {
+ children[j].setNeedsDataUpdate();
+ }
}
}
// Restore the selection if we are not already in a nested
@@ -249,7 +259,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
handleInvalidSelection(selection, newSelection);
}
}
- fTree.validate();
+ validate();
}
VirtualTree getTree() {
@@ -268,7 +278,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
} else {
// TODO: Implement insert() for element
}
- fTree.validate();
+ validate();
}
public void remove(final Object parentOrTreePath, final int index) {
@@ -282,9 +292,18 @@ public class InternalVirtualTreeModelViewer extends Viewer
VirtualItem parentItem = parentItems[i];
if (parentItem.isDisposed())
continue;
+
+ // Parent item is not expanded so just update its contents so that
+ // the plus sign gets refreshed.
+ if (!parentItem.getExpanded()) {
+ parentItem.setNeedsCountUpdate();
+ parentItem.setItemCount(-1);
+ virtualLazyUpdateHasChildren(parentItem);
+ }
+
if (index < parentItem.getItemCount()) {
-
VirtualItem item =parentItem.getItem(new VirtualItem.Index(index));
+
if (item.getData() != null) {
removedPath = getTreePathFromItem(item);
disassociate(item);
@@ -369,6 +388,15 @@ public class InternalVirtualTreeModelViewer extends Viewer
}
return -1;
}
+
+ public boolean getElementChildrenRealized(TreePath parentPath) {
+ VirtualItem parentItem = findItem(parentPath);
+ if (parentItem != null) {
+ return !parentItem.childrenNeedDataUpdate();
+ }
+ return true;
+ }
+
private ITreeModelLabelProvider getLabelProvider() {
return fLabelProvider;
@@ -382,36 +410,72 @@ public class InternalVirtualTreeModelViewer extends Viewer
public void refresh() {
refresh(fTree);
- getTree().validate();
+ validate();
}
public void refresh(Object element) {
VirtualItem[] items = findItems(element);
for (int i = 0; i < items.length; i++) {
refresh(items[i]);
- getTree().validate(items[i]);
+ validate();
}
}
private void refresh(VirtualItem item) {
- item.setNeedsCountUpdate();
- item.setNeedsLabelUpdate();
+ if (!item.needsDataUpdate()) {
+ if (item.getParent() != null) {
+ item.setNeedsLabelUpdate();
+ virtualLazyUpdateHasChildren(item);
+ }
+
+ VirtualItem[] items = item.getItems();
+ for (int i = 0; i < items.length; i++) {
+ items[i].setNeedsDataUpdate();
+ }
+ }
+ refreshStruct(item);
+ }
+
+ private void refreshStruct(VirtualItem item) {
+ boolean expanded = false;
if (item.getParent() == null) {
+ // root item
virtualLazyUpdateChildCount(item);
- } else if (item.getExpanded()) {
- virtualLazyUpdateChildCount(item);
- } else if (item.getData() != null) {
- virtualLazyUpdateHasChildren(item);
+ expanded = true;
+ } else {
+ if (item.getExpanded()) {
+ virtualLazyUpdateData(item);
+ expanded = true;
+ }
}
-
+
VirtualItem[] items = item.getItems();
for (int i = 0; i < items.length; i++) {
- items[i].setNeedsDataUpdate();
- refresh(items[i]);
+ if (expanded) {
+ refreshStruct(items[i]);
+ } else {
+ item.clear(new VirtualItem.Index(i));
+ }
}
}
-
-
+
+ private void validate() {
+ if (fValidateJob == null) {
+ fValidateJob = new UIJob(getDisplay(), "Virtual viewer validate job") {
+ {
+ setSystem(true);
+ }
+
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ fValidateJob = null;
+ fTree.validate();
+ return Status.OK_STATUS;
+ }
+ };
+ fValidateJob.schedule();
+ }
+ }
+
protected void inputChanged(Object input, Object oldInput) {
resetColumns(input);
}
@@ -483,7 +547,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
}
}
});
- fTree.validate();
+ validate();
}
public void setHasChildren(final Object elementOrTreePath, final boolean hasChildren) {
@@ -506,7 +570,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
if (hasChildren) {
if (!item.getExpanded()) {
item.setItemCount(-1);
- } else if (item.needsCountUpdate()) {
+ } else {
virtualLazyUpdateChildCount(item);
}
}
@@ -514,10 +578,19 @@ public class InternalVirtualTreeModelViewer extends Viewer
}
});
}
+
+ public boolean getHasChildren(Object elementOrTreePath) {
+ VirtualItem[] items = findItems(elementOrTreePath);
+ if (items.length > 0) {
+ return items[0].hasItems();
+ }
+ return false;
+ }
private void virtualLazyUpdateHasChildren(VirtualItem item) {
TreePath treePath;
treePath = getTreePathFromItem(item);
+ item.clearNeedsCountUpdate();
getContentProvider().updateHasChildren(treePath);
}
@@ -595,7 +668,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
if (item.needsLabelUpdate()) {
virtualLazyUpdateLabel(item);
}
- if (item.getExpanded() && item.hasItems() && item.needsCountUpdate()) {
+ if (item.needsCountUpdate() && item.getExpanded()) {
virtualLazyUpdateChildCount(item);
}
}
@@ -723,7 +796,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
}
// Make sure that the new selection is properly revealed.
- fTree.validate();
+ validate();
}
public void update(Object element) {
@@ -735,7 +808,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
public void doUpdate(VirtualItem item) {
item.setNeedsLabelUpdate();
- fTree.validate(item);
+ validate();
}
public ISelection getSelection() {
@@ -784,14 +857,15 @@ public class InternalVirtualTreeModelViewer extends Viewer
if (items.length > 0) {
expandToLevel(items[0], level);
}
- fTree.validate();
+ validate();
}
public void setExpandedState(Object elementOrTreePath, boolean expanded) {
VirtualItem[] items = findItems(elementOrTreePath);
- if (items.length > 0) {
- items[0].setExpanded(expanded);
+ for (int i = 0; i < items.length; i++) {
+ items[i].setExpanded(expanded);
}
+ validate();
}
public boolean getExpandedState(Object elementOrTreePath) {
@@ -808,10 +882,6 @@ public class InternalVirtualTreeModelViewer extends Viewer
return;
}
- if (item.getItemCount() < 0) {
- virtualLazyUpdateChildCount(item);
- item.clearNeedsCountUpdate();
- }
item.setExpanded(true);
if (item.getData() == null) {
@@ -1220,11 +1290,17 @@ public class InternalVirtualTreeModelViewer extends Viewer
}
public int getChildCount(TreePath path) {
+ int childCount = -1;
VirtualItem[] items = findItems(path);
if (items.length > 0) {
- return items[0].getItemCount();
+ childCount = items[0].getItemCount();
+ // Mimic the jface viewer behavior which returns 1 for child count
+ // for an item that has children but is not yet expanded.
+ if (childCount == -1 && items[0].hasItems()) {
+ childCount = 1;
+ }
}
- return -1;
+ return childCount;
}
public Object getChildElement(TreePath path, int index) {
@@ -1241,7 +1317,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
return null;
}
- public void saveElementState(TreePath path, ModelDelta delta) {
+ public void saveElementState(TreePath path, ModelDelta delta, int flagsToSave) {
VirtualTree tree = getTree();
VirtualItem[] selection = tree.getSelection();
Set set = new HashSet();
@@ -1255,32 +1331,40 @@ public class InternalVirtualTreeModelViewer extends Viewer
if (parent != null) {
delta.setChildCount(((ModelContentProvider)getContentProvider()).viewToModelCount(path, parent.getItemCount()));
if (parent.getExpanded()) {
- delta.setFlags(delta.getFlags() | IModelDelta.EXPAND);
+ if ((flagsToSave & IModelDelta.EXPAND) != 0) {
+ delta.setFlags(delta.getFlags() | IModelDelta.EXPAND);
+ }
+ } else if ((flagsToSave & IModelDelta.COLLAPSE) != 0 && parent.hasItems()){
+ delta.setFlags(delta.getFlags() | IModelDelta.COLLAPSE);
}
- if (set.contains(parent)) {
+
+ if (set.contains(parent) && (flagsToSave & IModelDelta.SELECT) != 0) {
delta.setFlags(delta.getFlags() | IModelDelta.SELECT);
}
items = parent.getItems();
for (int i = 0; i < items.length; i++) {
- doSaveElementState(path, delta, items[i], set);
+ doSaveElementState(path, delta, items[i], set, flagsToSave);
}
}
}
- private void doSaveElementState(TreePath parentPath, ModelDelta delta, VirtualItem item, Collection set) {
+ private void doSaveElementState(TreePath parentPath, ModelDelta delta, VirtualItem item, Collection set, int flagsToSave) {
Object element = item.getData();
if (element != null) {
boolean expanded = item.getExpanded();
boolean selected = set.contains(item);
- if (expanded || selected) {
- int flags = IModelDelta.NO_CHANGE;
- if (expanded) {
- flags = flags | IModelDelta.EXPAND;
- }
- if (selected) {
- flags = flags | IModelDelta.SELECT;
- }
+ int flags = IModelDelta.NO_CHANGE;
+ if (expanded && (flagsToSave & IModelDelta.EXPAND) != 0) {
+ flags = flags | IModelDelta.EXPAND;
+ }
+ if (!expanded && (flagsToSave & IModelDelta.COLLAPSE) != 0 && item.hasItems()){
+ flags = flags | IModelDelta.COLLAPSE;
+ }
+ if (selected && (flagsToSave & IModelDelta.SELECT) != 0) {
+ flags = flags | IModelDelta.SELECT;
+ }
+ if (expanded || flags != IModelDelta.NO_CHANGE) {
int modelIndex = ((ModelContentProvider)getContentProvider()).viewToModelIndex(parentPath, item.getIndex().intValue());
TreePath elementPath = parentPath.createChildPath(element);
int numChildren = ((ModelContentProvider)getContentProvider()).viewToModelCount(elementPath, item.getItemCount());
@@ -1288,7 +1372,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
if (expanded) {
VirtualItem[] items = item.getItems();
for (int i = 0; i < items.length; i++) {
- doSaveElementState(elementPath, childDelta, items[i], set);
+ doSaveElementState(elementPath, childDelta, items[i], set, flagsToSave);
}
}
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java
index 647523d10..584d22585 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java
@@ -158,9 +158,17 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
private Object fQueuedRestore = null;
/**
+ * Dummy marker element used in the state delta. The marker indicates
+ * that a given element in the pending state delta has been removed.
+ * It replaces the original element so that it may optionally be
+ * garbage collected.
+ */
+ private final static String ELEMENT_REMOVED = "ELEMENT_REMOVED"; //$NON-NLS-1$
+
+ /**
* Used to determine when restoration delta has been processed
*/
- class CheckState implements IModelDeltaVisitor {
+ protected class CheckState implements IModelDeltaVisitor {
private boolean complete = true;
private IModelDelta topDelta = null;
/* (non-Javadoc)
@@ -168,6 +176,17 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
*/
public boolean visit(IModelDelta delta, int depth) {
if (delta.getFlags() != IModelDelta.NO_CHANGE) {
+ IModelDelta parentDelta = delta.getParentDelta();
+ if (parentDelta != null && parentDelta.getFlags() == IModelDelta.NO_CHANGE) {
+ TreePath deltaPath = getViewerTreePath(delta);
+ if ( ((delta.getElement() instanceof IMemento) && !areMementoUpdatesPending(deltaPath.getParentPath(), delta)) ||
+ (!(delta.getElement() instanceof IMemento) && !areElementUpdatesPending(deltaPath)) )
+ {
+ removeDelta(delta);
+ return false;
+ }
+ }
+
if (delta.getFlags() == IModelDelta.REVEAL && !(delta.getElement() instanceof IMemento)) {
topDelta = delta;
} else {
@@ -185,6 +204,79 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
public IModelDelta getTopItemDelta() {
return topDelta;
}
+
+ private boolean areElementUpdatesPending(TreePath path) {
+ synchronized (fRequestsInProgress) {
+ TreePath parentPath = path.getParentPath();
+ List requests = (List)fWaitingRequests.get(path);
+ if (requests != null) {
+ for (int i = 0; i < requests.size(); i++) {
+ ViewerUpdateMonitor update = (ViewerUpdateMonitor)requests.get(i);
+ if (update instanceof ChildrenUpdate) {
+ return true;
+ }
+ }
+ }
+ requests = (List)fWaitingRequests.get(parentPath);
+ if (requests != null) {
+ for (int i = 0; i < requests.size(); i++) {
+ ViewerUpdateMonitor update = (ViewerUpdateMonitor)requests.get(i);
+ if (update.getElement().equals(path.getLastSegment())) {
+ return true;
+ }
+ }
+ }
+ requests = (List)fRequestsInProgress.get(path);
+ if (requests != null) {
+ for (int i = 0; i < requests.size(); i++) {
+ ViewerUpdateMonitor update = (ViewerUpdateMonitor)requests.get(i);
+ if (update instanceof ChildrenUpdate) {
+ return true;
+ }
+ }
+ }
+ requests = (List)fRequestsInProgress.get(parentPath);
+ if (requests != null) {
+ for (int i = 0; i < requests.size(); i++) {
+ ViewerUpdateMonitor update = (ViewerUpdateMonitor)requests.get(i);
+ if (update.getElement().equals(path.getLastSegment())) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean areMementoUpdatesPending(TreePath path, IModelDelta delta) {
+ if (fCompareRequestsInProgress.size() > 10) {
+ return fCompareRequestsInProgress.containsKey(new CompareRequestKey(path, delta));
+ } else {
+ for (Iterator itr = fCompareRequestsInProgress.keySet().iterator(); itr.hasNext(); ) {
+ CompareRequestKey key = (CompareRequestKey)itr.next();
+ if (key.fPath.equals(path) && delta.getElement().equals(key.fDelta.getElement())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void removeDelta(IModelDelta delta) {
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE RESTORE REMOVED: " + delta.getElement()); //$NON-NLS-1$
+ }
+
+ delta.accept(new IModelDeltaVisitor() {
+ public boolean visit(IModelDelta _visitorDelta, int depth) {
+ ModelDelta visitorDelta = (ModelDelta)_visitorDelta;
+ visitorDelta.setElement(ELEMENT_REMOVED);
+ visitorDelta.setFlags(IModelDelta.NO_CHANGE);
+ return true;
+ }
+ });
+
+ }
}
/**
@@ -340,7 +432,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
public IStatus runInUIThread(IProgressMonitor monitor) {
if (!isDisposed() && input.equals(getViewer().getInput())) {
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("RESTORE: " + stateDelta.toString()); //$NON-NLS-1$
+ System.out.println("STATE RESTORE: " + stateDelta.toString()); //$NON-NLS-1$
}
fViewerStates.remove(keyMementoString);
fPendingState = stateDelta;
@@ -388,14 +480,106 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
/**
* @param delta
*/
- abstract void doRestore(final ModelDelta delta, boolean knowsHasChildren, boolean knowsChildCount);
+ abstract void doRestore(final ModelDelta delta, boolean knowsHasChildren, boolean knowsChildCount, boolean checkChildrenRealized);
+
+ protected void appendToPendingStateDelta(TreePath path) {
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE APPEND BEGIN: " + path.getLastSegment()); //$NON-NLS-1$
+ }
+ // build a model delta representing expansion and selection state
+ final ModelDelta appendDeltaRoot = new ModelDelta(getViewer().getInput(), IModelDelta.NO_CHANGE);
+ ModelDelta delta = appendDeltaRoot;
+ for (int i = 0; i < path.getSegmentCount(); i++) {
+ delta = delta.addNode(path.getSegment(i), IModelDelta.NO_CHANGE);
+ }
+
+ fViewer.saveElementState(path, delta, IModelDelta.COLLAPSE | IModelDelta.EXPAND | IModelDelta.SELECT);
+
+ // Append a marker CONTENT flag to all the delta nodes that contain the EXPAND node. These
+ // markers are used by the restore logic to know when a delta node can be removed.
+ delta.accept(new IModelDeltaVisitor() {
+ public boolean visit(IModelDelta delta, int depth) {
+ if ((delta.getFlags() & IModelDelta.EXPAND) != 0) {
+ ((ModelDelta)delta).setFlags(delta.getFlags() | IModelDelta.CONTENT);
+ }
+ return true;
+ }
+ });
+
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE APPEND DELTA FROM VIEW: " + appendDeltaRoot); //$NON-NLS-1$
+ }
+
+ if (fPendingState != null) {
+ // If the restore for the current input was never completed, preserve
+ // that restore along with the restore that was completed.
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE APPEND OUTSTANDING RESTORE: " + fPendingState); //$NON-NLS-1$
+ }
+
+ IModelDeltaVisitor pendingStateVisitor = new IModelDeltaVisitor() {
+ public boolean visit(IModelDelta pendingDeltaNode, int depth) {
+ // Ignore the top element.
+ if (pendingDeltaNode.getParentDelta() == null) {
+ return true;
+ }
+
+ // Find the node in the save delta which is the parent
+ // of to the current pending delta node.
+ // If the parent node cannot be found, it means that
+ // most likely the user collapsed the parent node before
+ // the children were ever expanded.
+ // If the pending state node already exists in the parent
+ // node, it is already processed and we can skip it.
+ // If the pending state node does not contain any flags,
+ // we can also skip it.
+ ModelDelta saveDeltaNode = findSaveDelta(appendDeltaRoot, pendingDeltaNode);
+ if (saveDeltaNode != null &&
+ !isDeltaInParent(pendingDeltaNode, saveDeltaNode) &&
+ pendingDeltaNode.getFlags() != IModelDelta.NO_CHANGE)
+ {
+ saveDeltaNode.setChildCount(pendingDeltaNode.getParentDelta().getChildCount());
+ copyIntoDelta(pendingDeltaNode, saveDeltaNode);
+ } else {
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE Skipping: " + pendingDeltaNode.getElement()); //$NON-NLS-1$
+ }
+ }
+
+ // If the pending delta node has a memento element, its
+ // children should also be mementos therefore the copy
+ // delta operation should have added all the children
+ // of this pending delta node into the save delta.
+ if (pendingDeltaNode.getElement() instanceof IMemento) {
+ return false;
+ } else {
+ return pendingDeltaNode.getChildCount() > 0;
+ }
+ }
+ };
+ fPendingState.accept(pendingStateVisitor);
+ }
+
+ if (appendDeltaRoot.getChildDeltas().length > 0) {
+ // Set the new delta root as the pending state delta.
+ fPendingState = appendDeltaRoot;
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE APPEND NEW PENDING STATE DELTA " + fPendingState); //$NON-NLS-1$
+ }
+ } else {
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE APPEND CANCELED, NO DATA"); //$NON-NLS-1$
+ }
+ }
+ }
+
/**
* Perform any restoration required for the given tree path.
*
* @param path
*/
- protected synchronized void doRestore(final TreePath path, final int modelIndex, final boolean knowsHasChildren, final boolean knowsChildCount) {
+ protected synchronized void doRestore(final TreePath path, final int modelIndex, final boolean knowsHasChildren, final boolean knowsChildCount, final boolean checkChildrenRealized) {
if (fPendingState == null) {
return;
}
@@ -420,10 +604,13 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
// If found, just update the flags.
existingRequest.setKnowsHasChildren(knowsHasChildren);
existingRequest.setKnowsChildCount(knowsChildCount);
+ existingRequest.setCheckChildrenRealized(checkChildrenRealized);
} else {
// Start a new compare request
ElementCompareRequest compareRequest = new ElementCompareRequest(
- ModelContentProvider.this, getViewer().getInput(), potentialMatch, path, (IMemento) element, (ModelDelta)delta, modelIndex, knowsHasChildren, knowsChildCount);
+ ModelContentProvider.this, getViewer().getInput(), potentialMatch, path,
+ (IMemento) element, (ModelDelta)delta, modelIndex,
+ knowsHasChildren, knowsChildCount, checkChildrenRealized);
fCompareRequestsInProgress.put(key, compareRequest);
provider.compareElements(new IElementCompareRequest[]{ compareRequest });
}
@@ -431,7 +618,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
} else if (element.equals(potentialMatch)) {
// Element comparison already succeeded, and it matches our element.
// Call restore with delta to process the delta flags.
- doRestore((ModelDelta)delta, knowsHasChildren, knowsChildCount);
+ doRestore((ModelDelta)delta, knowsHasChildren, knowsChildCount, checkChildrenRealized);
}
return false;
}
@@ -447,7 +634,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
if (!request.isCanceled()) {
if (request.isEqual()) {
delta.setElement(request.getElement());
- doRestore(delta, request.knowsHasChildren(), request.knowChildCount());
+ doRestore(delta, request.knowsHasChildren(), request.knowChildCount(), request.checkChildrenRealized());
} else if (request.getModelIndex() != -1){
// Comparison failed.
// Check if the delta has a reveal flag, and if its index matches the index
@@ -469,21 +656,21 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
IElementMementoProvider stateProvider = ViewerAdapterService.getMementoProvider(input);
if (stateProvider != null) {
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("SAVE BEGIN: " + input); //$NON-NLS-1$
+ System.out.println("STATE SAVE BEGIN: " + input); //$NON-NLS-1$
}
// build a model delta representing expansion and selection state
final ModelDelta saveDeltaRoot = new ModelDelta(input, IModelDelta.NO_CHANGE);
buildViewerState(saveDeltaRoot);
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("SAVE DELTA FROM VIEW: " + saveDeltaRoot); //$NON-NLS-1$
+ System.out.println("STATE SAVE DELTA FROM VIEW: " + saveDeltaRoot); //$NON-NLS-1$
}
if (fPendingState != null) {
// If the restore for the current input was never completed, preserve
// that restore along with the restore that was completed.
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("SAVE OUTSTANDING RESTORE: " + fPendingState); //$NON-NLS-1$
+ System.out.println("STATE SAVE OUTSTANDING RESTORE: " + fPendingState); //$NON-NLS-1$
}
IModelDeltaVisitor pendingStateVisitor = new IModelDeltaVisitor() {
@@ -520,7 +707,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
copyIntoDelta(pendingDeltaNode, saveDeltaNode);
} else {
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println(" Skipping: " + pendingDeltaNode.getElement()); //$NON-NLS-1$
+ System.out.println("STATE Skipping: " + pendingDeltaNode.getElement()); //$NON-NLS-1$
}
}
@@ -543,7 +730,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
encodeDelta(saveDeltaRoot, stateProvider);
} else {
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("SAVE CANCELED, NO DATA"); //$NON-NLS-1$
+ System.out.println("STATE SAVE CANCELED, NO DATA"); //$NON-NLS-1$
}
}
}
@@ -570,7 +757,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
deltaPath.addFirst(delta);
}
- // For each element in the patch of the pendingStateDelta, find the corresponding
+ // For each element in the path of the pendingStateDelta, find the corresponding
// element in the partially restored delta being saved.
Iterator itr = deltaPath.iterator();
// Skip the root element
@@ -649,7 +836,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
DebugUIPlugin.log(e);
}
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("SAVE COMPLETED: " + rootDelta); //$NON-NLS-1$
+ System.out.println("STATE SAVE COMPLETED: " + rootDelta); //$NON-NLS-1$
}
stateSaveComplete(this);
}
@@ -662,7 +849,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
requests.clear();
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("SAVE ABORTED: " + rootDelta.getElement()); //$NON-NLS-1$
+ System.out.println("STATE SAVE ABORTED: " + rootDelta.getElement()); //$NON-NLS-1$
}
stateSaveComplete(this);
}
@@ -1237,7 +1424,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
fPendingState.accept(state);
if (state.isComplete()) {
if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("RESTORE COMPELTE: " + fPendingState); //$NON-NLS-1$
+ System.out.println("STATE RESTORE COMPELTE: " + fPendingState); //$NON-NLS-1$
}
fPendingState = null;
}
@@ -1375,6 +1562,8 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
}
}
+
+
/**
* Returns whether this given request should be run, or should wait for parent
@@ -1419,6 +1608,34 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
}
+ protected boolean getElementChildrenRealized(TreePath path) {
+ synchronized (fRequestsInProgress) {
+ List requests = (List)fWaitingRequests.get(path);
+ if (requests != null) {
+ for (int i = 0; i < requests.size(); i++) {
+ if (requests.get(i) instanceof ChildrenUpdate) {
+ return false;
+ }
+ }
+ }
+ requests = (List)fRequestsInProgress.get(path);
+ if (requests != null) {
+ int numChildrenUpdateRequests = 0;
+ for (int i = 0; i < requests.size(); i++) {
+ if (requests.get(i) instanceof ChildrenUpdate) {
+ if (++numChildrenUpdateRequests > 1) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return getViewer().getElementChildrenRealized(path);
+ }
+
+
+
/**
* Triggers waiting requests based on the given request that just completed.
*
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/SubTreeModelViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/SubTreeModelViewer.java
index 7156008c4..bc3c04cc5 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/SubTreeModelViewer.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/SubTreeModelViewer.java
@@ -197,6 +197,18 @@ public class SubTreeModelViewer extends TreeModelViewer {
return -1;
}
+ public boolean getHasChildren(Object elementOrTreePath) {
+ if (elementOrTreePath instanceof TreePath) {
+ TreePath path = (TreePath)elementOrTreePath;
+ if (path.startsWith(fRootPath, null)) {
+ return SubTreeModelViewer.this.getHasChildren(createSubPath(path));
+ }
+ } else {
+ return SubTreeModelViewer.this.getHasChildren(elementOrTreePath);
+ }
+ return false;
+ }
+
public Object getChildElement(TreePath path, int index) {
if (path.startsWith(fRootPath, null)) {
return SubTreeModelViewer.this.getChildElement(createSubPath(path), index);
@@ -214,6 +226,13 @@ public class SubTreeModelViewer extends TreeModelViewer {
}
return -1;
}
+
+ public boolean getElementChildrenRealized(TreePath parentPath) {
+ if (parentPath.startsWith(fRootPath, null)) {
+ return SubTreeModelViewer.this.getElementChildrenRealized(createSubPath(parentPath));
+ }
+ return true;
+ }
public void setElementData(TreePath path, int numColumns, String[] labels, ImageDescriptor[] images, FontData[] fontDatas, RGB[] foregrounds, RGB[] backgrounds) {
if (path.startsWith(fRootPath, null)) {
@@ -289,8 +308,8 @@ public class SubTreeModelViewer extends TreeModelViewer {
SubTreeModelViewer.this.removeViewerUpdateListener(listener);
}
- public void saveElementState(TreePath path, ModelDelta delta) {
- SubTreeModelViewer.this.saveElementState(path, delta);
+ public void saveElementState(TreePath path, ModelDelta delta, int deltaFlags) {
+ SubTreeModelViewer.this.saveElementState(path, delta, deltaFlags);
}
public void setAutoExpandLevel(int level) {
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java
index 07041e627..2149b3896 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java
@@ -112,7 +112,7 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
getViewer().replace(parentPath, viewIndex, element);
TreePath childPath = parentPath.createChildPath(element);
updateHasChildren(childPath);
- doRestore(childPath, modelIndex, false, false);
+ doRestore(childPath, modelIndex, false, false, false);
}
} else {
if (DEBUG_CONTENT_PROVIDER && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
@@ -134,6 +134,7 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
}
TreePath treePath = getViewerTreePath(delta);
cancelSubtreeUpdates(treePath);
+ appendToPendingStateDelta(treePath);
getViewer().refresh(getElement(treePath));
}
@@ -413,7 +414,7 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
*/
protected void buildViewerState(ModelDelta delta) {
ITreeModelContentProviderTarget viewer = getViewer();
- viewer.saveElementState(EMPTY_TREE_PATH, delta);
+ viewer.saveElementState(EMPTY_TREE_PATH, delta, IModelDelta.SELECT | IModelDelta.EXPAND);
// Add memento for top item if it is mapped to an element. The reveal memento
// is in its own path to avoid requesting unnecessary data when restoring it.
@@ -455,7 +456,7 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
for (int i = 0; i < count; i++) {
Object data = getViewer().getChildElement(TreePath.EMPTY, i);
if (data != null) {
- doRestore(new TreePath(new Object[]{data}), i, false, false);
+ doRestore(new TreePath(new Object[]{data}), i, false, false, false);
}
}
@@ -538,13 +539,26 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
/**
* @param delta
*/
- void doRestore(ModelDelta delta, boolean knowsHasChildren, boolean knowsChildCount) {
+ void doRestore(ModelDelta delta, boolean knowsHasChildren, boolean knowsChildCount, boolean checkChildrenRealized) {
TreePath treePath = getViewerTreePath(delta);
ITreeModelContentProviderTarget viewer = getViewer();
- // Attempt to expand the node only if the children are known.
- if (knowsHasChildren && (delta.getFlags() & IModelDelta.EXPAND) != 0) {
- viewer.expandToLevel(treePath, 1);
- delta.setFlags(delta.getFlags() & ~IModelDelta.EXPAND);
+
+ // Attempt to expand the node only if the children are known.
+ if (knowsHasChildren) {
+ if ((delta.getFlags() & IModelDelta.EXPAND) != 0) {
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE RESTORE EXPAND: " + treePath.getLastSegment()); //$NON-NLS-1$
+ }
+ viewer.expandToLevel(treePath, 1);
+ delta.setFlags(delta.getFlags() & ~IModelDelta.EXPAND);
+ }
+ if ((delta.getFlags() & IModelDelta.COLLAPSE) != 0) {
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE RESTORE COLLAPSE: " + treePath.getLastSegment()); //$NON-NLS-1$
+ }
+ getViewer().setExpandedState(treePath, false);
+ delta.setFlags(delta.getFlags() & ~IModelDelta.COLLAPSE);
+ }
}
if ((delta.getFlags() & IModelDelta.SELECT) != 0) {
viewer.setSelection(new TreeSelection(treePath), false, false);
@@ -569,6 +583,9 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
TreePath parentPath = treePath.getParentPath();
int index = viewer.findElementIndex(parentPath, treePath.getLastSegment());
if (index >= 0) {
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE RESTORE REVEAL: " + treePath.getLastSegment()); //$NON-NLS-1$
+ }
viewer.reveal(parentPath, index);
}
}
@@ -597,6 +614,19 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
}
}
+ // Some children of this element were just updated. If all its
+ // children are now realized, clear out any elements that still
+ // have flags, because they represent elements that were removed.
+ if ((checkChildrenRealized && getElementChildrenRealized(treePath)) ||
+ (knowsHasChildren && !viewer.getHasChildren(treePath)) )
+ {
+ if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE RESTORE CONTENT: " + treePath.getLastSegment()); //$NON-NLS-1$
+ }
+ delta.setFlags(delta.getFlags() & ~IModelDelta.CONTENT);
+ }
+
checkIfRestoreComplete();
}
+
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/VirtualItem.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/VirtualItem.java
index 337ef7197..e5e022e2e 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/VirtualItem.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/VirtualItem.java
@@ -15,6 +15,8 @@ import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
+import org.eclipse.core.runtime.Assert;
+
/**
* Virtual item, which is analogous to the SWT's tree item.
*
@@ -63,7 +65,7 @@ class VirtualItem {
}
public int compareTo(Object obj) {
- return obj instanceof Index ? ((Index)obj).fIndexValue.compareTo(fIndexValue) : 0;
+ return obj instanceof Index ? fIndexValue.compareTo(((Index)obj).fIndexValue) : 0;
}
public String toString() {
@@ -226,9 +228,6 @@ class VirtualItem {
void setData(Object data) {
fData.put(ELEMENT_DATA_KEY, data);
- if (data == null) {
- fNeedsDataUpdate = true;
- }
}
Object getData () {
@@ -236,10 +235,18 @@ class VirtualItem {
}
void setExpanded(boolean expanded) {
+ if (fExpanded == expanded) {
+ return;
+ }
fExpanded = expanded;
+
+ if (fExpanded && getItemCount() == -1) {
+ setNeedsCountUpdate();
+ }
+
- //Assert.assrt(!fExpanded || hasItems());
-
+ Assert.isTrue(!fExpanded || hasItems());
+
// If collapsed, make sure that all the children are collapsed as well.
if (!fExpanded) {
for (Iterator itr = fItems.values().iterator(); itr.hasNext();) {
@@ -307,6 +314,22 @@ class VirtualItem {
return item;
}
+ boolean childrenNeedDataUpdate() {
+ if (getItemCount() == 0) {
+ return false;
+ }
+ if (fItems == null || fItems.size() != fItemCount) {
+ return true;
+ }
+ for (Iterator itr = fItems.values().iterator(); itr.hasNext();) {
+ VirtualItem child = (VirtualItem)itr.next();
+ if (child.needsDataUpdate()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
VirtualItem[] getItems() {
return (VirtualItem[]) fItems.values().toArray(new VirtualItem[fItems.size()]);
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelDelta.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelDelta.java
index 9b54befb8..18fd862ed 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelDelta.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelDelta.java
@@ -116,6 +116,7 @@ public interface IModelDelta {
* SELECT and REVEAL flags.
*
* @see IModelSelectionPolicy
+= * @since 3.5
*/
public static int FORCE = 1 << 26;
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/ModelDelta.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/ModelDelta.java
index 868cb23ab..0f900c3d1 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/ModelDelta.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/ModelDelta.java
@@ -258,6 +258,9 @@ public class ModelDelta implements IModelDelta {
if ((flags & IModelDelta.CONTENT) > 0) {
buf.append("CONTENT | "); //$NON-NLS-1$
}
+ if ((flags & IModelDelta.COLLAPSE) > 0) {
+ buf.append("COLLAPSE | "); //$NON-NLS-1$
+ }
if ((flags & IModelDelta.EXPAND) > 0) {
buf.append("EXPAND | "); //$NON-NLS-1$
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchViewBreadcrumb.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchViewBreadcrumb.java
index 19d35d85d..6542fab63 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchViewBreadcrumb.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchViewBreadcrumb.java
@@ -390,7 +390,7 @@ public class LaunchViewBreadcrumb extends AbstractBreadcrumb implements IDebugCo
fDropDownViewer.setFilters(filters);
ModelDelta stateDelta = new ModelDelta(launchViewInput, IModelDelta.NO_CHANGE);
- fTreeViewer.saveElementState(TreePath.EMPTY, stateDelta);
+ fTreeViewer.saveElementState(TreePath.EMPTY, stateDelta, IModelDelta.EXPAND | IModelDelta.SELECT);
// If we do not want to expand the elements in the drop-down.
// Prune the delta to only select the element in the
@@ -483,7 +483,7 @@ public class LaunchViewBreadcrumb extends AbstractBreadcrumb implements IDebugCo
}
// Create the delta and save the drop-down viewer's state to it.
- fDropDownViewer.saveElementState(TreePath.EMPTY, delta);
+ fDropDownViewer.saveElementState(TreePath.EMPTY, delta, IModelDelta.EXPAND | IModelDelta.SELECT);
// Add the IModelDelta.FORCE flag to override the current selection in view.
rootDelta.accept(new IModelDeltaVisitor(){

Back to the top