Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarin Wright2008-03-24 11:26:18 -0400
committerDarin Wright2008-03-24 11:26:18 -0400
commitd26d56400f1b25f26e55a1635c65acfc0de0eaeb (patch)
tree288155eca9149d95987885bcc60080f8c2549b56
parent6888aa28f83e6631ab69a311172eefca6991c722 (diff)
downloadeclipse.platform.debug-d26d56400f1b25f26e55a1635c65acfc0de0eaeb.tar.gz
eclipse.platform.debug-d26d56400f1b25f26e55a1635c65acfc0de0eaeb.tar.xz
eclipse.platform.debug-d26d56400f1b25f26e55a1635c65acfc0de0eaeb.zip
Bug 188704 - Top index not maintained properly in variables / registers view.
-rw-r--r--org.eclipse.debug.ui/.options1
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenCountUpdate.java4
-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.java54
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/HasChildrenUpdate.java5
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java328
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java194
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/ModelDelta.java32
8 files changed, 484 insertions, 138 deletions
diff --git a/org.eclipse.debug.ui/.options b/org.eclipse.debug.ui/.options
index cba192bd8..2bf4af3b5 100644
--- a/org.eclipse.debug.ui/.options
+++ b/org.eclipse.debug.ui/.options
@@ -6,3 +6,4 @@ org.eclipse.debug.ui/debug/viewers/contentProvider = false
org.eclipse.debug.ui/debug/viewers/updateSequence = false
org.eclipse.debug.ui/debug/contextlaunching = false
org.eclipse.debug.ui/debug/launchhistory = false
+org.eclipse.debug.ui/debug/viewers/stateSaveRestore = false
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 f09f06ff5..3879f93c3 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Wind River Systems - Fix for viewer state save/restore [188704]
*******************************************************************************/
package org.eclipse.debug.internal.ui.viewers.model;
@@ -51,6 +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$
}
((TreeViewer)(getContentProvider().getViewer())).setChildCount(elementPath, viewCount);
+ getContentProvider().doRestore(getElementPath(), -1, true, true);
}
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 3818599ce..2d9f89842 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Wind River Systems - Fix for viewer state save/restore [188704]
*******************************************************************************/
package org.eclipse.debug.internal.ui.viewers.model;
@@ -76,6 +77,7 @@ public class ChildrenUpdate extends ViewerUpdateMonitor implements IChildrenUpda
}
TreePath childPath = elementPath.createChildPath(element);
provider.updateHasChildren(childPath);
+ provider.doRestore(childPath, modelIndex, false, false);
}
}
}
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 bcabac9f2..66b44cc5f 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006 IBM Corporation and others.
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,13 +7,18 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Wind River Systems - Fix for viewer state save/restore [188704]
*******************************************************************************/
package org.eclipse.debug.internal.ui.viewers.model;
+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.provisional.IElementCompareRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.ui.IMemento;
+import org.eclipse.ui.progress.UIJob;
/**
* @since 3.3
@@ -21,16 +26,24 @@ import org.eclipse.ui.IMemento;
class ElementCompareRequest extends MementoUpdate implements IElementCompareRequest {
private boolean fEqual;
+ private final int fModelIndex;
private ModelDelta fDelta;
+ private boolean fKnowsHasChildren;
+ private boolean fKnowsChildCount;
+
+
/**
* @param context
* @param element
* @param memento
*/
- public ElementCompareRequest(ModelContentProvider provider, Object viewerInput, Object element, TreePath elementPath, IMemento memento, ModelDelta delta) {
+ public ElementCompareRequest(ModelContentProvider provider, Object viewerInput, Object element, TreePath elementPath, IMemento memento, ModelDelta delta, int modelIndex, boolean hasChildren, boolean knowsChildCount) {
super(provider, viewerInput, provider.getPresentationContext(), element, elementPath, memento);
fProvider = provider;
fDelta = delta;
+ fModelIndex = modelIndex;
+ fKnowsHasChildren = hasChildren;
+ fKnowsChildCount = knowsChildCount;
}
/* (non-Javadoc)
@@ -44,14 +57,43 @@ class ElementCompareRequest extends MementoUpdate implements IElementCompareRequ
* @see org.eclipse.core.runtime.IProgressMonitor#done()
*/
public void done() {
- if (isEqual()) {
- fDelta.setElement(getElement());
- fProvider.doRestore(fDelta);
- }
+ UIJob job = new UIJob("restore delta") { //$NON-NLS-1$
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ if (!isCanceled()) {
+ fProvider.compareFinished(ElementCompareRequest.this, fDelta);
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.setSystem(true);
+ job.schedule();
}
boolean isEqual() {
return fEqual;
}
+
+ ModelDelta getDelta() {
+ return fDelta;
+ }
+
+ int getModelIndex() {
+ return fModelIndex;
+ }
+ void setKnowsHasChildren(boolean hasChildren) {
+ fKnowsHasChildren = hasChildren;
+ }
+
+ boolean knowsHasChildren() {
+ return fKnowsHasChildren;
+ }
+
+ void setKnowsChildCount(boolean childCount) {
+ fKnowsChildCount = childCount;
+ }
+
+ boolean knowChildCount() {
+ return fKnowsChildCount;
+ }
}
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 f7ad83330..9f5110b9f 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Wind River Systems - Fix for viewer state save/restore [188704]
*******************************************************************************/
package org.eclipse.debug.internal.ui.viewers.model;
@@ -52,7 +53,7 @@ class HasChildrenUpdate extends ViewerUpdateMonitor implements IHasChildrenUpdat
((InternalTreeModelViewer)contentProvider.getViewer()).autoExpand(elementPath);
}
if (elementPath.getSegmentCount() > 0) {
- contentProvider.doRestore(elementPath);
+ getContentProvider().doRestore(getElementPath(), -1, true, false);
}
}
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 15032c187..6fb2940c5 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Pawel Piech - Wind River - Bug 205335: ModelContentProvider does not cancel stale updates when switching viewer input
+ * Wind River Systems - Fix for viewer state save/restore [188704]
*******************************************************************************/
package org.eclipse.debug.internal.ui.viewers.model;
@@ -18,6 +19,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -102,6 +104,29 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
* Pending viewer state to be restored
*/
private ModelDelta fPendingState = null;
+
+ private static class CompareRequestKey {
+ CompareRequestKey(TreePath path, IModelDelta delta) {
+ fPath = path;
+ fDelta = delta;
+ }
+ TreePath fPath;
+ IModelDelta fDelta;
+
+ public boolean equals(Object obj) {
+ if (obj instanceof CompareRequestKey) {
+ CompareRequestKey key = (CompareRequestKey)obj;
+ return key.fDelta.equals(fDelta) && key.fPath.equals(fPath);
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return fDelta.hashCode() + fPath.hashCode();
+ }
+ }
+
+ private Map fCompareRequestsInProgress = new HashMap();
/**
* Set of IMementoManager's that are currently saving state
@@ -174,12 +199,15 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
// debug flags
public static boolean DEBUG_CONTENT_PROVIDER = false;
public static boolean DEBUG_UPDATE_SEQUENCE = false;
+ public static boolean DEBUG_STATE_SAVE_RESTORE = false;
static {
DEBUG_CONTENT_PROVIDER = DebugUIPlugin.DEBUG && "true".equals( //$NON-NLS-1$
Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/contentProvider")); //$NON-NLS-1$
DEBUG_UPDATE_SEQUENCE = DebugUIPlugin.DEBUG && "true".equals( //$NON-NLS-1$
Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/updateSequence")); //$NON-NLS-1$
+ DEBUG_STATE_SAVE_RESTORE = DebugUIPlugin.DEBUG && "true".equals( //$NON-NLS-1$
+ Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/stateSaveRestore")); //$NON-NLS-1$
}
/*
@@ -219,9 +247,14 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
public synchronized void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
fViewer = viewer;
if (oldInput != null) {
+ for (Iterator itr = fCompareRequestsInProgress.values().iterator(); itr.hasNext(); ) {
+ ((ElementCompareRequest)itr.next()).cancel();
+ itr.remove();
+ }
saveViewerState(oldInput);
}
if (newInput != oldInput) {
+ cancelSubtreeUpdates(TreePath.EMPTY);
disposeAllModelProxies();
cancelSubtreeUpdates(TreePath.EMPTY);
fTransform.clear();
@@ -251,7 +284,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
*
* @param input viewer input
*/
- private synchronized void startRestoreViewerState(final Object input) {
+ private synchronized void startRestoreViewerState(final Object input) {
fPendingState = null;
final IElementMementoProvider defaultProvider = ViewerAdapterService.getMementoProvider(input);
if (defaultProvider != null) {
@@ -271,18 +304,20 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
StringWriter writer = new StringWriter();
try {
keyMemento.save(writer);
- final ModelDelta stateDelta = (ModelDelta) fViewerStates.remove(writer.toString());
+ final String keyMementoString = writer.toString();
+ final ModelDelta stateDelta = (ModelDelta) fViewerStates.get(keyMementoString);
if (stateDelta != null) {
- if (DEBUG_CONTENT_PROVIDER) {
- System.out.println("RESTORE: " + stateDelta.toString()); //$NON-NLS-1$
- }
stateDelta.setElement(input);
// begin restoration
UIJob job = new UIJob("restore state") { //$NON-NLS-1$
public IStatus runInUIThread(IProgressMonitor monitor) {
if (!isDisposed() && input.equals(getViewer().getInput())) {
+ if (DEBUG_STATE_SAVE_RESTORE) {
+ System.out.println("RESTORE: " + stateDelta.toString()); //$NON-NLS-1$
+ }
+ fViewerStates.remove(keyMementoString);
fPendingState = stateDelta;
- doInitialRestore();
+ doInitialRestore(fPendingState);
}
return Status.OK_STATUS;
}
@@ -318,71 +353,240 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
}
+ /**
+ * Restore selection/expansion based on items already in the viewer
+ */
+ protected abstract void doInitialRestore(ModelDelta delta);
+
/**
- * Restore selection/expansion based on items already in the viewer
- */
- abstract protected void doInitialRestore();
-
- /**
- * @param delta
- */
- abstract void doRestore(final ModelDelta delta);
-
+ * @param delta
+ */
+ abstract void doRestore(final ModelDelta delta, boolean knowsHasChildren, boolean knowsChildCount);
+
/**
* Perform any restoration required for the given tree path.
*
* @param path
*/
- protected synchronized void doRestore(final TreePath path) {
+ protected synchronized void doRestore(final TreePath path, final int modelIndex, final boolean knowsHasChildren, final boolean knowsChildCount) {
if (fPendingState == null) {
return;
}
+
IModelDeltaVisitor visitor = new IModelDeltaVisitor() {
- public boolean visit(IModelDelta delta, int depth) {
- if (delta.getParentDelta() == null) {
- return true;
- }
+ public boolean visit(final IModelDelta delta, int depth) {
+
Object element = delta.getElement();
- Object potentialMatch = path.getSegment(depth - 1);
- if (element instanceof IMemento) {
- IElementMementoProvider provider = ViewerAdapterService.getMementoProvider(potentialMatch);
- if (provider == null) {
- provider = ViewerAdapterService.getMementoProvider(getViewer().getInput());
- }
- if (provider != null) {
- provider.compareElements(new IElementCompareRequest[]{
- new ElementCompareRequest(ModelContentProvider.this, getViewer().getInput(),
- potentialMatch, path, (IMemento) element, (ModelDelta)delta)});
- }
- } else {
- if (element.equals(potentialMatch)) {
- // already processed - visit children
- return path.getSegmentCount() > depth;
+ Object potentialMatch = depth != 0 ? path.getSegment(depth - 1) : getViewer().getInput();
+ // Only process if the depth in the delta matches the tree path.
+ if (depth == path.getSegmentCount()) {
+ if (element instanceof IMemento) {
+ IElementMementoProvider provider = ViewerAdapterService.getMementoProvider(potentialMatch);
+ if (provider == null) {
+ provider = ViewerAdapterService.getMementoProvider(getViewer().getInput());
+ }
+ if (provider != null) {
+ CompareRequestKey key = new CompareRequestKey(path, delta);
+ ElementCompareRequest existingRequest = (ElementCompareRequest)fCompareRequestsInProgress.get(key);
+ if (existingRequest != null) {
+ // Check all the running compare updates for a matching tree path.
+ // If found, just update the flags.
+ existingRequest.setKnowsHasChildren(knowsHasChildren);
+ existingRequest.setKnowsChildCount(knowsChildCount);
+ } else {
+ // Start a new compare request
+ ElementCompareRequest compareRequest = new ElementCompareRequest(
+ ModelContentProvider.this, getViewer().getInput(), potentialMatch, path, (IMemento) element, (ModelDelta)delta, modelIndex, knowsHasChildren, knowsChildCount);
+ fCompareRequestsInProgress.put(key, compareRequest);
+ provider.compareElements(new IElementCompareRequest[]{ compareRequest });
+ }
+ }
+ } 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);
}
- }
- return false;
+ return false;
+ }
+ // Only follow the paths that match the delta.
+ return element.equals(potentialMatch);
}
};
fPendingState.accept(visitor);
}
+ void compareFinished(ElementCompareRequest request, ModelDelta delta) {
+ fCompareRequestsInProgress.remove(request);
+ if (!request.isCanceled()) {
+ if (request.isEqual()) {
+ delta.setElement(request.getElement());
+ doRestore(delta, request.knowsHasChildren(), request.knowChildCount());
+ } else if (request.getModelIndex() != -1){
+ // Comparison failed.
+ // Check if the delta has a reveal flag, and if its index matches the index
+ // of the element that it was compared against. If this is the case,
+ // strip the reveal flag from the delta as it is most likely not applicable
+ // anymore.
+ if ( (delta.getFlags() & IModelDelta.REVEAL) != 0 && delta.getIndex() == request.getModelIndex() ) {
+ delta.setFlags(delta.getFlags() & ~IModelDelta.REVEAL);
+ }
+ }
+ }
+ }
+
/**
* Saves the viewer's state for the previous input.
- *
- * @param oldInput
+ * * @param oldInput
*/
protected void saveViewerState(Object input) {
IElementMementoProvider stateProvider = ViewerAdapterService.getMementoProvider(input);
if (stateProvider != null) {
+ if (DEBUG_STATE_SAVE_RESTORE) {
+ System.out.println("SAVE BEGIN: " + input); //$NON-NLS-1$
+ }
+
// build a model delta representing expansion and selection state
- ModelDelta delta = new ModelDelta(input, IModelDelta.NO_CHANGE);
- buildViewerState(delta);
- if (delta.getChildDeltas().length > 0) {
+ final ModelDelta saveDeltaRoot = new ModelDelta(input, IModelDelta.NO_CHANGE);
+ buildViewerState(saveDeltaRoot);
+ if (DEBUG_STATE_SAVE_RESTORE) {
+ System.out.println("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) {
+ System.out.println("SAVE 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(saveDeltaRoot, pendingDeltaNode);
+ if (saveDeltaNode != null &&
+ !isDeltaInParent(pendingDeltaNode, saveDeltaNode) &&
+ pendingDeltaNode.getFlags() != IModelDelta.NO_CHANGE)
+ {
+ // There should be only one delta element with
+ // the REVEAL flag in the entire save delta. The
+ // reveal flag in the pending delta trumps the one
+ // in the save delta because most likely the restore
+ // operation did not yet complete the reveal
+ // operation.
+ if ( (pendingDeltaNode.getFlags() & IModelDelta.REVEAL) != 0) {
+ clearRevealFlag(saveDeltaRoot);
+ }
+ saveDeltaNode.setChildCount(pendingDeltaNode.getParentDelta().getChildCount());
+ copyIntoDelta(pendingDeltaNode, saveDeltaNode);
+ } else {
+ if (DEBUG_STATE_SAVE_RESTORE) {
+ System.out.println(" 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 (saveDeltaRoot.getChildDeltas().length > 0) {
// encode delta with mementos in place of elements, in non-UI thread
- encodeDelta(delta, stateProvider);
+ encodeDelta(saveDeltaRoot, stateProvider);
+ } else {
+ if (DEBUG_STATE_SAVE_RESTORE) {
+ System.out.println("SAVE CANCELED, NO DATA"); //$NON-NLS-1$
+ }
}
}
}
+
+ private void clearRevealFlag(ModelDelta saveRootDelta) {
+ IModelDeltaVisitor clearDeltaVisitor = new IModelDeltaVisitor() {
+ public boolean visit(IModelDelta delta, int depth) {
+ if ( (delta.getFlags() & IModelDelta.REVEAL) != 0) {
+ ((ModelDelta)delta).setFlags(delta.getFlags() & ~IModelDelta.REVEAL);
+ }
+ return true;
+ }
+ };
+ saveRootDelta.accept(clearDeltaVisitor);
+ }
+
+ private ModelDelta findSaveDelta(ModelDelta saveDeltaRoot, IModelDelta pendingStateDelta) {
+ // Create a path of elements to the pendingStateDelta.
+ LinkedList deltaPath = new LinkedList();
+ IModelDelta delta = pendingStateDelta;
+ while (delta.getParentDelta() != null) {
+ delta = delta.getParentDelta();
+ deltaPath.addFirst(delta);
+ }
+
+ // For each element in the patch of the pendingStateDelta, find the corresponding
+ // element in the partially restored delta being saved.
+ Iterator itr = deltaPath.iterator();
+ // Skip the root element
+ itr.next();
+ ModelDelta saveDelta = saveDeltaRoot;
+ outer: while (itr.hasNext()) {
+ IModelDelta itrDelta = (IModelDelta)itr.next();
+ for (int i = 0; i < saveDelta.getChildDeltas().length; i++) {
+ if ( deltasEqual(saveDelta.getChildDeltas()[i], itrDelta) ) {
+ saveDelta = (ModelDelta)saveDelta.getChildDeltas()[i];
+ continue outer;
+ }
+ }
+ return null;
+ }
+ return saveDelta;
+ }
+
+ private boolean deltasEqual(IModelDelta d1, IModelDelta d2) {
+ // Note: don't compare the child count, because it is
+ // incorrect for nodes which have not been expanded yet.
+ return d1.getElement().equals(d2.getElement()) &&
+ d1.getIndex() == d2.getIndex();
+ }
+
+ private boolean isDeltaInParent(IModelDelta delta, ModelDelta destParent) {
+ for (int i = 0; i < destParent.getChildDeltas().length; i++) {
+ if ( deltasEqual(destParent.getChildDeltas()[i], delta) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void copyIntoDelta(IModelDelta delta, ModelDelta destParent) {
+ // Search the destination and make sure that the same delta
+ // doesn't exist already.
+
+ ModelDelta newDelta = destParent.addNode(delta.getElement(), delta.getIndex(), delta.getFlags(), delta.getChildCount());
+ for (int i = 0; i < delta.getChildDeltas().length; i++) {
+ copyIntoDelta(delta.getChildDeltas()[i], newDelta);
+ }
+ }
/**
* Encodes delta elements into mementos using the given provider.
@@ -417,6 +621,9 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
} catch (IOException e) {
DebugUIPlugin.log(e);
}
+ if (DEBUG_STATE_SAVE_RESTORE) {
+ System.out.println("SAVE COMPLETED: " + rootDelta); //$NON-NLS-1$
+ }
stateSaveComplete(this);
}
} else {
@@ -427,6 +634,9 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
req.cancel();
}
requests.clear();
+ if (DEBUG_STATE_SAVE_RESTORE) {
+ System.out.println("SAVE ABORTED: " + rootDelta.getElement()); //$NON-NLS-1$
+ }
stateSaveComplete(this);
}
}
@@ -473,14 +683,16 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
if (delta.getParentDelta() == null) {
manager.addRequest(
new ElementMementoRequest(ModelContentProvider.this, getViewer().getInput(), manager, getPresentationContext(),
- delta.getElement(), getViewerTreePath(delta), inputMemento, (ModelDelta)delta));
- } else {
+ delta.getElement(), getViewerTreePath(delta), inputMemento, (ModelDelta)delta));
+ } else {
+ if (!(delta.getElement() instanceof XMLMemento)) {
manager.addRequest(
new ElementMementoRequest(ModelContentProvider.this, getViewer().getInput(), manager, getPresentationContext(),
delta.getElement(), getViewerTreePath(delta), childrenMemento.createChild("CHILD_ELEMENT"), (ModelDelta)delta)); //$NON-NLS-1$
- }
- return true;
+ }
}
+ return true;
+ }
};
rootDelta.accept(visitor);
stateSaveStarted(manager);
@@ -869,20 +1081,18 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
fTransform.clear(parent);
}
- protected synchronized IModelDelta checkIfRestoreComplete() {
+ protected synchronized void checkIfRestoreComplete() {
if (fPendingState == null) {
- return null;
+ return;
}
CheckState state = new CheckState();
fPendingState.accept(state);
if (state.isComplete()) {
+ if (DEBUG_STATE_SAVE_RESTORE) {
+ System.out.println("RESTORE COMPELTE: " + fPendingState); //$NON-NLS-1$
+ }
fPendingState = null;
- if (DEBUG_CONTENT_PROVIDER) {
- System.out.println("RESTORE COMPELTE"); //$NON-NLS-1$
- }
- return state.getTopItemDelta();
}
- return null;
}
void addViewerUpdateListener(IViewerUpdateListener listener) {
@@ -1008,6 +1218,14 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
fWaitingRequests.remove(iterator.next());
}
}
+ for (Iterator itr = fCompareRequestsInProgress.keySet().iterator(); itr.hasNext(); ) {
+ CompareRequestKey key = (CompareRequestKey)itr.next();
+ if (key.fPath.startsWith(path, null)) {
+ ElementCompareRequest compareRequest = (ElementCompareRequest)fCompareRequestsInProgress.get(key);
+ compareRequest.cancel();
+ itr.remove();
+ }
+ }
}
/**
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 086016cc5..fc77a6d3b 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,17 +7,18 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Wind River Systems - Fix for viewer state save/restore [188704]
*******************************************************************************/
package org.eclipse.debug.internal.ui.viewers.model;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Set;
-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.provisional.IElementContentProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
@@ -30,7 +31,6 @@ import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
-import org.eclipse.ui.progress.UIJob;
/**
* Content provider for a virtual tree.
@@ -358,21 +358,29 @@ public class TreeModelContentProvider extends ModelContentProvider implements IL
for (int i = 0; i < items.length; i++) {
buildViewerState(EMPTY_TREE_PATH, delta, items[i], set, i);
}
- // add memento for top item if it is mapped to an element
+ // 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.
TreeItem topItem = tree.getTopItem();
if (topItem != null && topItem.getData() != null) {
- TreePath path = ((InternalTreeModelViewer)getTreeViewer()).getTreePathFromItem(topItem);
+ LinkedList itemsInPath = new LinkedList();
+ TreeItem item = topItem;
+ while (item != null) {
+ itemsInPath.addFirst(item);
+ item = item.getParentItem();
+ }
ModelDelta parentDelta = delta;
- for (int i = 0; i < path.getSegmentCount(); i++) {
- Object element = path.getSegment(i);
- ModelDelta childDelta = parentDelta.getChildDelta(element);
- if (childDelta == null) {
- parentDelta = parentDelta.addNode(element, IModelDelta.NO_CHANGE);
- } else {
- parentDelta = childDelta;
- }
+ for (Iterator itr = itemsInPath.iterator(); itr.hasNext();) {
+ TreeItem next = (TreeItem)itr.next();
+ Object element = next.getData();
+ int index = next.getParentItem() == null ? tree.indexOf(next) : next.getParentItem().indexOf(next);
+ ModelDelta childDelta = parentDelta.getChildDelta(element);
+ if (childDelta == null) {
+ parentDelta = parentDelta.addNode(element, index, IModelDelta.NO_CHANGE);
+ } else {
+ parentDelta = childDelta;
+ }
}
- parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.REVEAL);
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.REVEAL);
}
}
@@ -412,17 +420,60 @@ public class TreeModelContentProvider extends ModelContentProvider implements IL
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.ModelContentProvider#doInitialRestore()
*/
- protected void doInitialRestore() {
- Tree tree = (Tree) getViewer().getControl();
- TreeItem[] items = tree.getItems();
- for (int i = 0; i < items.length; i++) {
- TreeItem item = items[i];
- Object data = item.getData();
- if (data != null) {
- doRestore(new TreePath(new Object[]{data}));
- }
- }
- }
+ protected void doInitialRestore(ModelDelta delta) {
+ // First restore the reveal delta.
+ ModelDelta revealDelta = findRevealDelta(delta);
+ /*if (revealDelta != null) {
+ doUpdateElement(TreePath.EMPTY, revealDelta.getIndex());
+ }*/
+
+ // Restore visible items.
+ // Note (Pawel Piech): the initial list of items is normally
+ // empty, so I'm not sure if the code below ever does anything.
+ Tree tree = (Tree) getViewer().getControl();
+ TreeItem[] items = tree.getItems();
+ for (int i = 0; i < items.length; i++) {
+ TreeItem item = items[i];
+ Object data = item.getData();
+ if (data != null) {
+ doRestore(new TreePath(new Object[]{data}), i, false, false);
+ }
+ }
+
+ }
+
+ /**
+ * Finds the delta with the reveal flag, then it walks up this
+ * delta and marks all the parents of it with the reveal flag.
+ * These flags are then used by the restore logic to restore
+ * and reveal all the nodes leading up to the element that should
+ * be ultimately at the top.
+ * @return The node just under the rootDelta which contains
+ * the reveal flag. <code>null</code> if no reveal flag was found.
+ */
+ private ModelDelta findRevealDelta(ModelDelta rootDelta) {
+ final ModelDelta[] revealDelta = new ModelDelta[1];
+ IModelDeltaVisitor visitor = new IModelDeltaVisitor() {
+ public boolean visit(IModelDelta delta, int depth) {
+ if ( (delta.getFlags() & IModelDelta.REVEAL) != 0) {
+ revealDelta[0] = (ModelDelta)delta;
+ }
+ // Keep recursing only if we haven't found our delta yet.
+ return revealDelta[0] == null;
+ }
+ };
+
+ rootDelta.accept(visitor);
+ if (revealDelta[0] != null) {
+ ModelDelta parentDelta = (ModelDelta)revealDelta[0].getParentDelta();
+ while(parentDelta.getParentDelta() != null) {
+ revealDelta[0] = parentDelta;
+ revealDelta[0].setFlags(revealDelta[0].getFlags() | IModelDelta.REVEAL);
+ parentDelta = (ModelDelta)parentDelta.getParentDelta();
+ }
+ }
+ return revealDelta[0];
+ }
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ILazyTreePathContentProvider#getParents(java.lang.Object)
@@ -468,45 +519,56 @@ public class TreeModelContentProvider extends ModelContentProvider implements IL
/**
* @param delta
*/
- void doRestore(final ModelDelta delta) {
- if (delta.getFlags() != IModelDelta.NO_CHANGE) {
- UIJob job = new UIJob("restore delta") { //$NON-NLS-1$
- public IStatus runInUIThread(IProgressMonitor monitor) {
- TreePath treePath = getViewerTreePath(delta);
- InternalTreeModelViewer viewer = (InternalTreeModelViewer)getViewer();
- if ((delta.getFlags() & IModelDelta.EXPAND) != 0) {
- viewer.expandToLevel(treePath, 1);
- }
- if ((delta.getFlags() & IModelDelta.SELECT) != 0) {
- viewer.setSelection(new TreeSelection(treePath));
- }
- int flag = IModelDelta.NO_CHANGE;
- if ((delta.getFlags() & IModelDelta.REVEAL) != 0) {
- flag = IModelDelta.REVEAL;
- }
- delta.setFlags(flag);
- IModelDelta topItemDelta = checkIfRestoreComplete();
- // force child deltas to update, so viewer is populated
- IModelDelta[] childDeltas = delta.getChildDeltas();
- for (int i = 0; i < childDeltas.length; i++) {
- IModelDelta childDelta = childDeltas[i];
- int modelIndex = childDelta.getIndex();
- if (modelIndex >= 0) {
- doUpdateElement(treePath, modelIndex);
- }
- }
- if (topItemDelta != null) {
- TreePath itemPath = getViewerTreePath(topItemDelta);
- Widget topItem = viewer.findItem(itemPath);
- if (topItem instanceof TreeItem) {
- viewer.getTree().setTopItem((TreeItem) topItem);
- }
- }
- return Status.OK_STATUS;
- }
- };
- job.setSystem(true);
- job.schedule();
+ void doRestore(ModelDelta delta, boolean knowsHasChildren, boolean knowsChildCount) {
+ TreePath treePath = getViewerTreePath(delta);
+ InternalTreeModelViewer viewer = (InternalTreeModelViewer)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);
+ }
+ if ((delta.getFlags() & IModelDelta.SELECT) != 0) {
+ viewer.setSelection(new TreeSelection(treePath), false);
+ delta.setFlags(delta.getFlags() & ~IModelDelta.SELECT);
}
+ if ((delta.getFlags() & IModelDelta.REVEAL) != 0) {
+ delta.setFlags(delta.getFlags() & ~IModelDelta.REVEAL);
+ // Look for the reveal flag in the child deltas. If
+ // A child delta has the reveal flag, do not set the
+ // top element yet.
+ boolean setTopItem = true;
+ IModelDelta[] childDeltas = delta.getChildDeltas();
+ for (int i = 0; i < childDeltas.length; i++) {
+ IModelDelta childDelta = childDeltas[i];
+ int modelIndex = childDelta.getIndex();
+ if (modelIndex >= 0 && (childDelta.getFlags() & IModelDelta.REVEAL) != 0) {
+ setTopItem = false;
+ }
+ }
+
+ if (setTopItem) {
+ TreePath itemPath = getViewerTreePath(delta);
+ Widget topItem = viewer.findItem(itemPath);
+ if (topItem instanceof TreeItem) {
+ viewer.getTree().setTopItem((TreeItem) topItem);
+ }
+ }
+ }
+
+ // If we know the children, look for the reveal delta in
+ // the child deltas. For the children with reveal
+ // flag start a new update.
+ if (knowsChildCount) {
+ IModelDelta[] childDeltas = delta.getChildDeltas();
+ for (int i = 0; i < childDeltas.length; i++) {
+ IModelDelta childDelta = childDeltas[i];
+ int modelIndex = childDelta.getIndex();
+ if (modelIndex >= 0 && (childDelta.getFlags() & IModelDelta.REVEAL) != 0) {
+ doUpdateElement(treePath, modelIndex);
+ }
+ }
+ }
+
+ checkIfRestoreComplete();
}
}
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 d41500402..321550301 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Wind River Systems - Fix for viewer state save/restore [188704]
*******************************************************************************/
package org.eclipse.debug.internal.ui.viewers.model.provisional;
@@ -235,16 +236,18 @@ public class ModelDelta implements IModelDelta {
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Model Delta Start\n"); //$NON-NLS-1$
- appendDetail(buf, this);
+ appendDetail(" ", buf, this); //$NON-NLS-1$
buf.append("Model Delta End\n"); //$NON-NLS-1$
return buf.toString();
}
- private void appendDetail(StringBuffer buf, IModelDelta delta) {
- buf.append("\tElement: "); //$NON-NLS-1$
+ private void appendDetail(String indent, StringBuffer buf, IModelDelta delta) {
+ buf.append(indent);
+ buf.append("Element: "); //$NON-NLS-1$
buf.append(delta.getElement());
buf.append('\n');
- buf.append("\t\tFlags: "); //$NON-NLS-1$
+ buf.append(indent);
+ buf.append(" Flags: "); //$NON-NLS-1$
int flags = delta.getFlags();
if (flags == 0) {
buf.append("NO_CHANGE"); //$NON-NLS-1$
@@ -279,16 +282,21 @@ public class ModelDelta implements IModelDelta {
if ((flags & IModelDelta.UNINSTALL) > 0) {
buf.append("UNINSTALL | "); //$NON-NLS-1$
}
+ if ((flags & IModelDelta.REVEAL) > 0) {
+ buf.append("REVEAL | "); //$NON-NLS-1$
+ }
+
}
buf.append('\n');
- buf.append("\t\tIndex: "); //$NON-NLS-1$
+ buf.append(indent);
+ buf.append(" Index: "); //$NON-NLS-1$
buf.append(delta.getIndex());
buf.append(" Child Count: "); //$NON-NLS-1$
buf.append(delta.getChildCount());
buf.append('\n');
IModelDelta[] nodes = delta.getChildDeltas();
for (int i = 0; i < nodes.length; i++) {
- appendDetail(buf, nodes[i]);
+ appendDetail(indent + " ", buf, nodes[i]); //$NON-NLS-1$
}
}
@@ -332,4 +340,14 @@ public class ModelDelta implements IModelDelta {
public void setFlags(int flags) {
fFlags = flags;
}
+
+ /**
+ * Sets this delta's child count.
+ *
+ * @param count
+ */
+ public void setChildCount(int count) {
+ fChildCount = count;
+ }
+
}

Back to the top