Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Piech2009-11-11 00:59:15 +0000
committerPawel Piech2009-11-11 00:59:15 +0000
commit0030724c66680f3283e9598926672ce93f2a7b40 (patch)
treeb200b434153ebb62cae9bf4feae0c8a84fe0b138
parentd1ce210537eae1bdf88fbed6d6fb75cb1e23aba0 (diff)
downloadeclipse.platform.debug-0030724c66680f3283e9598926672ce93f2a7b40.tar.gz
eclipse.platform.debug-0030724c66680f3283e9598926672ce93f2a7b40.tar.xz
eclipse.platform.debug-0030724c66680f3283e9598926672ce93f2a7b40.zip
Bug 291267 - Fix for broken state saving and expanding logic in debugger views.
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ChildrenUpdateTests.java97
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ITestModelUpdatesListenerConstants.java7
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java48
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java31
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java45
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementCompareRequest.java8
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementMementoRequest.java6
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProvider.java15
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelViewer.java15
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalTreeModelViewer.java16
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/InternalVirtualTreeModelViewer.java15
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java3235
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/SubTreeModelViewer.java17
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java8
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IStateUpdateListener.java58
15 files changed, 2043 insertions, 1578 deletions
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 561104977..c64c9d190 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
@@ -20,6 +20,7 @@ import org.eclipse.debug.internal.ui.viewers.model.TreeModelContentProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.jface.viewers.ISelection;
@@ -44,38 +45,32 @@ public class ChildrenUpdateTests extends TestCase {
protected ITreeModelContentProviderTarget getViewer() {
return new ITreeModelContentProviderTarget(){
- public void setSelection(ISelection selection) {
- }
-
- public void removeSelectionChangedListener(ISelectionChangedListener listener) {
- }
-
- public void addSelectionChangedListener(ISelectionChangedListener listener) {
- }
-
- public void updateViewer(IModelDelta delta) {
- }
-
- public void setSelection(ISelection selection, boolean reveal, boolean force) {
- }
-
- public void setInput(Object object) {
- }
-
- public void setAutoExpandLevel(int level) {
- }
-
- public void saveElementState(TreePath path, ModelDelta delta, int flags) {
- }
-
- public void removeViewerUpdateListener(IViewerUpdateListener listener) {
- }
-
- public void removeModelChangedListener(IModelChangedListener listener) {
- }
-
- public void removeLabelUpdateListener(ILabelUpdateListener listener) {
- }
+ public void setSelection(ISelection selection) {}
+ public void removeSelectionChangedListener(ISelectionChangedListener listener) {}
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {}
+ public void updateViewer(IModelDelta delta) {}
+ public void setSelection(ISelection selection, boolean reveal, boolean force) {}
+ public void setInput(Object object) {}
+ public void setAutoExpandLevel(int level) {}
+ public void saveElementState(TreePath path, ModelDelta delta, int flags) {}
+ public void removeStateUpdateListener(IStateUpdateListener listener) {}
+ public void removeViewerUpdateListener(IViewerUpdateListener listener) {}
+ public void removeModelChangedListener(IModelChangedListener listener) {}
+ public void removeLabelUpdateListener(ILabelUpdateListener listener) {}
+ public void addViewerUpdateListener(IViewerUpdateListener listener) {}
+ public void addStateUpdateListener(IStateUpdateListener listener) {}
+ public void addModelChangedListener(IModelChangedListener listener) {}
+ public void addLabelUpdateListener(ILabelUpdateListener listener) {}
+ public void update(Object element) {}
+ public void setHasChildren(Object elementOrTreePath, boolean hasChildren) {}
+ public void setExpandedState(Object elementOrTreePath, boolean expanded) {}
+ public void setChildCount(Object elementOrTreePath, int count) {}
+ public void reveal(TreePath path, int index) {}
+ public void replace(Object parentOrTreePath, int index, Object element) {}
+ public void remove(Object parentOrTreePath, int index) {}
+ public void remove(Object elementOrTreePath) {}
+ public void refresh() {}
+ public void refresh(Object element) {}
public ISelection getSelection() {
return null;
@@ -101,44 +96,6 @@ public class ChildrenUpdateTests extends TestCase {
return 0;
}
- public void addViewerUpdateListener(IViewerUpdateListener listener) {
- }
-
- public void addModelChangedListener(IModelChangedListener listener) {
- }
-
- public void addLabelUpdateListener(ILabelUpdateListener listener) {
- }
-
- public void update(Object element) {
- }
-
- public void setHasChildren(Object elementOrTreePath, boolean hasChildren) {
- }
-
- public void setExpandedState(Object elementOrTreePath, boolean expanded) {
- }
-
- public void setChildCount(Object elementOrTreePath, int count) {
- }
-
- public void reveal(TreePath path, int index) {
- }
-
- public void replace(Object parentOrTreePath, int index, Object element) {
- }
-
- public void remove(Object parentOrTreePath, int index) {
- }
-
- public void remove(Object elementOrTreePath) {
- }
-
- public void refresh() {
- }
-
- public void refresh(Object element) {
- }
public boolean overrideSelection(ISelection current, ISelection candidate) {
return false;
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
index 26570fc5f..10aa25c03 100644
--- 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
@@ -25,9 +25,12 @@ public interface ITestModelUpdatesListenerConstants {
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 STATE_SAVE_COMPLETE = 0X0100;
+ public static final int STATE_RESTORE_COMPLETE = 0X0200;
+ public static final int STATE_UPDATES = 0X0400;
- public static final int VIEWER_UPDATES_RUNNING = 0X0100;
- public static final int LABEL_UPDATES_RUNNING = 0X0200;
+ public static final int VIEWER_UPDATES_RUNNING = 0X0800;
+ public static final int LABEL_UPDATES_RUNNING = 0X1000;
public static final int LABEL_COMPLETE = LABEL_UPDATES_COMPLETE | LABEL_UPDATES;
public static final int CONTENT_COMPLETE =
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 f19df2734..70058c59a 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
@@ -55,6 +55,7 @@ abstract public class StateTests extends TestCase implements ITestModelUpdatesLi
fViewer.addViewerUpdateListener(fListener);
fViewer.addLabelUpdateListener(fListener);
fViewer.addModelChangedListener(fListener);
+ fViewer.addStateUpdateListener(fListener);
fShell.open ();
}
@@ -68,12 +69,17 @@ abstract public class StateTests extends TestCase implements ITestModelUpdatesLi
fViewer.removeLabelUpdateListener(fListener);
fViewer.removeViewerUpdateListener(fListener);
fViewer.removeModelChangedListener(fListener);
+ fViewer.addStateUpdateListener(fListener);
// Close the shell and exit.
fShell.close();
while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
}
+ protected ITreeModelContentProviderTarget getCTargetViewer() {
+ return (ITreeModelContentProviderTarget)fViewer;
+ }
+
public void testUpdateViewer() {
//TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
@@ -334,4 +340,46 @@ abstract public class StateTests extends TestCase implements ITestModelUpdatesLi
Assert.assertTrue(viewer.getExpandedState(model.findElement("6")) == false);
}
+ public void testSaveAndRstoreOnInputChange1() {
+ //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);
+
+ // Expand some, but not all elements
+ expandAlternateElements(model);
+
+ // Extract the original state from viewer
+ ModelDelta originalState = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
+ fViewer.saveElementState(TreePath.EMPTY, originalState, IModelDelta.EXPAND | IModelDelta.SELECT);
+
+ // Set the viewer input to null. This will trigger the view to save the viewer state.
+ fListener.reset(true, false);
+ fListener.addStateUpdates(getCTargetViewer(), TreePath.EMPTY, model.getRootElement());
+ fViewer.setInput(null);
+ while (!fListener.isFinished(STATE_SAVE_COMPLETE)) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+
+ // Set the viewer input back to the model. When view updates are complete
+ // the viewer
+ // Note: disable redundant updates because the reveal delta triggers one.
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), 1, false, false);
+ // TODO: add state updates somehow?
+ fViewer.setInput(model.getRootElement());
+ while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+
+ // Extract the restored state from viewer
+ ModelDelta restoredState = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE);
+ fViewer.saveElementState(TreePath.EMPTY, restoredState, IModelDelta.EXPAND | IModelDelta.SELECT);
+
+ Assert.assertTrue( deltaMatches(originalState, restoredState) );
+ }
+
}
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 c4f5f348d..363afc39a 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
@@ -21,8 +21,11 @@ import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ICheckUpdate;
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.IElementCompareRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
@@ -41,7 +44,7 @@ import org.eclipse.jface.viewers.Viewer;
*
* @since 3.6
*/
-public class TestModel implements IElementContentProvider, IElementLabelProvider, IModelProxyFactory2 /*, IElementCheckReceiver */ {
+public class TestModel implements IElementContentProvider, IElementLabelProvider, IModelProxyFactory2 , IElementMementoProvider {
public static class TestElement extends PlatformObject {
private final TestModel fModel;
@@ -75,6 +78,10 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
return null;
}
+ public String getID() {
+ return fID;
+ }
+
public void setLabelAppendix(String appendix) {
fLabelAppendix = appendix;
}
@@ -229,6 +236,27 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
}
}
+ public final static String ELEMENT_MEMENTO_ID = "id";
+
+ public void compareElements(IElementCompareRequest[] updates) {
+ for (int i = 0; i < updates.length; i++) {
+ String elementID = ((TestElement)updates[i].getElement()).getID();
+ String mementoID = updates[i].getMemento().getString(ELEMENT_MEMENTO_ID);
+ updates[i].setEqual( elementID.equals(mementoID) );
+ updates[i].done();
+ }
+
+ }
+
+ public void encodeElements(IElementMementoRequest[] updates) {
+ for (int i = 0; i < updates.length; i++) {
+ String elementID = ((TestElement)updates[i].getElement()).getID();
+ updates[i].getMemento().putString(ELEMENT_MEMENTO_ID, elementID);
+ updates[i].done();
+ }
+ }
+
+
public void elementChecked(IPresentationContext context, Object viewerInput, TreePath path, boolean checked) {
TestElement element = getElement(path);
Assert.assertFalse(element.getGrayed());
@@ -616,5 +644,6 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
return m1;
}
+
}
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 c694e1d1d..ea866c774 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
@@ -28,12 +28,14 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
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, ITestModelUpdatesListenerConstants
+ implements IViewerUpdateListener, ILabelUpdateListener, IModelChangedListener, ITestModelUpdatesListenerConstants,
+ IStateUpdateListener
{
private boolean fFailOnRedundantUpdates;
private boolean fFailOnMultipleUpdateSequences;
@@ -43,9 +45,12 @@ public class TestModelUpdatesListener
private Set fChildCountUpdates = new HashSet();
private Set fLabelUpdates = new HashSet();
private Set fProxyModels = new HashSet();
+ private Set fStateUpdates = new HashSet();
private boolean fViewerUpdatesComplete;
private boolean fLabelUpdatesComplete;
private boolean fModelChangedComplete;
+ private boolean fStateSaveComplete;
+ private boolean fStateRestoreComplete;
private int fViewerUpdatesRunning;
private int fLabelUpdatesRunning;
@@ -86,6 +91,8 @@ public class TestModelUpdatesListener
fViewerUpdatesComplete = false;
fLabelUpdatesComplete = false;
fModelChangedComplete = false;
+ fStateSaveComplete = false;
+ fStateRestoreComplete = false;
}
public void addHasChildrenUpdate(TreePath path) {
@@ -135,10 +142,14 @@ public class TestModelUpdatesListener
addUpdates(path, element, levels, ALL_UPDATES_COMPLETE);
}
+ public void addStateUpdates(ITreeModelContentProviderTarget viewer, TreePath path, TestElement element) {
+ addUpdates(viewer, path, element, -1, STATE_UPDATES);
+ }
+
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)) {
if ((flags & LABEL_UPDATES) != 0) {
@@ -163,6 +174,10 @@ public class TestModelUpdatesListener
fChildrenUpdates.put(path, childrenIndexes);
}
+ if ((flags & STATE_UPDATES) != 0 && viewer != null) {
+ fStateUpdates.add(path);
+ }
+
for (int i = 0; i < children.length; i++) {
addUpdates(viewer, path.createChildPath(children[i]), children[i], levels, flags);
}
@@ -208,6 +223,12 @@ public class TestModelUpdatesListener
if ( (flags & MODEL_CHANGED_COMPLETE) != 0) {
if (!fModelChangedComplete) return false;
}
+ if ( (flags & STATE_SAVE_COMPLETE) != 0) {
+ if (!fStateSaveComplete) return false;
+ }
+ if ( (flags & STATE_RESTORE_COMPLETE) != 0) {
+ if (!fStateRestoreComplete) return false;
+ }
if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
if (fProxyModels.size() != 0) return false;
}
@@ -313,6 +334,26 @@ public class TestModelUpdatesListener
}
}
}
+
+ public void stateRestoreUpdatesBegin(Object input) {
+ }
+
+ public void stateRestoreUpdatesComplete(Object input) {
+ fStateRestoreComplete = true;
+ }
+
+ public void stateSaveUpdatesBegin(Object input) {
+ }
+
+ public void stateSaveUpdatesComplete(Object input) {
+ fStateSaveComplete = true;
+ }
+
+ public void stateUpdateComplete(Object input, IViewerUpdate update) {
+ }
+
+ public void stateUpdateStarted(Object input, IViewerUpdate update) {
+ }
}
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 2b3422ed2..54e592e41 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
@@ -109,4 +109,12 @@ class ElementCompareRequest extends MementoUpdate implements IElementCompareRequ
boolean checkChildrenRealized() {
return fCheckChildrenRealized;
}
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("IElementCompareRequest: "); //$NON-NLS-1$
+ buf.append(getElement());
+ return buf.toString();
+ }
+
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementMementoRequest.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementMementoRequest.java
index f821e19dc..0b77420d1 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementMementoRequest.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ElementMementoRequest.java
@@ -46,4 +46,10 @@ class ElementMementoRequest extends MementoUpdate implements IElementMementoRequ
fManager.requestComplete(this);
}
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("IElementMementoRequest: "); //$NON-NLS-1$
+ buf.append(getElement());
+ return buf.toString();
+ }
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProvider.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProvider.java
index 4801352a5..1b7e93e4a 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProvider.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ITreeModelContentProvider.java
@@ -12,7 +12,9 @@ package org.eclipse.debug.internal.ui.viewers.model;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
import org.eclipse.jface.viewers.ILazyTreePathContentProvider;
import org.eclipse.jface.viewers.TreePath;
@@ -152,6 +154,19 @@ public interface ITreeModelContentProvider extends ILazyTreePathContentProvider
*/
public void removeModelChangedListener(IModelChangedListener listener);
+
+ /**
+ * Registers the specified listener for state update notifications.
+ * @since 3.6
+ */
+ public void addStateUpdateListener(IStateUpdateListener listener);
+
+ /**
+ * Removes the specified listener from state update notifications.
+ * @since 3.6
+ */
+ public void removeStateUpdateListener(IStateUpdateListener listener);
+
/**
* Instructs the content provider to process the given model delta. This
* mechanism can be used to control the view's layout (expanding, selecting
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 9e6198327..a23191780 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
@@ -13,8 +13,11 @@ package org.eclipse.debug.internal.ui.viewers.model;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.TreePath;
@@ -138,6 +141,18 @@ public interface ITreeModelViewer extends ISelectionProvider {
public void removeViewerUpdateListener(IViewerUpdateListener listener);
/**
+ * Registers the specified listener for state update notifications.
+ * @since 3.6
+ */
+ public void addStateUpdateListener(IStateUpdateListener listener);
+
+ /**
+ * Removes the specified listener from state update notifications.
+ * @since 3.6
+ */
+ public void removeStateUpdateListener(IStateUpdateListener listener);
+
+ /**
* Registers the specified listener for view label update notifications.
*/
public void addLabelUpdateListener(ILabelUpdateListener listener);
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 1a8bddf79..1177bb805 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
@@ -39,6 +39,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
@@ -1701,7 +1702,7 @@ public class InternalTreeModelViewer extends TreeViewer
}
/**
- * Registers the specified listener for view update notifications.
+ * Registers the specified listener for view update notifications.
*
* @param listener listener
*/
@@ -1741,7 +1742,18 @@ public class InternalTreeModelViewer extends TreeViewer
cp.removeModelChangedListener(listener);
}
}
-
+
+ public void addStateUpdateListener(IStateUpdateListener listener) {
+ ((ITreeModelContentProvider)getContentProvider()).addStateUpdateListener(listener);
+ }
+
+ public void removeStateUpdateListener(IStateUpdateListener listener) {
+ ITreeModelContentProvider cp = (ITreeModelContentProvider)getContentProvider();
+ if (cp != null) {
+ cp.removeStateUpdateListener(listener);
+ }
+ }
+
/*
* (non-Javadoc) Method declared in AbstractTreeViewer.
*/
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 427d49b59..8c545c34f 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
@@ -32,6 +32,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedList
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
@@ -1244,7 +1245,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
}
public void addViewerUpdateListener(IViewerUpdateListener listener) {
- ((ModelContentProvider)getContentProvider()).addViewerUpdateListener(listener);
+ getContentProvider().addViewerUpdateListener(listener);
}
public void removeViewerUpdateListener(IViewerUpdateListener listener) {
@@ -1255,7 +1256,7 @@ public class InternalVirtualTreeModelViewer extends Viewer
}
public void addModelChangedListener(IModelChangedListener listener) {
- ((ModelContentProvider)getContentProvider()).addModelChangedListener(listener);
+ getContentProvider().addModelChangedListener(listener);
}
public void removeModelChangedListener(IModelChangedListener listener) {
@@ -1265,6 +1266,16 @@ public class InternalVirtualTreeModelViewer extends Viewer
}
}
+ public void addStateUpdateListener(IStateUpdateListener listener) {
+ getContentProvider().addStateUpdateListener(listener);
+ }
+
+ public void removeStateUpdateListener(IStateUpdateListener listener) {
+ ITreeModelContentProvider cp = getContentProvider();
+ if (cp != null) {
+ cp.removeStateUpdateListener(listener);
+ }
+ }
public void addLabelUpdateListener(ILabelUpdateListener listener) {
getLabelProvider().addLabelUpdateListener(listener);
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 584d22585..1b793f53b 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
@@ -47,6 +47,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory2;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
@@ -66,424 +67,506 @@ import org.eclipse.ui.progress.WorkbenchJob;
*/
abstract class ModelContentProvider implements IContentProvider, IModelChangedListener {
- private ITreeModelContentProviderTarget fViewer;
-
- /**
- * Mask used to filter delta updates coming from the model.
- */
- private int fModelDeltaMask = ~0;
-
- /**
- * Map tree paths to model proxy responsible for element
- *
- * Used to install different model proxy instances for one element depending on the tree path.
- */
- private Map fTreeModelProxies = new HashMap(); // tree model proxy by element tree path
-
- /**
- * Map element to model proxy responsible for it.
- *
- * Used to install a single model proxy which is responsible
- * for all instances of an element in the model tree.
- */
- private Map fModelProxies = new HashMap(); // model proxy by element
-
- /**
- * Map of nodes that have been filtered from the viewer.
- */
- private FilterTransform fTransform = new FilterTransform();
-
- /**
- * Model listeners
- */
- private ListenerList fModelListeners = new ListenerList();
-
- /**
- * Update listeners
- */
- private ListenerList fUpdateListeners = new ListenerList();
-
- /**
- * Map of updates in progress: element path -> list of requests
- */
- private Map fRequestsInProgress = new HashMap();
-
- /**
- * Map of dependent requests waiting for parent requests to complete:
- * element path -> list of requests
- */
- private Map fWaitingRequests = new HashMap();
-
- /**
- * Map of viewer states keyed by viewer input mementos
- */
- private Map fViewerStates = new LRUMap(20);
-
- /**
- * 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
- */
- private Set fPendingStateSaves = new HashSet();
-
- /**
- * Used to queue a viewer input for state restore
- */
- 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
- */
- protected class CheckState implements IModelDeltaVisitor {
- private boolean complete = true;
- private IModelDelta topDelta = null;
- /* (non-Javadoc)
- * @see org.eclipse.debug.internal.ui.viewers.provisional.IModelDeltaVisitor#visit(org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta, int)
- */
- 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 {
- complete = false;
- return false;
- }
- }
- return true;
- }
-
- public boolean isComplete() {
- return complete;
- }
-
- public IModelDelta getTopItemDelta() {
- return topDelta;
- }
-
- private boolean areElementUpdatesPending(TreePath path) {
- synchronized (fRequestsInProgress) {
- TreePath parentPath = path.getParentPath();
- List requests = (List)fWaitingRequests.get(path);
+ private ITreeModelContentProviderTarget fViewer;
+
+ /**
+ * Mask used to filter delta updates coming from the model.
+ */
+ private int fModelDeltaMask = ~0;
+
+ /**
+ * Map tree paths to model proxy responsible for element
+ *
+ * Used to install different model proxy instances for one element depending
+ * on the tree path.
+ */
+ private Map fTreeModelProxies = new HashMap(); // tree model proxy by
+ // element tree path
+
+ /**
+ * Map element to model proxy responsible for it.
+ *
+ * Used to install a single model proxy which is responsible for all
+ * instances of an element in the model tree.
+ */
+ private Map fModelProxies = new HashMap(); // model proxy by element
+
+ /**
+ * Map of nodes that have been filtered from the viewer.
+ */
+ private FilterTransform fTransform = new FilterTransform();
+
+ /**
+ * Model listeners
+ */
+ private ListenerList fModelListeners = new ListenerList();
+
+ /**
+ * Viewer update listeners
+ */
+ private ListenerList fUpdateListeners = new ListenerList();
+
+ /**
+ * State update listeners
+ */
+ private ListenerList fStateUpdateListeners = new ListenerList();
+
+ /**
+ * Map of updates in progress: element path -> list of requests
+ */
+ private Map fRequestsInProgress = new HashMap();
+
+ /**
+ * Map of dependent requests waiting for parent requests to complete:
+ * element path -> list of requests
+ */
+ private Map fWaitingRequests = new HashMap();
+
+ /**
+ * Map of viewer states keyed by viewer input mementos
+ */
+ private Map fViewerStates = new LRUMap(20);
+
+ /**
+ * 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 LinkedHashMap();
+
+ /**
+ * Set of IMementoManager's that are currently saving state
+ */
+ private Set fPendingStateSaves = new HashSet();
+
+ /**
+ * Used to queue a viewer input for state restore
+ */
+ 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
+ */
+ protected class CheckState implements IModelDeltaVisitor {
+ private boolean complete = true;
+
+ private IModelDelta topDelta = null;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.debug.internal.ui.viewers.provisional.IModelDeltaVisitor
+ * #visit(org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta,
+ * int)
+ */
+ public boolean visit(IModelDelta delta, int depth) {
+ if (delta.getFlags() != IModelDelta.NO_CHANGE) {
+ IModelDelta parentDelta = delta.getParentDelta();
+ // Remove the delta if :
+ // - The parent delta has no more flags on it.
+ // - There are no more pending updates for the element.
+ // - If element is a memento, there are no state requests pending.
+ if (parentDelta != null && parentDelta.getFlags() == IModelDelta.NO_CHANGE) {
+ TreePath deltaPath = getViewerTreePath(delta);
+ if ( !areElementUpdatesPending(deltaPath) &&
+ (!(delta.getElement() instanceof IMemento) || !areMementoUpdatesPending(delta)) )
+ {
+ removeDelta(delta);
+ return false;
+ }
+ }
+
+ if (delta.getFlags() == IModelDelta.REVEAL && !(delta.getElement() instanceof IMemento)) {
+ topDelta = delta;
+ } else {
+ complete = false;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean isComplete() {
+ return complete;
+ }
+
+ 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);
+ ViewerUpdateMonitor update = (ViewerUpdateMonitor) requests.get(i);
if (update instanceof ChildrenUpdate) {
return true;
}
}
}
- requests = (List)fWaitingRequests.get(parentPath);
+ requests = (List) fWaitingRequests.get(parentPath);
if (requests != null) {
for (int i = 0; i < requests.size(); i++) {
- ViewerUpdateMonitor update = (ViewerUpdateMonitor)requests.get(i);
+ ViewerUpdateMonitor update = (ViewerUpdateMonitor) requests.get(i);
if (update.getElement().equals(path.getLastSegment())) {
return true;
}
}
}
- requests = (List)fRequestsInProgress.get(path);
+ requests = (List) fRequestsInProgress.get(path);
if (requests != null) {
for (int i = 0; i < requests.size(); i++) {
- ViewerUpdateMonitor update = (ViewerUpdateMonitor)requests.get(i);
+ ViewerUpdateMonitor update = (ViewerUpdateMonitor) requests.get(i);
if (update instanceof ChildrenUpdate) {
return true;
}
}
}
- requests = (List)fRequestsInProgress.get(parentPath);
+ requests = (List) fRequestsInProgress.get(parentPath);
if (requests != null) {
for (int i = 0; i < requests.size(); i++) {
- ViewerUpdateMonitor update = (ViewerUpdateMonitor)requests.get(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 boolean areMementoUpdatesPending(IModelDelta delta) {
+ for (Iterator itr = fCompareRequestsInProgress.keySet().iterator(); itr.hasNext();) {
+ CompareRequestKey key = (CompareRequestKey) itr.next();
+ if (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$
+ private void removeDelta(IModelDelta delta) {
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("\tRESTORE REMOVED: " + delta.getElement()); //$NON-NLS-1$
}
-
+
delta.accept(new IModelDeltaVisitor() {
public boolean visit(IModelDelta _visitorDelta, int depth) {
- ModelDelta visitorDelta = (ModelDelta)_visitorDelta;
+ ModelDelta visitorDelta = (ModelDelta) _visitorDelta;
visitorDelta.setElement(ELEMENT_REMOVED);
visitorDelta.setFlags(IModelDelta.NO_CHANGE);
return true;
}
});
- }
- }
-
- /**
- * LRU cache for viewer states
- */
- class LRUMap extends LinkedHashMap {
- private static final long serialVersionUID= 1L;
- private int fMaxSize;
- LRUMap(int maxSize) {
- super();
- fMaxSize = maxSize;
- }
- protected boolean removeEldestEntry(Entry eldest) {
- return size() > fMaxSize;
- }
- }
-
- /**
- * Update type constants
- */
- static final int UPDATE_SEQUENCE_BEGINS = 0;
- static final int UPDATE_SEQUENCE_COMPLETE = 1;
- static final int UPDATE_BEGINS = 2;
- static final int UPDATE_COMPLETE = 3;
-
- /**
- * Constant for an empty tree path.
- */
- protected static final TreePath EMPTY_TREE_PATH = new TreePath(new Object[]{});
-
- // debug flags
+ }
+ }
+
+ /**
+ * LRU cache for viewer states
+ */
+ class LRUMap extends LinkedHashMap {
+ private static final long serialVersionUID = 1L;
+
+ private int fMaxSize;
+
+ LRUMap(int maxSize) {
+ super();
+ fMaxSize = maxSize;
+ }
+
+ protected boolean removeEldestEntry(Entry eldest) {
+ return size() > fMaxSize;
+ }
+ }
+
+ /**
+ * Update type constants
+ */
+ static final int UPDATE_SEQUENCE_BEGINS = 0;
+
+ static final int UPDATE_SEQUENCE_COMPLETE = 1;
+
+ static final int UPDATE_BEGINS = 2;
+
+ static final int UPDATE_COMPLETE = 3;
+
+ /**
+ * Additional state update type constants
+ */
+ static final int STATE_SAVE_SEQUENCE_BEGINS = 4;
+
+ static final int STATE_SAVE_SEQUENCE_COMPLETE = 5;
+
+ static final int STATE_RESTORE_SEQUENCE_BEGINS = 6;
+
+ static final int STATE_RESTORE_SEQUENCE_COMPLETE = 7;
+
+ /**
+ * Constant for an empty tree path.
+ */
+ protected static final TreePath EMPTY_TREE_PATH = new TreePath(new Object[] {});
+
+ // debug flags
public static String DEBUG_PRESENTATION_ID = null;
- public static boolean DEBUG_CONTENT_PROVIDER = false;
- public static boolean DEBUG_UPDATE_SEQUENCE = false;
+
+ public static boolean DEBUG_CONTENT_PROVIDER = false;
+
+ public static boolean DEBUG_UPDATE_SEQUENCE = false;
+
public static boolean DEBUG_STATE_SAVE_RESTORE = false;
+
public static boolean DEBUG_DELTAS = false;
- static {
+ static {
DEBUG_PRESENTATION_ID = Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/presentationId"); //$NON-NLS-1$
if (!DebugUIPlugin.DEBUG || "".equals(DEBUG_PRESENTATION_ID)) { //$NON-NLS-1$
DEBUG_PRESENTATION_ID = null;
}
- 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$
+ 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$
DEBUG_DELTAS = DebugUIPlugin.DEBUG && "true".equals( //$NON-NLS-1$
- Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/deltas")); //$NON-NLS-1$
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.viewers.IContentProvider#dispose()
- */
- public synchronized void dispose() {
- // cancel pending updates
- synchronized (fRequestsInProgress) {
- Iterator iterator = fRequestsInProgress.values().iterator();
- while (iterator.hasNext()) {
- List requests = (List) iterator.next();
- Iterator reqIter = requests.iterator();
- while (reqIter.hasNext()) {
- ((IRequest) reqIter.next()).cancel();
- }
- }
- fWaitingRequests.clear();
- }
- fModelListeners.clear();
- fUpdateListeners.clear();
- disposeAllModelProxies();
- fViewer = null;
- }
-
- public synchronized boolean isDisposed() {
- return fViewer == null;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
- * java.lang.Object, java.lang.Object)
- */
- public synchronized void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- fViewer = (ITreeModelContentProviderTarget)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();
- if (newInput != null) {
- installModelProxy(newInput, TreePath.EMPTY);
- restoreViewerState(newInput);
- }
- }
- }
-
- /**
- * Restores the viewer state unless a save is taking place. If a save is
- * taking place, the restore is queued.
- * @param input viewer input
- */
- protected synchronized void restoreViewerState(final Object input) {
- fPendingState = null;
- if (isSavingState()) {
- fQueuedRestore = input;
- } else {
- startRestoreViewerState(input);
- }
- }
-
- /**
- * Restores viewer state for the given input
- *
- * @param input viewer input
- */
- private synchronized void startRestoreViewerState(final Object input) {
- fPendingState = null;
- final IElementMementoProvider defaultProvider = ViewerAdapterService.getMementoProvider(input);
- if (defaultProvider != null) {
- // build a model delta representing expansion and selection state
- final ModelDelta delta = new ModelDelta(input, IModelDelta.NO_CHANGE);
- final XMLMemento inputMemento = XMLMemento.createWriteRoot("VIEWER_INPUT_MEMENTO"); //$NON-NLS-1$
- final IMementoManager manager = new IMementoManager() {
-
- private IElementMementoRequest fRequest;
-
- /* (non-Javadoc)
- * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IMementoManager#requestComplete(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest)
- */
- public synchronized void requestComplete(IElementMementoRequest request) {
- if (!request.isCanceled() && (request.getStatus() == null || request.getStatus().isOK())) {
- XMLMemento keyMemento = (XMLMemento) delta.getElement();
- StringWriter writer = new StringWriter();
- try {
- keyMemento.save(writer);
- final String keyMementoString = writer.toString();
- final ModelDelta stateDelta = (ModelDelta) fViewerStates.get(keyMementoString);
- if (stateDelta != null) {
- 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 && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("STATE RESTORE: " + stateDelta.toString()); //$NON-NLS-1$
- }
- fViewerStates.remove(keyMementoString);
- fPendingState = stateDelta;
- doInitialRestore(fPendingState);
- }
- return Status.OK_STATUS;
- }
-
- };
- job.setSystem(true);
- job.schedule();
- }
- } catch (IOException e) {
- DebugUIPlugin.log(e);
- }
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IMementoManager#processReqeusts()
- */
- public void processReqeusts() {
- defaultProvider.encodeElements(new IElementMementoRequest[]{fRequest});
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IMementoManager#addRequest(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest)
- */
- public synchronized void addRequest(IElementMementoRequest req) {
- fRequest = req;
- }
-
- };
- manager.addRequest(new ElementMementoRequest(ModelContentProvider.this, getViewer().getInput(), manager, getPresentationContext(),
- delta.getElement(), getViewerTreePath(delta), inputMemento, delta));
- manager.processReqeusts();
- }
- }
-
+ Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/deltas")); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public synchronized void dispose() {
+ // cancel pending updates
+ synchronized (fRequestsInProgress) {
+ Iterator iterator = fRequestsInProgress.values().iterator();
+ while (iterator.hasNext()) {
+ List requests = (List) iterator.next();
+ Iterator reqIter = requests.iterator();
+ while (reqIter.hasNext()) {
+ ((IRequest) reqIter.next()).cancel();
+ }
+ }
+ fWaitingRequests.clear();
+ }
+ fModelListeners.clear();
+ fUpdateListeners.clear();
+ fStateUpdateListeners.clear();
+ disposeAllModelProxies();
+ fViewer = null;
+ }
+
+ public synchronized boolean isDisposed() {
+ return fViewer == null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface
+ * .viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+ public synchronized void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ fViewer = (ITreeModelContentProviderTarget) 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();
+ if (newInput != null) {
+ installModelProxy(newInput, TreePath.EMPTY);
+ restoreViewerState(newInput);
+ }
+ }
+ }
+
+ /**
+ * Restores the viewer state unless a save is taking place. If a save is
+ * taking place, the restore is queued.
+ *
+ * @param input
+ * viewer input
+ */
+ protected synchronized void restoreViewerState(final Object input) {
+ fPendingState = null;
+ if (isSavingState()) {
+ fQueuedRestore = input;
+ } else {
+ startRestoreViewerState(input);
+ }
+ }
+
+ /**
+ * Restores viewer state for the given input
+ *
+ * @param input
+ * viewer input
+ */
+ private synchronized void startRestoreViewerState(final Object input) {
+ fPendingState = null;
+ final IElementMementoProvider defaultProvider = ViewerAdapterService.getMementoProvider(input);
+ if (defaultProvider != null) {
+ // build a model delta representing expansion and selection state
+ final ModelDelta delta = new ModelDelta(input, IModelDelta.NO_CHANGE);
+ final XMLMemento inputMemento = XMLMemento.createWriteRoot("VIEWER_INPUT_MEMENTO"); //$NON-NLS-1$
+ final IMementoManager manager = new IMementoManager() {
+
+ private IElementMementoRequest fRequest;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.debug.internal.ui.viewers.model.provisional.viewers
+ * .
+ * IMementoManager#requestComplete(org.eclipse.debug.internal.ui
+ * .viewers.model.provisional.IElementMementoRequest)
+ */
+ public synchronized void requestComplete(IElementMementoRequest request) {
+ notifyStateUpdate(input, UPDATE_COMPLETE, request);
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext()
+ .getId()))) {
+ System.out.println("\tSTATE END: " + request); //$NON-NLS-1$
+ }
+
+ if (!request.isCanceled() && (request.getStatus() == null || request.getStatus().isOK())) {
+ XMLMemento keyMemento = (XMLMemento) delta.getElement();
+ StringWriter writer = new StringWriter();
+ try {
+ keyMemento.save(writer);
+ final String keyMementoString = writer.toString();
+ final ModelDelta stateDelta = (ModelDelta) fViewerStates.get(keyMementoString);
+ if (stateDelta != null) {
+ 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
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID
+ .equals(getPresentationContext().getId()))) {
+ System.out.println("\tRESTORE: " + stateDelta.toString()); //$NON-NLS-1$
+ }
+ fViewerStates.remove(keyMementoString);
+ fPendingState = stateDelta;
+ doInitialRestore(fPendingState);
+ } else {
+ notifyStateUpdate(input, STATE_RESTORE_SEQUENCE_BEGINS, null);
+ }
+ return Status.OK_STATUS;
+ }
+
+ };
+ job.setSystem(true);
+ job.schedule();
+ } else {
+ notifyStateUpdate(input, STATE_RESTORE_SEQUENCE_BEGINS, null);
+ }
+ } catch (IOException e) {
+ DebugUIPlugin.log(e);
+ }
+ } else {
+ notifyStateUpdate(input, STATE_RESTORE_SEQUENCE_BEGINS, null);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.debug.internal.ui.viewers.model.provisional.viewers
+ * .IMementoManager#processReqeusts()
+ */
+ public void processReqeusts() {
+ notifyStateUpdate(input, STATE_RESTORE_SEQUENCE_BEGINS, null);
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext()
+ .getId()))) {
+ System.out.println("\tSTATE BEGIN: " + fRequest); //$NON-NLS-1$
+ }
+ notifyStateUpdate(input, UPDATE_BEGINS, fRequest);
+ defaultProvider.encodeElements(new IElementMementoRequest[] { fRequest });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.debug.internal.ui.viewers.model.provisional.viewers
+ * .
+ * IMementoManager#addRequest(org.eclipse.debug.internal.ui.viewers
+ * .model.provisional.IElementMementoRequest)
+ */
+ public synchronized void addRequest(IElementMementoRequest req) {
+ fRequest = req;
+ }
+
+ };
+ manager.addRequest(new ElementMementoRequest(ModelContentProvider.this, getViewer().getInput(), manager,
+ getPresentationContext(), delta.getElement(), getViewerTreePath(delta), inputMemento, delta));
+ manager.processReqeusts();
+ }
+ }
+
/**
* Restore selection/expansion based on items already in the viewer
*/
- protected abstract void doInitialRestore(ModelDelta delta);
+ protected abstract void doInitialRestore(ModelDelta delta);
- /**
+ /**
* @param delta
*/
- abstract void doRestore(final ModelDelta delta, boolean knowsHasChildren, boolean knowsChildCount, boolean checkChildrenRealized);
+ 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()))) {
+ 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$
}
@@ -495,62 +578,67 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
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.
+
+ // 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);
+ ((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 (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("\tAPPEND DELTA: " + appendDeltaRoot); //$NON-NLS-1$
}
-
+
if (fPendingState != null) {
- // If the restore for the current input was never completed, preserve
+ // 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$
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("\tAPPEND 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
+
+ // 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
+ // 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,
+ // 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)
- {
+ 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 (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext()
+ .getId()))) {
+ System.out.println("\tSKIPPED: " + pendingDeltaNode.getElement()); //$NON-NLS-1$
}
}
-
- // If the pending delta node has a memento element, its
+
+ // 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.
+ // of this pending delta node into the save delta.
if (pendingDeltaNode.getElement() instanceof IMemento) {
return false;
} else {
@@ -559,162 +647,190 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
};
fPendingState.accept(pendingStateVisitor);
- }
+ }
if (appendDeltaRoot.getChildDeltas().length > 0) {
// Set the new delta root as the pending state delta.
+ if (fPendingState == null) {
+ notifyStateUpdate(appendDeltaRoot.getElement(), STATE_RESTORE_SEQUENCE_BEGINS, null);
+ }
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$
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE APPEND COMPLETE " + 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$
- }
+ 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, final boolean checkChildrenRealized) {
- if (fPendingState == null) {
- return;
- }
-
- IModelDeltaVisitor visitor = new IModelDeltaVisitor() {
- public boolean visit(final IModelDelta delta, int depth) {
-
- Object element = delta.getElement();
- 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);
- 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, checkChildrenRealized);
- 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, checkChildrenRealized);
- }
- 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(), request.checkChildrenRealized());
- } 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
- */
- protected void saveViewerState(Object input) {
- IElementMementoProvider stateProvider = ViewerAdapterService.getMementoProvider(input);
- if (stateProvider != null) {
- if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ }
+
+ /**
+ * 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, final boolean checkChildrenRealized) {
+ if (fPendingState == null) {
+ return;
+ }
+
+ IModelDeltaVisitor visitor = new IModelDeltaVisitor() {
+ public boolean visit(final IModelDelta delta, int depth) {
+
+ Object element = delta.getElement();
+ 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);
+ 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, checkChildrenRealized);
+ fCompareRequestsInProgress.put(key, compareRequest);
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID
+ .equals(getPresentationContext().getId()))) {
+ System.out.println("\tSTATE BEGIN: " + compareRequest); //$NON-NLS-1$
+ }
+ notifyStateUpdate(fPendingState.getElement(), UPDATE_BEGINS, 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, checkChildrenRealized);
+ }
+ return false;
+ }
+ // Only follow the paths that match the delta.
+ return element.equals(potentialMatch);
+ }
+ };
+ fPendingState.accept(visitor);
+ }
+
+ void compareFinished(ElementCompareRequest request, ModelDelta delta) {
+ notifyStateUpdate(request.getViewerInput(), UPDATE_COMPLETE, request);
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("\tSTATE END: " + request + " = " + false); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ fCompareRequestsInProgress.remove(request);
+ if (!request.isCanceled()) {
+ if (request.isEqual()) {
+ delta.setElement(request.getElement());
+ 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
+ // 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
+ */
+ protected void saveViewerState(Object input) {
+ 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("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);
+ // 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("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("STATE SAVE OUTSTANDING RESTORE: " + fPendingState); //$NON-NLS-1$
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("\tSAVE DELTA FROM VIEW:\n" + 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("\tSAVE 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
+
+ // 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
+ // 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
+ // 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,
+ // 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
+ 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 did not yet complete the reveal
// operation.
- if ( (pendingDeltaNode.getFlags() & IModelDelta.REVEAL) != 0) {
+ if ((pendingDeltaNode.getFlags() & IModelDelta.REVEAL) != 0) {
clearRevealFlag(saveDeltaRoot);
}
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 (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID
+ .equals(getPresentationContext().getId()))) {
+ System.out.println("\tSKIPPED: " + pendingDeltaNode.getElement()); //$NON-NLS-1$
}
}
-
- // If the pending delta node has a memento element, its
+
+ // 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.
+ // of this pending delta node into the save delta.
if (pendingDeltaNode.getElement() instanceof IMemento) {
return false;
} else {
@@ -723,312 +839,358 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
};
fPendingState.accept(pendingStateVisitor);
- }
-
- if (saveDeltaRoot.getChildDeltas().length > 0) {
- // encode delta with mementos in place of elements, in non-UI thread
- encodeDelta(saveDeltaRoot, stateProvider);
- } else {
- if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("STATE SAVE CANCELED, NO DATA"); //$NON-NLS-1$
- }
- }
- }
- }
-
- private void clearRevealFlag(ModelDelta saveRootDelta) {
+ }
+
+ if (saveDeltaRoot.getChildDeltas().length > 0) {
+ // encode delta with mementos in place of elements, in non-UI
+ // thread
+ encodeDelta(saveDeltaRoot, stateProvider);
+ } else {
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("STATE 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);
+ 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 path 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) {
+ }
+
+ 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 path 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) ) {
+ 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());
+ 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.
- *
- * @param delta
- * @param stateProvider
- */
- protected void encodeDelta(final ModelDelta rootDelta, final IElementMementoProvider defaultProvider) {
- final XMLMemento inputMemento = XMLMemento.createWriteRoot("VIEWER_INPUT_MEMENTO"); //$NON-NLS-1$
- final XMLMemento childrenMemento = XMLMemento.createWriteRoot("CHILDREN_MEMENTO"); //$NON-NLS-1$
- final IMementoManager manager = new IMementoManager() {
-
- /**
- * list of memento requests
- */
- private List requests = new ArrayList();
- private boolean abort = false;
-
- /* (non-Javadoc)
- * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IMementoManager#requestComplete(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest)
- */
- public synchronized void requestComplete(IElementMementoRequest request) {
- if (!abort) {
- if (!request.isCanceled() && (request.getStatus() == null || request.getStatus().isOK())) {
- requests.remove(request);
- if (requests.isEmpty()) {
- XMLMemento keyMemento = (XMLMemento) rootDelta.getElement();
- StringWriter writer = new StringWriter();
- try {
- keyMemento.save(writer);
- fViewerStates.put(writer.toString(), rootDelta);
- } catch (IOException e) {
- DebugUIPlugin.log(e);
- }
- if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("STATE SAVE COMPLETED: " + rootDelta); //$NON-NLS-1$
- }
- stateSaveComplete(this);
- }
- } else {
- abort = true;
- Iterator iterator = requests.iterator();
- while (iterator.hasNext()) {
- IElementMementoRequest req = (IElementMementoRequest) iterator.next();
- req.cancel();
- }
- requests.clear();
- if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("STATE SAVE ABORTED: " + rootDelta.getElement()); //$NON-NLS-1$
- }
- stateSaveComplete(this);
- }
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IMementoManager#processReqeusts()
- */
- public synchronized void processReqeusts() {
- Map providers = new HashMap();
- Iterator iterator = requests.iterator();
- while (iterator.hasNext()) {
- IElementMementoRequest request = (IElementMementoRequest) iterator.next();
- IElementMementoProvider provider = ViewerAdapterService.getMementoProvider(request.getElement());
- if (provider == null) {
- provider = defaultProvider;
- }
- List reqs = (List) providers.get(provider);
- if (reqs == null) {
- reqs = new ArrayList();
- providers.put(provider, reqs);
- }
- reqs.add(request);
- }
- iterator = providers.entrySet().iterator();
- while (iterator.hasNext()) {
- Entry entry = (Entry) iterator.next();
- IElementMementoProvider provider = (IElementMementoProvider) entry.getKey();
- List reqs = (List) entry.getValue();
- provider.encodeElements((IElementMementoRequest[]) reqs.toArray(new IElementMementoRequest[reqs.size()]));
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IMementoManager#addRequest(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest)
- */
- public synchronized void addRequest(IElementMementoRequest request) {
- requests.add(request);
- }
-
- };
- IModelDeltaVisitor visitor = new IModelDeltaVisitor() {
- public boolean visit(IModelDelta delta, int depth) {
- if (delta.getParentDelta() == null) {
- manager.addRequest(
- new ElementMementoRequest(ModelContentProvider.this, getViewer().getInput(), manager, getPresentationContext(),
- 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;
- }
- };
- rootDelta.accept(visitor);
- stateSaveStarted(manager);
- manager.processReqeusts();
- }
-
- /**
- * Called when a state save is starting.
- *
- * @param manager
- */
- private synchronized void stateSaveStarted(IMementoManager manager) {
- fPendingStateSaves.add(manager);
- }
-
- /**
- * Called when a state save is complete.
- *
- * @param manager
- */
- private synchronized void stateSaveComplete(IMementoManager manager) {
- fPendingStateSaves.remove(manager);
- if (fQueuedRestore != null) {
- Object temp = fQueuedRestore;
- fQueuedRestore = null;
- restoreViewerState(temp);
- }
- }
-
- /**
- * Returns whether any state saving is in progress.
- *
- * @return whether any state saving is in progress
- */
- private synchronized boolean isSavingState() {
- return !fPendingStateSaves.isEmpty();
- }
-
- /**
- * Builds a delta with the given root delta for expansion/selection state.
- *
- * @param delta root delta
- */
- protected abstract void buildViewerState(ModelDelta delta);
-
- /**
- * Uninstalls the model proxy installed for the given element, if any.
- *
- * @param element
- */
- protected synchronized void disposeModelProxy(TreePath path) {
- IModelProxy proxy = (IModelProxy) fTreeModelProxies.remove(path);
- if (proxy != null) {
- proxy.dispose();
- }
- proxy = (IModelProxy) fModelProxies.remove(path.getLastSegment());
- if (proxy != null) {
- proxy.dispose();
- }
- }
-
- /**
- * Uninstalls each model proxy
- */
- protected synchronized void disposeAllModelProxies() {
- Iterator updatePolicies = fModelProxies.values().iterator();
- while (updatePolicies.hasNext()) {
- IModelProxy proxy = (IModelProxy) updatePolicies.next();
- proxy.dispose();
- }
- fModelProxies.clear();
-
- updatePolicies = fTreeModelProxies.values().iterator();
- while (updatePolicies.hasNext()) {
- IModelProxy proxy = (IModelProxy) updatePolicies.next();
- proxy.dispose();
- }
- fTreeModelProxies.clear();
- }
-
- protected synchronized IModelProxy[] getModelProxies() {
- IModelProxy[] proxies = new IModelProxy[fTreeModelProxies.size() + fModelProxies.size()];
- fTreeModelProxies.values().toArray(proxies);
- System.arraycopy(fModelProxies.values().toArray(), 0, proxies, fModelProxies.size(), fModelProxies.size());
- return proxies;
- }
-
- protected synchronized IModelProxy getElementProxy(TreePath path) {
- while (path != null) {
- IModelProxy proxy = (IModelProxy)fTreeModelProxies.get(path);
- if (proxy != null) {
- return proxy;
- }
-
- proxy = (IModelProxy)fModelProxies.get(path.getLastSegment());
- if (proxy != null) {
- return proxy;
- }
-
- path = path.getParentPath();
- }
- return null;
- }
-
- /**
- * Installs the model proxy for the given element into this content provider
- * if not already installed.
- *
- * @param element
- * element to install an update policy for
- */
- protected synchronized void installModelProxy(Object input, TreePath path) {
- if (!fTreeModelProxies.containsKey(path) && !fModelProxies.containsKey(path.getLastSegment())) {
- Object element = path.getSegmentCount() != 0 ? path.getLastSegment() : input;
+ }
+
+ /**
+ * Encodes delta elements into mementos using the given provider.
+ *
+ * @param delta
+ * @param stateProvider
+ */
+ protected void encodeDelta(final ModelDelta rootDelta, final IElementMementoProvider defaultProvider) {
+ final Object input = rootDelta.getElement();
+ final XMLMemento inputMemento = XMLMemento.createWriteRoot("VIEWER_INPUT_MEMENTO"); //$NON-NLS-1$
+ final XMLMemento childrenMemento = XMLMemento.createWriteRoot("CHILDREN_MEMENTO"); //$NON-NLS-1$
+ final IMementoManager manager = new IMementoManager() {
+
+ /**
+ * list of memento requests
+ */
+ private List requests = new ArrayList();
+
+ private boolean abort = false;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.debug.internal.ui.viewers.model.provisional.viewers
+ * .IMementoManager
+ * #requestComplete(org.eclipse.debug.internal.ui.viewers
+ * .model.provisional.IElementMementoRequest)
+ */
+ public synchronized void requestComplete(IElementMementoRequest request) {
+ notifyStateUpdate(input, UPDATE_COMPLETE, request);
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("\tSTATE END: " + request); //$NON-NLS-1$
+ }
+
+ if (!abort) {
+ if (!request.isCanceled() && (request.getStatus() == null || request.getStatus().isOK())) {
+ requests.remove(request);
+ if (requests.isEmpty()) {
+ XMLMemento keyMemento = (XMLMemento) rootDelta.getElement();
+ StringWriter writer = new StringWriter();
+ try {
+ keyMemento.save(writer);
+ fViewerStates.put(writer.toString(), rootDelta);
+ } catch (IOException e) {
+ DebugUIPlugin.log(e);
+ }
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID
+ .equals(getPresentationContext().getId()))) {
+ System.out.println("STATE SAVE COMPLETED: " + rootDelta); //$NON-NLS-1$
+ }
+ stateSaveComplete(input, this);
+ }
+ } else {
+ abort = true;
+ Iterator iterator = requests.iterator();
+ while (iterator.hasNext()) {
+ IElementMementoRequest req = (IElementMementoRequest) iterator.next();
+ req.cancel();
+ }
+ requests.clear();
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext()
+ .getId()))) {
+ System.out.println("STATE SAVE ABORTED: " + rootDelta.getElement()); //$NON-NLS-1$
+ }
+ stateSaveComplete(input, this);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.debug.internal.ui.viewers.model.provisional.viewers
+ * .IMementoManager#processReqeusts()
+ */
+ public synchronized void processReqeusts() {
+ Map providers = new HashMap();
+ Iterator iterator = requests.iterator();
+ while (iterator.hasNext()) {
+ IElementMementoRequest request = (IElementMementoRequest) iterator.next();
+ notifyStateUpdate(input, UPDATE_BEGINS, request);
+ IElementMementoProvider provider = ViewerAdapterService.getMementoProvider(request.getElement());
+ if (provider == null) {
+ provider = defaultProvider;
+ }
+ List reqs = (List) providers.get(provider);
+ if (reqs == null) {
+ reqs = new ArrayList();
+ providers.put(provider, reqs);
+ }
+ reqs.add(request);
+ }
+ iterator = providers.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Entry entry = (Entry) iterator.next();
+ IElementMementoProvider provider = (IElementMementoProvider) entry.getKey();
+ List reqs = (List) entry.getValue();
+ provider.encodeElements((IElementMementoRequest[]) reqs.toArray(new IElementMementoRequest[reqs
+ .size()]));
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.debug.internal.ui.viewers.model.provisional.viewers
+ * .IMementoManager
+ * #addRequest(org.eclipse.debug.internal.ui.viewers.
+ * model.provisional.IElementMementoRequest)
+ */
+ public synchronized void addRequest(IElementMementoRequest request) {
+ requests.add(request);
+ }
+
+ };
+ IModelDeltaVisitor visitor = new IModelDeltaVisitor() {
+ public boolean visit(IModelDelta delta, int depth) {
+ // Add the CONTENT flag to all nodes with an EXPAND flag.
+ // During restoring, this flag is used as a marker indicating
+ // whether all the content of a given element has been
+ // retrieved.
+ if ((delta.getFlags() | IModelDelta.EXPAND) != 0) {
+ ((ModelDelta)delta).setFlags(delta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ // This is the root element, save the root element memento in 'inputMemento'.
+ if (delta.getParentDelta() == null) {
+ manager.addRequest(new ElementMementoRequest(ModelContentProvider.this, input, manager,
+ getPresentationContext(), delta.getElement(), getViewerTreePath(delta), inputMemento,
+ (ModelDelta) delta));
+ } else {
+ // If this is another node element, save the memento to a children memento.
+ if (!(delta.getElement() instanceof XMLMemento)) {
+ manager.addRequest(new ElementMementoRequest(ModelContentProvider.this, input, manager,
+ getPresentationContext(), delta.getElement(), getViewerTreePath(delta), childrenMemento
+ .createChild("CHILD_ELEMENT"), (ModelDelta) delta)); //$NON-NLS-1$
+ }
+ }
+ return true;
+ }
+ };
+ rootDelta.accept(visitor);
+ stateSaveStarted(input, manager);
+ manager.processReqeusts();
+ }
+
+ /**
+ * Called when a state save is starting.
+ *
+ * @param manager
+ */
+ private synchronized void stateSaveStarted(Object input, IMementoManager manager) {
+ notifyStateUpdate(input, STATE_SAVE_SEQUENCE_BEGINS, null);
+ fPendingStateSaves.add(manager);
+ }
+
+ /**
+ * Called when a state save is complete.
+ *
+ * @param manager
+ */
+ private synchronized void stateSaveComplete(Object input, IMementoManager manager) {
+ notifyStateUpdate(input, STATE_SAVE_SEQUENCE_COMPLETE, null);
+ fPendingStateSaves.remove(manager);
+ if (fQueuedRestore != null) {
+ Object temp = fQueuedRestore;
+ fQueuedRestore = null;
+ restoreViewerState(temp);
+ }
+ }
+
+ /**
+ * Returns whether any state saving is in progress.
+ *
+ * @return whether any state saving is in progress
+ */
+ private synchronized boolean isSavingState() {
+ return !fPendingStateSaves.isEmpty();
+ }
+
+ /**
+ * Builds a delta with the given root delta for expansion/selection state.
+ *
+ * @param delta
+ * root delta
+ */
+ protected abstract void buildViewerState(ModelDelta delta);
+
+ /**
+ * Uninstalls the model proxy installed for the given element, if any.
+ *
+ * @param element
+ */
+ protected synchronized void disposeModelProxy(TreePath path) {
+ IModelProxy proxy = (IModelProxy) fTreeModelProxies.remove(path);
+ if (proxy != null) {
+ proxy.dispose();
+ }
+ proxy = (IModelProxy) fModelProxies.remove(path.getLastSegment());
+ if (proxy != null) {
+ proxy.dispose();
+ }
+ }
+
+ /**
+ * Uninstalls each model proxy
+ */
+ protected synchronized void disposeAllModelProxies() {
+ Iterator updatePolicies = fModelProxies.values().iterator();
+ while (updatePolicies.hasNext()) {
+ IModelProxy proxy = (IModelProxy) updatePolicies.next();
+ proxy.dispose();
+ }
+ fModelProxies.clear();
+
+ updatePolicies = fTreeModelProxies.values().iterator();
+ while (updatePolicies.hasNext()) {
+ IModelProxy proxy = (IModelProxy) updatePolicies.next();
+ proxy.dispose();
+ }
+ fTreeModelProxies.clear();
+ }
+
+ protected synchronized IModelProxy[] getModelProxies() {
+ IModelProxy[] proxies = new IModelProxy[fTreeModelProxies.size() + fModelProxies.size()];
+ fTreeModelProxies.values().toArray(proxies);
+ System.arraycopy(fModelProxies.values().toArray(), 0, proxies, fModelProxies.size(), fModelProxies.size());
+ return proxies;
+ }
+
+ protected synchronized IModelProxy getElementProxy(TreePath path) {
+ while (path != null) {
+ IModelProxy proxy = (IModelProxy) fTreeModelProxies.get(path);
+ if (proxy != null) {
+ return proxy;
+ }
+
+ proxy = (IModelProxy) fModelProxies.get(path.getLastSegment());
+ if (proxy != null) {
+ return proxy;
+ }
+
+ path = path.getParentPath();
+ }
+ return null;
+ }
+
+ /**
+ * Installs the model proxy for the given element into this content provider
+ * if not already installed.
+ *
+ * @param element
+ * element to install an update policy for
+ */
+ protected synchronized void installModelProxy(Object input, TreePath path) {
+ if (!fTreeModelProxies.containsKey(path) && !fModelProxies.containsKey(path.getLastSegment())) {
+ Object element = path.getSegmentCount() != 0 ? path.getLastSegment() : input;
IModelProxy proxy = null;
IModelProxyFactory2 modelProxyFactory2 = ViewerAdapterService.getModelProxyFactory2(element);
if (modelProxyFactory2 != null) {
- proxy = modelProxyFactory2.createTreeModelProxy(input, path, getPresentationContext());
- if (proxy != null) {
+ proxy = modelProxyFactory2.createTreeModelProxy(input, path, getPresentationContext());
+ if (proxy != null) {
fTreeModelProxies.put(path, proxy);
- }
- }
+ }
+ }
if (proxy == null) {
IModelProxyFactory modelProxyFactory = ViewerAdapterService.getModelProxyFactory(element);
if (modelProxyFactory != null) {
@@ -1038,87 +1200,95 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
}
}
-
+
if (proxy != null) {
- final IModelProxy finalProxy = proxy;
- if (proxy != null) {
- Job job = new Job("Model Proxy installed notification job") {//$NON-NLS-1$
- protected IStatus run(IProgressMonitor monitor) {
- if (!monitor.isCanceled()) {
- IPresentationContext context = null;
- Viewer viewer = null;
- synchronized (ModelContentProvider.this) {
- if (!isDisposed()) {
- context = getPresentationContext();
- viewer = (Viewer)getViewer();
- }
- }
- if (context != null && !finalProxy.isDisposed()) {
- finalProxy.init(context);
- finalProxy.addModelChangedListener(ModelContentProvider.this);
- finalProxy.installed(viewer);
- }
- }
- return Status.OK_STATUS;
- }
- /* (non-Javadoc)
- * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
- */
- public boolean shouldRun() {
- return !isDisposed();
- }
- };
- job.setSystem(true);
- job.schedule();
- }
- }
- }
- }
-
- /**
- * Returns the presentation context for this content provider.
- *
- * @return presentation context
- */
- protected abstract IPresentationContext getPresentationContext();
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.debug.internal.ui.viewers.provisional.IModelChangedListener#modelChanged(org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta)
- */
- public synchronized void modelChanged(final IModelDelta delta, final IModelProxy proxy) {
- if (fViewer != null && !proxy.isDisposed()) {
- WorkbenchJob job = new WorkbenchJob(fViewer.getDisplay(), "process model delta") { //$NON-NLS-1$
- public IStatus runInUIThread(IProgressMonitor monitor) {
+ final IModelProxy finalProxy = proxy;
+ if (proxy != null) {
+ Job job = new Job("Model Proxy installed notification job") {//$NON-NLS-1$
+ protected IStatus run(IProgressMonitor monitor) {
+ if (!monitor.isCanceled()) {
+ IPresentationContext context = null;
+ Viewer viewer = null;
+ synchronized (ModelContentProvider.this) {
+ if (!isDisposed()) {
+ context = getPresentationContext();
+ viewer = (Viewer) getViewer();
+ }
+ }
+ if (context != null && !finalProxy.isDisposed()) {
+ finalProxy.init(context);
+ finalProxy.addModelChangedListener(ModelContentProvider.this);
+ finalProxy.installed(viewer);
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
+ */
+ public boolean shouldRun() {
+ return !isDisposed();
+ }
+ };
+ job.setSystem(true);
+ job.schedule();
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the presentation context for this content provider.
+ *
+ * @return presentation context
+ */
+ protected abstract IPresentationContext getPresentationContext();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.debug.internal.ui.viewers.provisional.IModelChangedListener
+ * #modelChanged
+ * (org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta)
+ */
+ public synchronized void modelChanged(final IModelDelta delta, final IModelProxy proxy) {
+ if (fViewer != null && !proxy.isDisposed()) {
+ WorkbenchJob job = new WorkbenchJob(fViewer.getDisplay(), "process model delta") { //$NON-NLS-1$
+ public IStatus runInUIThread(IProgressMonitor monitor) {
if (!proxy.isDisposed()) {
- if (DEBUG_DELTAS && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ if (DEBUG_DELTAS
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext()
+ .getId()))) {
DebugUIPlugin.debug("RECEIVED DELTA: " + delta.toString()); //$NON-NLS-1$
}
-
+
updateModel(delta, getModelDeltaMask());
-
+
// Call model listeners after updating the viewer model.
Object[] listeners = fModelListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
- ((IModelChangedListener)listeners[i]).modelChanged(delta, proxy);
+ ((IModelChangedListener) listeners[i]).modelChanged(delta, proxy);
}
}
return Status.OK_STATUS;
- }
- };
- job.setSystem(true);
- job.schedule();
- }
- }
-
- /**
- * @see ITreeModelContentProvider#setModelDeltaMask(int)
- */
+ }
+ };
+ job.setSystem(true);
+ job.schedule();
+ }
+ }
+
+ /**
+ * @see ITreeModelContentProvider#setModelDeltaMask(int)
+ */
public void setModelDeltaMask(int mask) {
fModelDeltaMask = mask;
}
-
+
/**
* @see ITreeModelContentProvider#getModelDeltaMask()
*/
@@ -1127,52 +1297,51 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
public void updateModel(IModelDelta delta, int mask) {
- IModelDelta[] deltaArray = new IModelDelta[] { delta };
- updateNodes(deltaArray,
- mask & (IModelDelta.REMOVED | IModelDelta.UNINSTALL));
- updateNodes(deltaArray,
- mask & ITreeModelContentProvider.UPDATE_MODEL_DELTA_FLAGS & ~(IModelDelta.REMOVED | IModelDelta.UNINSTALL));
- updateNodes(deltaArray,
- mask & ITreeModelContentProvider.CONTROL_MODEL_DELTA_FLAGS);
- }
-
+ IModelDelta[] deltaArray = new IModelDelta[] { delta };
+ updateNodes(deltaArray, mask & (IModelDelta.REMOVED | IModelDelta.UNINSTALL));
+ updateNodes(deltaArray, mask & ITreeModelContentProvider.UPDATE_MODEL_DELTA_FLAGS
+ & ~(IModelDelta.REMOVED | IModelDelta.UNINSTALL));
+ updateNodes(deltaArray, mask & ITreeModelContentProvider.CONTROL_MODEL_DELTA_FLAGS);
+ }
+
/**
- * Updates the viewer with the following deltas.
+ * Updates the viewer with the following deltas.
*
- * @param nodes Model deltas to be processed.
- * @param override If true, it overrides the mode which suppresses
- * processing of SELECT, REVEAL, EXPAND, COLLAPSE flags of
- * {@link IModelDelta}.
- */
- protected void updateNodes(IModelDelta[] nodes, int mask) {
- for (int i = 0; i < nodes.length; i++) {
- IModelDelta node = nodes[i];
- int flags = node.getFlags() & mask;
-
- if ((flags & IModelDelta.ADDED) != 0) {
- handleAdd(node);
- }
- if ((flags & IModelDelta.REMOVED) != 0) {
- handleRemove(node);
- }
- if ((flags & IModelDelta.CONTENT) != 0) {
- handleContent(node);
- }
- if ((flags & IModelDelta.STATE) != 0) {
- handleState(node);
- }
- if ((flags & IModelDelta.INSERTED) != 0) {
- handleInsert(node);
- }
- if ((flags & IModelDelta.REPLACED) != 0) {
- handleReplace(node);
- }
- if ((flags & IModelDelta.INSTALL) != 0) {
- handleInstall(node);
- }
- if ((flags & IModelDelta.UNINSTALL) != 0) {
- handleUninstall(node);
- }
+ * @param nodes
+ * Model deltas to be processed.
+ * @param override
+ * If true, it overrides the mode which suppresses processing of
+ * SELECT, REVEAL, EXPAND, COLLAPSE flags of {@link IModelDelta}.
+ */
+ protected void updateNodes(IModelDelta[] nodes, int mask) {
+ for (int i = 0; i < nodes.length; i++) {
+ IModelDelta node = nodes[i];
+ int flags = node.getFlags() & mask;
+
+ if ((flags & IModelDelta.ADDED) != 0) {
+ handleAdd(node);
+ }
+ if ((flags & IModelDelta.REMOVED) != 0) {
+ handleRemove(node);
+ }
+ if ((flags & IModelDelta.CONTENT) != 0) {
+ handleContent(node);
+ }
+ if ((flags & IModelDelta.STATE) != 0) {
+ handleState(node);
+ }
+ if ((flags & IModelDelta.INSERTED) != 0) {
+ handleInsert(node);
+ }
+ if ((flags & IModelDelta.REPLACED) != 0) {
+ handleReplace(node);
+ }
+ if ((flags & IModelDelta.INSTALL) != 0) {
+ handleInstall(node);
+ }
+ if ((flags & IModelDelta.UNINSTALL) != 0) {
+ handleUninstall(node);
+ }
if ((flags & IModelDelta.EXPAND) != 0) {
handleExpand(node);
}
@@ -1185,432 +1354,502 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
if ((flags & IModelDelta.REVEAL) != 0) {
handleReveal(node);
}
- updateNodes(node.getChildDeltas(), mask);
- }
- }
-
- protected abstract void handleState(IModelDelta delta);
-
- protected abstract void handleSelect(IModelDelta delta);
-
- protected abstract void handleExpand(IModelDelta delta);
-
- protected abstract void handleCollapse(IModelDelta delta);
-
- protected abstract void handleContent(IModelDelta delta);
-
- protected abstract void handleRemove(IModelDelta delta);
-
- protected abstract void handleAdd(IModelDelta delta);
-
- protected abstract void handleInsert(IModelDelta delta);
-
- protected abstract void handleReplace(IModelDelta delta);
-
- protected abstract void handleReveal(IModelDelta delta);
-
- protected void handleInstall(IModelDelta delta) {
- installModelProxy(getViewer().getInput(), getFullTreePath(delta));
- }
-
- protected void handleUninstall(IModelDelta delta) {
- disposeModelProxy(getFullTreePath(delta));
- }
-
- /**
- * Returns a tree path for the node including the root element.
- *
- * @param node
- * model delta
- * @return corresponding tree path
- */
- protected TreePath getFullTreePath(IModelDelta node) {
- ArrayList list = new ArrayList();
- while (node.getParentDelta() != null) {
- list.add(0, node.getElement());
- node = node.getParentDelta();
- }
- return new TreePath(list.toArray());
- }
-
- /**
- * Returns a tree path for the node, *not* including the root element.
- *
- * @param node
- * model delta
- * @return corresponding tree path
- */
- protected TreePath getViewerTreePath(IModelDelta node) {
- ArrayList list = new ArrayList();
- IModelDelta parentDelta = node.getParentDelta();
- while (parentDelta != null) {
- list.add(0, node.getElement());
- node = parentDelta;
- parentDelta = node.getParentDelta();
- }
- return new TreePath(list.toArray());
- }
-
- /**
- * Returns the viewer this content provider is working for.
- *
- * @return viewer
- */
- protected ITreeModelContentProviderTarget getViewer() {
- return fViewer;
- }
-
- /**
- * Translates and returns the given child index from the viewer coordinate
- * space to the model coordinate space.
- *
- * @param parentPath path to parent element
- * @param index index of child element in viewer (filtered) space
- * @return index of child element in model (raw) space
- */
- public /* protected */ int viewToModelIndex(TreePath parentPath, int index) {
- return fTransform.viewToModelIndex(parentPath, index);
- }
-
- /**
- * Translates and returns the given child count from the viewer coordinate
- * space to the model coordinate space.
- *
- * @param parentPath path to parent element
- * @param count number of child elements in viewer (filtered) space
- * @return number of child elements in model (raw) space
- */
- public /* protected */ int viewToModelCount(TreePath parentPath, int count) {
- return fTransform.viewToModelCount(parentPath, count);
- }
-
- /**
- * Translates and returns the given child index from the model coordinate
- * space to the viewer coordinate space.
- *
- * @param parentPath path to parent element
- * @param index index of child element in model (raw) space
- * @return index of child element in viewer (filtered) space or -1 if filtered
- */
- public int modelToViewIndex(TreePath parentPath, int index) {
- return fTransform.modelToViewIndex(parentPath, index);
- }
-
- /**
- * Translates and returns the given child count from the model coordinate
- * space to the viewer coordinate space.
- *
- * @param parentPath path to parent element
- * @param count child count element in model (raw) space
- * @return child count in viewer (filtered) space
- */
- public int modelToViewChildCount(TreePath parentPath, int count) {
- return fTransform.modelToViewCount(parentPath, count);
- }
-
- /**
- * Notes that the child at the specified index of the given parent element
- * has been filtered from the viewer. Returns whether the child at the given
- * index was already filtered.
- *
- * @param parentPath path to parent element
- * @param index index of child element to be filtered
- * @param element the filtered element
- * @return whether the child was already filtered
- */
- protected boolean addFilteredIndex(TreePath parentPath, int index, Object element) {
- return fTransform.addFilteredIndex(parentPath, index, element);
- }
-
- /**
- * Notes that the element at the given index has been removed from its parent
- * and filtered indexes should be updated accordingly.
- *
- * @param parentPath path to parent element
- * @param index index of element that was removed
- */
- protected void removeElementFromFilters(TreePath parentPath, int index) {
- fTransform.removeElementFromFilters(parentPath, index);
- }
-
- /**
- * Removes the given element from filtered elements of the given parent
- * element. Return true if the element was removed, otherwise false.
- *
- * @param parentPath path to parent element
- * @param element element to remove
- * @return whether the element was removed
- */
- protected boolean removeElementFromFilters(TreePath parentPath, Object element) {
- return fTransform.removeElementFromFilters(parentPath, element);
- }
-
- /**
- * The child count for a parent has been computed. Ensure any filtered items
- * above the given count are cleared.
- *
- * @param parentPath path to parent element
- * @param childCount number of children
- */
- protected void setModelChildCount(TreePath parentPath, int childCount) {
- fTransform.setModelChildCount(parentPath, childCount);
- }
-
- /**
- * Returns whether the given element is filtered.
- *
- * @param parentElementOrTreePath
- * the parent element or path
- * @param element
- * the child element
- * @return whether to filter the element
- */
- public boolean shouldFilter(Object parentElementOrTreePath, Object element) {
- ViewerFilter[] filters = fViewer.getFilters();
- if (filters.length > 0) {
- for (int j = 0; j < filters.length; j++) {
- if (!(filters[j].select((Viewer)fViewer, parentElementOrTreePath, element))) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns whether the given index of the specified parent was previously filtered.
- *
- * @param parentPath
- * @param index
- * @return whether the element at the given index was filtered
- */
- protected boolean isFiltered(TreePath parentPath, int index) {
- return fTransform.isFiltered(parentPath, index);
- }
-
- /**
- * Notification the given element is being unmapped.
- *
- * @param path
- */
- public void unmapPath(TreePath path) {
- //System.out.println("Unmap " + path.getLastSegment());
- fTransform.clear(path);
- cancelSubtreeUpdates(path);
- }
-
- /**
- * Returns filtered children or <code>null</code>
- * @param parent
- * @return filtered children or <code>null</code>
- */
- protected int[] getFilteredChildren(TreePath parent) {
- return fTransform.getFilteredChildren(parent);
- }
-
- protected void clearFilteredChild(TreePath parent, int modelIndex) {
- fTransform.clear(parent, modelIndex);
- }
-
- protected void clearFilters(TreePath parent) {
- fTransform.clear(parent);
- }
-
- protected synchronized void checkIfRestoreComplete() {
- if (fPendingState == null) {
- return;
- }
- CheckState state = new CheckState();
- fPendingState.accept(state);
- if (state.isComplete()) {
- if (DEBUG_STATE_SAVE_RESTORE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ updateNodes(node.getChildDeltas(), mask);
+ }
+ }
+
+ protected abstract void handleState(IModelDelta delta);
+
+ protected abstract void handleSelect(IModelDelta delta);
+
+ protected abstract void handleExpand(IModelDelta delta);
+
+ protected abstract void handleCollapse(IModelDelta delta);
+
+ protected abstract void handleContent(IModelDelta delta);
+
+ protected abstract void handleRemove(IModelDelta delta);
+
+ protected abstract void handleAdd(IModelDelta delta);
+
+ protected abstract void handleInsert(IModelDelta delta);
+
+ protected abstract void handleReplace(IModelDelta delta);
+
+ protected abstract void handleReveal(IModelDelta delta);
+
+ protected void handleInstall(IModelDelta delta) {
+ installModelProxy(getViewer().getInput(), getFullTreePath(delta));
+ }
+
+ protected void handleUninstall(IModelDelta delta) {
+ disposeModelProxy(getFullTreePath(delta));
+ }
+
+ /**
+ * Returns a tree path for the node including the root element.
+ *
+ * @param node
+ * model delta
+ * @return corresponding tree path
+ */
+ protected TreePath getFullTreePath(IModelDelta node) {
+ ArrayList list = new ArrayList();
+ while (node.getParentDelta() != null) {
+ list.add(0, node.getElement());
+ node = node.getParentDelta();
+ }
+ return new TreePath(list.toArray());
+ }
+
+ /**
+ * Returns a tree path for the node, *not* including the root element.
+ *
+ * @param node
+ * model delta
+ * @return corresponding tree path
+ */
+ protected TreePath getViewerTreePath(IModelDelta node) {
+ ArrayList list = new ArrayList();
+ IModelDelta parentDelta = node.getParentDelta();
+ while (parentDelta != null) {
+ list.add(0, node.getElement());
+ node = parentDelta;
+ parentDelta = node.getParentDelta();
+ }
+ return new TreePath(list.toArray());
+ }
+
+ /**
+ * Returns the viewer this content provider is working for.
+ *
+ * @return viewer
+ */
+ protected ITreeModelContentProviderTarget getViewer() {
+ return fViewer;
+ }
+
+ /**
+ * Translates and returns the given child index from the viewer coordinate
+ * space to the model coordinate space.
+ *
+ * @param parentPath
+ * path to parent element
+ * @param index
+ * index of child element in viewer (filtered) space
+ * @return index of child element in model (raw) space
+ */
+ public/* protected */int viewToModelIndex(TreePath parentPath, int index) {
+ return fTransform.viewToModelIndex(parentPath, index);
+ }
+
+ /**
+ * Translates and returns the given child count from the viewer coordinate
+ * space to the model coordinate space.
+ *
+ * @param parentPath
+ * path to parent element
+ * @param count
+ * number of child elements in viewer (filtered) space
+ * @return number of child elements in model (raw) space
+ */
+ public/* protected */int viewToModelCount(TreePath parentPath, int count) {
+ return fTransform.viewToModelCount(parentPath, count);
+ }
+
+ /**
+ * Translates and returns the given child index from the model coordinate
+ * space to the viewer coordinate space.
+ *
+ * @param parentPath
+ * path to parent element
+ * @param index
+ * index of child element in model (raw) space
+ * @return index of child element in viewer (filtered) space or -1 if
+ * filtered
+ */
+ public int modelToViewIndex(TreePath parentPath, int index) {
+ return fTransform.modelToViewIndex(parentPath, index);
+ }
+
+ /**
+ * Translates and returns the given child count from the model coordinate
+ * space to the viewer coordinate space.
+ *
+ * @param parentPath
+ * path to parent element
+ * @param count
+ * child count element in model (raw) space
+ * @return child count in viewer (filtered) space
+ */
+ public int modelToViewChildCount(TreePath parentPath, int count) {
+ return fTransform.modelToViewCount(parentPath, count);
+ }
+
+ /**
+ * Notes that the child at the specified index of the given parent element
+ * has been filtered from the viewer. Returns whether the child at the given
+ * index was already filtered.
+ *
+ * @param parentPath
+ * path to parent element
+ * @param index
+ * index of child element to be filtered
+ * @param element
+ * the filtered element
+ * @return whether the child was already filtered
+ */
+ protected boolean addFilteredIndex(TreePath parentPath, int index, Object element) {
+ return fTransform.addFilteredIndex(parentPath, index, element);
+ }
+
+ /**
+ * Notes that the element at the given index has been removed from its
+ * parent and filtered indexes should be updated accordingly.
+ *
+ * @param parentPath
+ * path to parent element
+ * @param index
+ * index of element that was removed
+ */
+ protected void removeElementFromFilters(TreePath parentPath, int index) {
+ fTransform.removeElementFromFilters(parentPath, index);
+ }
+
+ /**
+ * Removes the given element from filtered elements of the given parent
+ * element. Return true if the element was removed, otherwise false.
+ *
+ * @param parentPath
+ * path to parent element
+ * @param element
+ * element to remove
+ * @return whether the element was removed
+ */
+ protected boolean removeElementFromFilters(TreePath parentPath, Object element) {
+ return fTransform.removeElementFromFilters(parentPath, element);
+ }
+
+ /**
+ * The child count for a parent has been computed. Ensure any filtered items
+ * above the given count are cleared.
+ *
+ * @param parentPath
+ * path to parent element
+ * @param childCount
+ * number of children
+ */
+ protected void setModelChildCount(TreePath parentPath, int childCount) {
+ fTransform.setModelChildCount(parentPath, childCount);
+ }
+
+ /**
+ * Returns whether the given element is filtered.
+ *
+ * @param parentElementOrTreePath
+ * the parent element or path
+ * @param element
+ * the child element
+ * @return whether to filter the element
+ */
+ public boolean shouldFilter(Object parentElementOrTreePath, Object element) {
+ ViewerFilter[] filters = fViewer.getFilters();
+ if (filters.length > 0) {
+ for (int j = 0; j < filters.length; j++) {
+ if (!(filters[j].select((Viewer) fViewer, parentElementOrTreePath, element))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether the given index of the specified parent was previously
+ * filtered.
+ *
+ * @param parentPath
+ * @param index
+ * @return whether the element at the given index was filtered
+ */
+ protected boolean isFiltered(TreePath parentPath, int index) {
+ return fTransform.isFiltered(parentPath, index);
+ }
+
+ /**
+ * Notification the given element is being unmapped.
+ *
+ * @param path
+ */
+ public void unmapPath(TreePath path) {
+ // System.out.println("Unmap " + path.getLastSegment());
+ fTransform.clear(path);
+ cancelSubtreeUpdates(path);
+ }
+
+ /**
+ * Returns filtered children or <code>null</code>
+ *
+ * @param parent
+ * @return filtered children or <code>null</code>
+ */
+ protected int[] getFilteredChildren(TreePath parent) {
+ return fTransform.getFilteredChildren(parent);
+ }
+
+ protected void clearFilteredChild(TreePath parent, int modelIndex) {
+ fTransform.clear(parent, modelIndex);
+ }
+
+ protected void clearFilters(TreePath parent) {
+ fTransform.clear(parent);
+ }
+
+ protected synchronized void checkIfRestoreComplete() {
+ if (fPendingState == null) {
+ return;
+ }
+ CheckState state = new CheckState();
+ fPendingState.accept(state);
+ if (state.isComplete()) {
+ if (DEBUG_STATE_SAVE_RESTORE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
System.out.println("STATE RESTORE COMPELTE: " + fPendingState); //$NON-NLS-1$
}
- fPendingState = null;
- }
- }
-
- public void addViewerUpdateListener(IViewerUpdateListener listener) {
- fUpdateListeners.add(listener);
- }
-
- public void removeViewerUpdateListener(IViewerUpdateListener listener) {
- fUpdateListeners.remove(listener);
- }
-
- /**
- * Notification an update request has started
- *
- * @param update
- */
- void updateStarted(ViewerUpdateMonitor update) {
- boolean begin = false;
- synchronized (fRequestsInProgress) {
- begin = fRequestsInProgress.isEmpty();
- List requests = (List) fRequestsInProgress.get(update.getSchedulingPath());
- if (requests == null) {
- requests = new ArrayList();
- fRequestsInProgress.put(update.getSchedulingPath(), requests);
- }
- requests.add(update);
- }
- if (begin) {
- if (DEBUG_UPDATE_SEQUENCE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("MODEL SEQUENCE BEGINS"); //$NON-NLS-1$
- }
- notifyUpdate(UPDATE_SEQUENCE_BEGINS, null);
- }
- if (DEBUG_UPDATE_SEQUENCE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("\tBEGIN - " + update); //$NON-NLS-1$
- }
- notifyUpdate(UPDATE_BEGINS, update);
- }
-
- /**
- * Notification an update request has completed
- *
- * @param update
- */
- void updateComplete(ViewerUpdateMonitor update) {
- boolean end = false;
- synchronized (fRequestsInProgress) {
- List requests = (List) fRequestsInProgress.get(update.getSchedulingPath());
- if (requests != null) {
- requests.remove(update);
- trigger(update);
- if (requests.isEmpty()) {
- fRequestsInProgress.remove(update.getSchedulingPath());
- }
- }
- end = fRequestsInProgress.isEmpty();
- }
- notifyUpdate(UPDATE_COMPLETE, update);
- if (DEBUG_UPDATE_SEQUENCE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("\tEND - " + update); //$NON-NLS-1$
- }
- if (end) {
- if (DEBUG_UPDATE_SEQUENCE && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("MODEL SEQUENCE ENDS"); //$NON-NLS-1$
- }
- notifyUpdate(UPDATE_SEQUENCE_COMPLETE, null);
- }
- }
-
- protected void notifyUpdate(final int type, final IViewerUpdate update) {
- if (!fUpdateListeners.isEmpty()) {
- Object[] listeners = fUpdateListeners.getListeners();
- for (int i = 0; i < listeners.length; i++) {
- final IViewerUpdateListener listener = (IViewerUpdateListener) listeners[i];
- SafeRunner.run(new ISafeRunnable() {
- public void run() throws Exception {
- switch (type) {
- case UPDATE_SEQUENCE_BEGINS:
- listener.viewerUpdatesBegin();
- break;
- case UPDATE_SEQUENCE_COMPLETE:
- listener.viewerUpdatesComplete();
- break;
- case UPDATE_BEGINS:
- listener.updateStarted(update);
- break;
- case UPDATE_COMPLETE:
- listener.updateComplete(update);
- break;
- }
- }
- public void handleException(Throwable exception) {
- DebugUIPlugin.log(exception);
- }
- });
- }
- }
- }
-
- protected void cancelSubtreeUpdates(TreePath path) {
- synchronized (fRequestsInProgress) {
- Iterator iterator = fRequestsInProgress.entrySet().iterator();
- while (iterator.hasNext()) {
- Entry entry = (Entry) iterator.next();
- TreePath entryPath = (TreePath) entry.getKey();
- if (entryPath.startsWith(path, null)) {
- List requests = (List) entry.getValue();
- Iterator reqIter = requests.iterator();
- while (reqIter.hasNext()) {
- ((IRequest)reqIter.next()).cancel();
- }
- }
- }
- List purge = new ArrayList();
- iterator = fWaitingRequests.keySet().iterator();
- while (iterator.hasNext()) {
- TreePath entryPath = (TreePath) iterator.next();
- if (entryPath.startsWith(path, null)) {
- purge.add(entryPath);
- }
- }
- iterator = purge.iterator();
- while (iterator.hasNext()) {
- 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();
- }
- }
- }
-
-
-
- /**
- * Returns whether this given request should be run, or should wait for parent
- * update to complete.
- *
- * @param update
- * @return whether to start the given request
- */
- void schedule(ViewerUpdateMonitor update) {
- synchronized (fRequestsInProgress) {
- TreePath schedulingPath = update.getSchedulingPath();
- List requests = (List) fWaitingRequests.get(schedulingPath);
- if (requests == null) {
- // no waiting requests
- TreePath parentPath = schedulingPath;
- while (fRequestsInProgress.get(parentPath) == null) {
- parentPath = parentPath.getParentPath();
- if (parentPath == null) {
- // no running requests: start request
- update.start();
- return;
- }
- }
- // request running on parent, add to waiting list
- requests = new ArrayList();
- requests.add(update);
- fWaitingRequests.put(schedulingPath, requests);
- } else {
- // there are waiting requests: coalesce with existing request?
- Iterator reqIter = requests.iterator();
- while (reqIter.hasNext()) {
- ViewerUpdateMonitor waiting = (ViewerUpdateMonitor) reqIter.next();
- if (waiting.coalesce(update)) {
- // coalesced with existing request, done
- return;
- }
- }
- // add to list of waiting requests
- requests.add(update);
- return;
- }
- }
- }
-
- protected boolean getElementChildrenRealized(TreePath path) {
- synchronized (fRequestsInProgress) {
- List requests = (List)fWaitingRequests.get(path);
+ notifyStateUpdate(fPendingState.getElement(), STATE_RESTORE_SEQUENCE_COMPLETE, null);
+ fPendingState = null;
+ }
+ }
+
+ public void addViewerUpdateListener(IViewerUpdateListener listener) {
+ fUpdateListeners.add(listener);
+ }
+
+ public void removeViewerUpdateListener(IViewerUpdateListener listener) {
+ fUpdateListeners.remove(listener);
+ }
+
+ /**
+ * Notification an update request has started
+ *
+ * @param update
+ */
+ void updateStarted(ViewerUpdateMonitor update) {
+ boolean begin = false;
+ synchronized (fRequestsInProgress) {
+ begin = fRequestsInProgress.isEmpty();
+ List requests = (List) fRequestsInProgress.get(update.getSchedulingPath());
+ if (requests == null) {
+ requests = new ArrayList();
+ fRequestsInProgress.put(update.getSchedulingPath(), requests);
+ }
+ requests.add(update);
+ }
+ if (begin) {
+ if (DEBUG_UPDATE_SEQUENCE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("MODEL SEQUENCE BEGINS"); //$NON-NLS-1$
+ }
+ notifyUpdate(UPDATE_SEQUENCE_BEGINS, null);
+ }
+ if (DEBUG_UPDATE_SEQUENCE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("\tBEGIN - " + update); //$NON-NLS-1$
+ }
+ notifyUpdate(UPDATE_BEGINS, update);
+ }
+
+ /**
+ * Notification an update request has completed
+ *
+ * @param update
+ */
+ void updateComplete(ViewerUpdateMonitor update) {
+ boolean end = false;
+ synchronized (fRequestsInProgress) {
+ List requests = (List) fRequestsInProgress.get(update.getSchedulingPath());
+ if (requests != null) {
+ requests.remove(update);
+ trigger(update);
+ if (requests.isEmpty()) {
+ fRequestsInProgress.remove(update.getSchedulingPath());
+ }
+ }
+ end = fRequestsInProgress.isEmpty();
+ }
+ notifyUpdate(UPDATE_COMPLETE, update);
+ if (DEBUG_UPDATE_SEQUENCE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("\tEND - " + update); //$NON-NLS-1$
+ }
+ if (end) {
+ if (DEBUG_UPDATE_SEQUENCE
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
+ System.out.println("MODEL SEQUENCE ENDS"); //$NON-NLS-1$
+ }
+ notifyUpdate(UPDATE_SEQUENCE_COMPLETE, null);
+ }
+ }
+
+ protected void notifyUpdate(final int type, final IViewerUpdate update) {
+ if (!fUpdateListeners.isEmpty()) {
+ Object[] listeners = fUpdateListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ final IViewerUpdateListener listener = (IViewerUpdateListener) listeners[i];
+ SafeRunner.run(new ISafeRunnable() {
+ public void run() throws Exception {
+ switch (type) {
+ case UPDATE_SEQUENCE_BEGINS:
+ listener.viewerUpdatesBegin();
+ break;
+ case UPDATE_SEQUENCE_COMPLETE:
+ listener.viewerUpdatesComplete();
+ break;
+ case UPDATE_BEGINS:
+ listener.updateStarted(update);
+ break;
+ case UPDATE_COMPLETE:
+ listener.updateComplete(update);
+ break;
+ }
+ }
+
+ public void handleException(Throwable exception) {
+ DebugUIPlugin.log(exception);
+ }
+ });
+ }
+ }
+ }
+
+ public void addStateUpdateListener(IStateUpdateListener listener) {
+ fStateUpdateListeners.add(listener);
+ }
+
+ public void removeStateUpdateListener(IStateUpdateListener listener) {
+ fStateUpdateListeners.remove(listener);
+ }
+
+ protected void notifyStateUpdate(final Object input, final int type, final IViewerUpdate update) {
+ if (!fStateUpdateListeners.isEmpty()) {
+ Object[] listeners = fStateUpdateListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ final IStateUpdateListener listener = (IStateUpdateListener) listeners[i];
+ SafeRunner.run(new ISafeRunnable() {
+ public void run() throws Exception {
+ switch (type) {
+ case STATE_SAVE_SEQUENCE_BEGINS:
+ listener.stateSaveUpdatesBegin(input);
+ break;
+ case STATE_SAVE_SEQUENCE_COMPLETE:
+ listener.stateSaveUpdatesComplete(input);
+ break;
+ case STATE_RESTORE_SEQUENCE_BEGINS:
+ listener.stateRestoreUpdatesBegin(input);
+ break;
+ case STATE_RESTORE_SEQUENCE_COMPLETE:
+ listener.stateRestoreUpdatesComplete(input);
+ break;
+ case UPDATE_BEGINS:
+ listener.stateUpdateStarted(input, update);
+ break;
+ case UPDATE_COMPLETE:
+ listener.stateUpdateComplete(input, update);
+ break;
+ }
+ }
+
+ public void handleException(Throwable exception) {
+ DebugUIPlugin.log(exception);
+ }
+ });
+ }
+ }
+ }
+
+ protected void cancelSubtreeUpdates(TreePath path) {
+ synchronized (fRequestsInProgress) {
+ Iterator iterator = fRequestsInProgress.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Entry entry = (Entry) iterator.next();
+ TreePath entryPath = (TreePath) entry.getKey();
+ if (entryPath.startsWith(path, null)) {
+ List requests = (List) entry.getValue();
+ Iterator reqIter = requests.iterator();
+ while (reqIter.hasNext()) {
+ ((IRequest) reqIter.next()).cancel();
+ }
+ }
+ }
+ List purge = new ArrayList();
+ iterator = fWaitingRequests.keySet().iterator();
+ while (iterator.hasNext()) {
+ TreePath entryPath = (TreePath) iterator.next();
+ if (entryPath.startsWith(path, null)) {
+ purge.add(entryPath);
+ }
+ }
+ iterator = purge.iterator();
+ while (iterator.hasNext()) {
+ 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();
+ }
+ }
+ }
+
+ /**
+ * Returns whether this given request should be run, or should wait for
+ * parent update to complete.
+ *
+ * @param update
+ * @return whether to start the given request
+ */
+ void schedule(ViewerUpdateMonitor update) {
+ synchronized (fRequestsInProgress) {
+ TreePath schedulingPath = update.getSchedulingPath();
+ List requests = (List) fWaitingRequests.get(schedulingPath);
+ if (requests == null) {
+ // no waiting requests
+ TreePath parentPath = schedulingPath;
+ while (fRequestsInProgress.get(parentPath) == null) {
+ parentPath = parentPath.getParentPath();
+ if (parentPath == null) {
+ // no running requests: start request
+ update.start();
+ return;
+ }
+ }
+ // request running on parent, add to waiting list
+ requests = new ArrayList();
+ requests.add(update);
+ fWaitingRequests.put(schedulingPath, requests);
+ } else {
+ // there are waiting requests: coalesce with existing request?
+ Iterator reqIter = requests.iterator();
+ while (reqIter.hasNext()) {
+ ViewerUpdateMonitor waiting = (ViewerUpdateMonitor) reqIter.next();
+ if (waiting.coalesce(update)) {
+ // coalesced with existing request, done
+ return;
+ }
+ }
+ // add to list of waiting requests
+ requests.add(update);
+ return;
+ }
+ }
+ }
+
+ 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) {
@@ -1618,173 +1857,179 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
}
}
}
- 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;
- }
- }
- }
- }
- }
-
+ 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.
- *
- * TODO: should we cancel child updates if a request has been canceled?
- *
- * @param request
- */
- void trigger(ViewerUpdateMonitor request) {
- if (fWaitingRequests.isEmpty()) {
- return;
- }
- TreePath schedulingPath = request.getSchedulingPath();
- List waiting = (List) fWaitingRequests.get(schedulingPath);
- if (waiting == null) {
- // no waiting, update the entry with the shortest path
- int length = Integer.MAX_VALUE;
- Iterator entries = fWaitingRequests.entrySet().iterator();
- Entry candidate = null;
- while (entries.hasNext()) {
- Entry entry = (Entry) entries.next();
- TreePath key = (TreePath) entry.getKey();
- if (key.getSegmentCount() < length) {
- candidate = entry;
- length = key.getSegmentCount();
- }
- }
- if (candidate != null) {
- startHighestPriorityRequest((TreePath) candidate.getKey(), (List) candidate.getValue());
- }
- } else {
- // start the highest priority request
- startHighestPriorityRequest(schedulingPath, waiting);
- }
- }
-
- /**
- * @param key
- * @param waiting
- */
- private void startHighestPriorityRequest(TreePath key, List waiting) {
- int priority = 4;
- ViewerUpdateMonitor next = null;
- Iterator requests = waiting.iterator();
- while (requests.hasNext()) {
- ViewerUpdateMonitor vu = (ViewerUpdateMonitor) requests.next();
- if (vu.getPriority() < priority) {
- next = vu;
- priority = next.getPriority();
- }
- }
- waiting.remove(next);
- if (waiting.isEmpty()) {
- fWaitingRequests.remove(key);
- }
- next.start();
- }
-
- /**
- * Registers the given listener for model delta notification.
- *
- * @param listener model delta listener
- */
- public void addModelChangedListener(IModelChangedListener listener) {
- fModelListeners.add(listener);
- }
-
- /**
- * Unregisters the given listener from model delta notification.
- *
- * @param listener model delta listener
- */
- public void removeModelChangedListener(IModelChangedListener listener) {
- fModelListeners.remove(listener);
- }
-
- /**
- * Returns the element corresponding to the given tree path.
- *
- * @param path tree path
- * @return model element
- */
- protected Object getElement(TreePath path) {
- if (path.getSegmentCount() > 0) {
- return path.getLastSegment();
- }
- return getViewer().getInput();
- }
-
- /**
- * Reschedule any children updates in progress for the given parent
- * that have a start index greater than the given index. An element
- * has been removed at this index, invalidating updates in progress.
- *
- * @param parentPath view tree path to parent element
- * @param modelIndex index at which an element was removed
- */
- protected void rescheduleUpdates(TreePath parentPath, int modelIndex) {
- synchronized (fRequestsInProgress) {
- List requests = (List)fRequestsInProgress.get(parentPath);
- List reCreate = null;
- if (requests != null) {
- Iterator iterator = requests.iterator();
- while (iterator.hasNext()) {
- IViewerUpdate update = (IViewerUpdate) iterator.next();
- if (update instanceof IChildrenUpdate) {
- IChildrenUpdate childrenUpdate = (IChildrenUpdate) update;
- if (childrenUpdate.getOffset() > modelIndex) {
- childrenUpdate.cancel();
- if (reCreate == null) {
- reCreate = new ArrayList();
- }
- reCreate.add(childrenUpdate);
- if (DEBUG_CONTENT_PROVIDER && getPresentationContext().getId().equals(DEBUG_PRESENTATION_ID)) {
- System.out.println("canceled update in progress handling REMOVE: " + childrenUpdate); //$NON-NLS-1$
- }
- }
- }
- }
- }
- requests = (List)fWaitingRequests.get(parentPath);
- if (requests != null) {
- Iterator iterator = requests.iterator();
- while (iterator.hasNext()) {
- IViewerUpdate update = (IViewerUpdate) iterator.next();
- if (update instanceof IChildrenUpdate) {
- IChildrenUpdate childrenUpdate = (IChildrenUpdate) update;
- if (childrenUpdate.getOffset() > modelIndex) {
- ((ChildrenUpdate)childrenUpdate).setOffset(childrenUpdate.getOffset() - 1);
- if (DEBUG_CONTENT_PROVIDER && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID.equals(getPresentationContext().getId()))) {
- System.out.println("modified waiting update handling REMOVE: " + childrenUpdate); //$NON-NLS-1$
- }
- }
- }
- }
- }
- // re-schedule canceled updates at new position.
- // have to do this last else the requests would be waiting and
- // get modified.
- if (reCreate != null) {
- Iterator iterator = reCreate.iterator();
- while (iterator.hasNext()) {
- IChildrenUpdate childrenUpdate = (IChildrenUpdate) iterator.next();
- int start = childrenUpdate.getOffset() - 1;
- int end = start + childrenUpdate.getLength();
- for (int i = start; i < end; i++) {
- ((TreeModelContentProvider)this).doUpdateElement(parentPath, i);
- }
- }
- }
- }
- }
+
+ /**
+ * Triggers waiting requests based on the given request that just completed.
+ *
+ * TODO: should we cancel child updates if a request has been canceled?
+ *
+ * @param request
+ */
+ void trigger(ViewerUpdateMonitor request) {
+ if (fWaitingRequests.isEmpty()) {
+ return;
+ }
+ TreePath schedulingPath = request.getSchedulingPath();
+ List waiting = (List) fWaitingRequests.get(schedulingPath);
+ if (waiting == null) {
+ // no waiting, update the entry with the shortest path
+ int length = Integer.MAX_VALUE;
+ Iterator entries = fWaitingRequests.entrySet().iterator();
+ Entry candidate = null;
+ while (entries.hasNext()) {
+ Entry entry = (Entry) entries.next();
+ TreePath key = (TreePath) entry.getKey();
+ if (key.getSegmentCount() < length) {
+ candidate = entry;
+ length = key.getSegmentCount();
+ }
+ }
+ if (candidate != null) {
+ startHighestPriorityRequest((TreePath) candidate.getKey(), (List) candidate.getValue());
+ }
+ } else {
+ // start the highest priority request
+ startHighestPriorityRequest(schedulingPath, waiting);
+ }
+ }
+
+ /**
+ * @param key
+ * @param waiting
+ */
+ private void startHighestPriorityRequest(TreePath key, List waiting) {
+ int priority = 4;
+ ViewerUpdateMonitor next = null;
+ Iterator requests = waiting.iterator();
+ while (requests.hasNext()) {
+ ViewerUpdateMonitor vu = (ViewerUpdateMonitor) requests.next();
+ if (vu.getPriority() < priority) {
+ next = vu;
+ priority = next.getPriority();
+ }
+ }
+ waiting.remove(next);
+ if (waiting.isEmpty()) {
+ fWaitingRequests.remove(key);
+ }
+ next.start();
+ }
+
+ /**
+ * Registers the given listener for model delta notification.
+ *
+ * @param listener
+ * model delta listener
+ */
+ public void addModelChangedListener(IModelChangedListener listener) {
+ fModelListeners.add(listener);
+ }
+
+ /**
+ * Unregisters the given listener from model delta notification.
+ *
+ * @param listener
+ * model delta listener
+ */
+ public void removeModelChangedListener(IModelChangedListener listener) {
+ fModelListeners.remove(listener);
+ }
+
+ /**
+ * Returns the element corresponding to the given tree path.
+ *
+ * @param path
+ * tree path
+ * @return model element
+ */
+ protected Object getElement(TreePath path) {
+ if (path.getSegmentCount() > 0) {
+ return path.getLastSegment();
+ }
+ return getViewer().getInput();
+ }
+
+ /**
+ * Reschedule any children updates in progress for the given parent that
+ * have a start index greater than the given index. An element has been
+ * removed at this index, invalidating updates in progress.
+ *
+ * @param parentPath
+ * view tree path to parent element
+ * @param modelIndex
+ * index at which an element was removed
+ */
+ protected void rescheduleUpdates(TreePath parentPath, int modelIndex) {
+ synchronized (fRequestsInProgress) {
+ List requests = (List) fRequestsInProgress.get(parentPath);
+ List reCreate = null;
+ if (requests != null) {
+ Iterator iterator = requests.iterator();
+ while (iterator.hasNext()) {
+ IViewerUpdate update = (IViewerUpdate) iterator.next();
+ if (update instanceof IChildrenUpdate) {
+ IChildrenUpdate childrenUpdate = (IChildrenUpdate) update;
+ if (childrenUpdate.getOffset() > modelIndex) {
+ childrenUpdate.cancel();
+ if (reCreate == null) {
+ reCreate = new ArrayList();
+ }
+ reCreate.add(childrenUpdate);
+ if (DEBUG_CONTENT_PROVIDER
+ && getPresentationContext().getId().equals(DEBUG_PRESENTATION_ID)) {
+ System.out.println("canceled update in progress handling REMOVE: " + childrenUpdate); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ requests = (List) fWaitingRequests.get(parentPath);
+ if (requests != null) {
+ Iterator iterator = requests.iterator();
+ while (iterator.hasNext()) {
+ IViewerUpdate update = (IViewerUpdate) iterator.next();
+ if (update instanceof IChildrenUpdate) {
+ IChildrenUpdate childrenUpdate = (IChildrenUpdate) update;
+ if (childrenUpdate.getOffset() > modelIndex) {
+ ((ChildrenUpdate) childrenUpdate).setOffset(childrenUpdate.getOffset() - 1);
+ if (DEBUG_CONTENT_PROVIDER
+ && (DEBUG_PRESENTATION_ID == null || DEBUG_PRESENTATION_ID
+ .equals(getPresentationContext().getId()))) {
+ System.out.println("modified waiting update handling REMOVE: " + childrenUpdate); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ // re-schedule canceled updates at new position.
+ // have to do this last else the requests would be waiting and
+ // get modified.
+ if (reCreate != null) {
+ Iterator iterator = reCreate.iterator();
+ while (iterator.hasNext()) {
+ IChildrenUpdate childrenUpdate = (IChildrenUpdate) iterator.next();
+ int start = childrenUpdate.getOffset() - 1;
+ int end = start + childrenUpdate.getLength();
+ for (int i = start; i < end; i++) {
+ ((TreeModelContentProvider) this).doUpdateElement(parentPath, i);
+ }
+ }
+ }
+ }
+ }
}
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 bc3c04cc5..f30f9b3cb 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
@@ -13,6 +13,7 @@ package org.eclipse.debug.internal.ui.viewers.model;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IStateUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
@@ -276,6 +277,10 @@ public class SubTreeModelViewer extends TreeModelViewer {
SubTreeModelViewer.this.addModelChangedListener(listener);
}
+ public void addStateUpdateListener(IStateUpdateListener listener) {
+ SubTreeModelViewer.this.addStateUpdateListener(listener);
+ }
+
public void addViewerUpdateListener(IViewerUpdateListener listener) {
SubTreeModelViewer.this.addViewerUpdateListener(listener);
}
@@ -304,6 +309,10 @@ public class SubTreeModelViewer extends TreeModelViewer {
SubTreeModelViewer.this.removeModelChangedListener(listener);
}
+ public void removeStateUpdateListener(IStateUpdateListener listener) {
+ SubTreeModelViewer.this.removeStateUpdateListener(listener);
+ }
+
public void removeViewerUpdateListener(IViewerUpdateListener listener) {
SubTreeModelViewer.this.removeViewerUpdateListener(listener);
}
@@ -378,6 +387,10 @@ public class SubTreeModelViewer extends TreeModelViewer {
fBaseProvider.addModelChangedListener(listener);
}
+ public void addStateUpdateListener(IStateUpdateListener listener) {
+ fBaseProvider.addStateUpdateListener(listener);
+ }
+
public void addViewerUpdateListener(IViewerUpdateListener listener) {
fBaseProvider.addViewerUpdateListener(listener);
}
@@ -398,6 +411,10 @@ public class SubTreeModelViewer extends TreeModelViewer {
fBaseProvider.removeModelChangedListener(listener);
}
+ public void removeStateUpdateListener(IStateUpdateListener listener) {
+ fBaseProvider.removeStateUpdateListener(listener);
+ }
+
public void removeViewerUpdateListener(IViewerUpdateListener listener) {
fBaseProvider.removeViewerUpdateListener(listener);
}
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 2149b3896..abd200ebc 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
@@ -547,14 +547,14 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
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$
+ System.out.println("\tRESTORE 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$
+ System.out.println("\tRESTORE COLLAPSE: " + treePath.getLastSegment()); //$NON-NLS-1$
}
getViewer().setExpandedState(treePath, false);
delta.setFlags(delta.getFlags() & ~IModelDelta.COLLAPSE);
@@ -584,7 +584,7 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
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$
+ System.out.println("\tRESTORE REVEAL: " + treePath.getLastSegment()); //$NON-NLS-1$
}
viewer.reveal(parentPath, index);
}
@@ -621,7 +621,7 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
(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$
+ System.out.println("\tRESTORE CONTENT: " + treePath.getLastSegment()); //$NON-NLS-1$
}
delta.setFlags(delta.getFlags() & ~IModelDelta.CONTENT);
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IStateUpdateListener.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IStateUpdateListener.java
new file mode 100644
index 000000000..d88ae2946
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IStateUpdateListener.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.viewers.model.provisional;
+
+
+/**
+ * Listener for viewer state updates.
+ *
+ * @since 3.6
+ */
+public interface IStateUpdateListener {
+
+ /**
+ * Notification that a sequence of state saving updates are starting.
+ */
+ public void stateSaveUpdatesBegin(Object input);
+
+ /**
+ * Notification that viewer updates are complete. Corresponds to
+ * a <code>viewerUpdatesBegin()</code> notification.
+ */
+ public void stateSaveUpdatesComplete(Object input);
+
+ /**
+ * Notification that a sequence of viewer updates are starting.
+ */
+ public void stateRestoreUpdatesBegin(Object input);
+
+ /**
+ * Notification that viewer updates are complete. Corresponds to
+ * a <code>viewerUpdatesBegin()</code> notification.
+ */
+ public void stateRestoreUpdatesComplete(Object input);
+
+ /**
+ * Notification that a specific update has started within
+ * a sequence of updates.
+ *
+ * @param update update
+ */
+ public void stateUpdateStarted(Object input, IViewerUpdate update);
+
+ /**
+ * Notification that a specific update has completed within a
+ * sequence of updates.
+ *
+ * @param update update
+ */
+ public void stateUpdateComplete(Object input, IViewerUpdate update);
+}

Back to the top