Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Piech2009-09-25 22:44:00 +0000
committerPawel Piech2009-09-25 22:44:00 +0000
commit819f593395137640fa5faf8124751f93e40a4f78 (patch)
tree9a3d789a87b8bdeea91966a550f88e0e4a94d548
parent66c6f5f8b5a34ba152ed2e08b166a9a167967a31 (diff)
downloadeclipse.platform.debug-819f593395137640fa5faf8124751f93e40a4f78.tar.gz
eclipse.platform.debug-819f593395137640fa5faf8124751f93e40a4f78.tar.xz
eclipse.platform.debug-819f593395137640fa5faf8124751f93e40a4f78.zip
Bug 241336 - [flexible hierarchy] IModelProxyFactory.createModelProxy() should take the full path to element.
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java72
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java265
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java31
-rw-r--r--org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java14
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java109
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java1
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ViewerAdapterService.java16
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelProxyFactory2.java48
8 files changed, 452 insertions, 104 deletions
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java
index 87c326548..79fb7a56a 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java
@@ -121,9 +121,9 @@ abstract public class DeltaTests extends TestCase {
TestElement element = model.getRootElement().getChildren()[0];
TreePath elementPath = new TreePath(new Object[] { element });
TestElement[] newChildren = new TestElement[] {
- model.new TestElement("1.1", new TestElement[0]),
- model.new TestElement("1.2", new TestElement[0]),
- model.new TestElement("1.3", new TestElement[0]),
+ new TestElement(model, "1.1", new TestElement[0]),
+ new TestElement(model, "1.2", new TestElement[0]),
+ new TestElement(model, "1.3", new TestElement[0]),
};
ModelDelta delta = model.setElementChildren(elementPath, newChildren);
@@ -148,7 +148,7 @@ abstract public class DeltaTests extends TestCase {
model.validateData(fViewer, TreePath.EMPTY);
// Update the model
- TestElement element = model.new TestElement("7", new TestElement[0]);
+ TestElement element = new TestElement(model, "7", new TestElement[0]);
TreePath elementPath = new TreePath(new Object[] { element });
ModelDelta delta = model.insertElementChild(TreePath.EMPTY, 6, element);
@@ -182,7 +182,7 @@ abstract public class DeltaTests extends TestCase {
model.validateData(fViewer, TreePath.EMPTY);
// Update the model
- TestElement element = model.new TestElement("7", new TestElement[0]);
+ TestElement element = new TestElement(model, "7", new TestElement[0]);
TreePath elementPath = new TreePath(new Object[] { element });
ModelDelta delta = model.addElementChild(TreePath.EMPTY, 6, element);
@@ -304,5 +304,67 @@ abstract public class DeltaTests extends TestCase {
}
}
+ public void testCompositeModelRefreshStruct() {
+ //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer);
+
+ TestModel model = TestModel.compositeMultiLevel();
+ fViewer.setAutoExpandLevel(-1);
+
+ // Create the listener
+ // TODO: redundant updates on install deltas
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false);
+
+ // Set the input into the view and update the view.
+ fViewer.setInput(model.getRootElement());
+ while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY, true);
+ // Update the model
+ TreePath m4_2_1Path = model.findElement("m4.2.1");
+ TestElement m4_2_1 = model.getElement(m4_2_1Path);
+ TestModel m4 = m4_2_1.getModel();
+ TestElement[] newChildren = new TestElement[] {
+ new TestElement(m4, "4.2.1.new-1", new TestElement[0]),
+ new TestElement(m4, "4.2.1.new-2", new TestElement[0]),
+ new TestElement(m4, "4.2.1.new-3", new TestElement[0]),
+ };
+
+ ModelDelta delta = m4.setElementChildren(m4_2_1Path, newChildren);
+
+ fListener.reset(m4_2_1Path, m4_2_1, -1, true, false);
+ model.postDelta(delta);
+ while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY);
+ }
+
+ public void testCompositeModelAddElement() {
+ TestModel model = TestModel.compositeMultiLevel();
+ fViewer.setAutoExpandLevel(-1);
+
+ // Create the listener
+ // TODO: redundant updates on install deltas
+ fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false);
+
+ // Set the input into the view and update the view.
+ fViewer.setInput(model.getRootElement());
+ while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+ model.validateData(fViewer, TreePath.EMPTY, true);
+
+ TreePath m3_1Path = model.findElement("m3.1");
+ TestElement m3_1 = model.getElement(m3_1Path);
+ TestModel m3 = m3_1.getModel();
+ TestElement m3_1_new = new TestElement(m3, "m3.1-new", new TestElement[0]);
+ TreePath m3_1_newPath = m3_1Path.createChildPath(m3_1_new);
+ ModelDelta delta = m3.addElementChild(m3_1Path, 0, m3_1_new);
+
+ fListener.reset(m3_1_newPath, m3_1_new, -1, true, false);
+ fListener.addChildreUpdate(m3_1Path, 0);
+ fListener.setFailOnRedundantUpdates(false);
+
+ m3.postDelta(delta);
+ while (!fListener.isFinished(TestModelUpdatesListener.ALL_UPDATES_COMPLETE | TestModelUpdatesListener.MODEL_CHANGED_COMPLETE))
+ if (!fDisplay.readAndDispatch ()) fDisplay.sleep ();
+
+ model.validateData(fViewer, TreePath.EMPTY);
+ }
}
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 f484fd8a3..201650697 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
@@ -27,11 +27,12 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdat
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
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.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.ModelDelta;
import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.Viewer;
/**
* Test model for the use in unit tests. This test model contains a set of
@@ -40,9 +41,10 @@ import org.eclipse.jface.viewers.TreePath;
*
* @since 3.6
*/
-public class TestModel implements IElementContentProvider, IElementLabelProvider, IModelProxyFactory /*, IElementCheckReceiver */ {
+public class TestModel implements IElementContentProvider, IElementLabelProvider, IModelProxyFactory2 /*, IElementCheckReceiver */ {
- public class TestElement extends PlatformObject {
+ public static class TestElement extends PlatformObject {
+ private final TestModel fModel;
private final String fID;
TestElement[] fChildren;
String fLabelAppendix = "";
@@ -50,20 +52,25 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
boolean fChecked;
boolean fGrayed;
- public TestElement(String text, TestElement[] children) {
- this (text, false, false, children);
+ public TestElement(TestModel model, String text, TestElement[] children) {
+ this (model, text, false, false, children);
}
- public TestElement(String text, boolean checked, boolean grayed, TestElement[] children) {
+ public TestElement(TestModel model, String text, boolean checked, boolean grayed, TestElement[] children) {
+ fModel = model;
fID = text;
fChildren = children;
fChecked = checked;
fGrayed = grayed;
}
+ public TestModel getModel() {
+ return fModel;
+ }
+
public Object getAdapter(Class adapter) {
- if (adapter.isInstance(TestModel.this)) {
- return TestModel.this;
+ if (adapter.isInstance(fModel)) {
+ return fModel;
}
return null;
}
@@ -114,9 +121,32 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
}
}
- private class ModelProxy extends AbstractModelProxy {}
+ private class ModelProxy extends AbstractModelProxy {
+ public void installed(Viewer viewer) {
+ super.installed(viewer);
+ ModelDelta rootDelta = TestModel.this.getBaseDelta(new ModelDelta(fInput, IModelDelta.NO_CHANGE));
+ installSubModelProxies(fRootPath, rootDelta);
+ fireModelChanged(rootDelta);
+ }
+
+ private void installSubModelProxies(TreePath path, ModelDelta delta) {
+ TestElement element = getElement(path);
+ if (element.fModel != TestModel.this) {
+ // Found an element from a different model. Install its proxy and return.
+ delta.setFlags(delta.getFlags() | IModelDelta.INSTALL);
+ } else {
+ TestElement[] children = element.getChildren();
+
+ for (int i = 0; i < children.length; i++) {
+ installSubModelProxies(path.createChildPath(children[i]), delta.addNode(children[i], IModelDelta.NO_CHANGE));
+ }
+ }
+ }
+ }
private TestElement fRoot;
+ private Object fInput = null;
+ private TreePath fRootPath = TreePath.EMPTY;
private ModelProxy fModelProxy;
/**
@@ -128,6 +158,14 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
return fRoot;
}
+ ModelDelta getBaseDelta(ModelDelta rootDelta) {
+ ModelDelta delta = rootDelta;
+ for (int i = 0; i < fRootPath.getSegmentCount(); i++) {
+ delta = delta.addNode(fRootPath.getSegment(i), IModelDelta.NO_CHANGE);
+ }
+ return delta;
+ }
+
public int getModelDepth() {
return getDepth(getRootElement(), 0);
}
@@ -193,8 +231,14 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
element.setChecked(checked, false);
}
- public IModelProxy createModelProxy(Object element, IPresentationContext context) {
+ public IModelProxy createTreeModelProxy(Object input, TreePath path, IPresentationContext context) {
fModelProxy = new ModelProxy();
+ fInput = input;
+ fRootPath = path;
+ return fModelProxy;
+ }
+
+ public IModelProxy getModelProxy() {
return fModelProxy;
}
@@ -258,14 +302,15 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
TestElement[] children = element.getChildren();
delta.setChildCount(children.length);
Object segment = path.getSegment(i);
- int j = 0;
- for (j = 0; j < element.getChildren().length; j++) {
- if (segment.equals(element.getChildren()[j])) {
- element = element.getChildren()[j];
+ int j;
+ for (j = 0; j < children.length; j++) {
+ if (segment.equals(children[j])) {
+ element = children[j];
delta = delta.addNode(element, j, IModelDelta.NO_CHANGE);
+ break;
}
}
- if (j == element.getChildren().length) {
+ if (j == children.length) {
throw new IllegalArgumentException("Invalid path");
}
}
@@ -273,32 +318,49 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
}
+ private TreePath getRelativePath(TreePath path) {
+ Object[] segments = new Object[path.getSegmentCount() - fRootPath.getSegmentCount()];
+ for (int i = fRootPath.getSegmentCount(), _i = 0; i < path.getSegmentCount(); i++, _i++) {
+ segments[_i] = path.getSegment(i);
+ }
+ return new TreePath(segments);
+ }
+
public ModelDelta appendElementLabel(TreePath path, String labelAppendix) {
- ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE);
- TestElement element = getElement(path);
- ModelDelta delta = getElementDelta(baseDelta, path);
+ Assert.assertTrue(path.startsWith(fRootPath, null));
+ ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
+ ModelDelta baseDelta = getBaseDelta(rootDelta);
+ TreePath relativePath = getRelativePath(path);
+ TestElement element = getElement(relativePath);
+ ModelDelta delta = getElementDelta(baseDelta, relativePath);
element.setLabelAppendix(labelAppendix);
delta.setFlags(delta.getFlags() | IModelDelta.STATE);
- return baseDelta;
+ return rootDelta;
}
public ModelDelta setElementChecked(TreePath path, boolean checked, boolean grayed) {
- ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE);
- TestElement element = getElement(path);
- ModelDelta delta = getElementDelta(baseDelta, path);
+ Assert.assertTrue(path.startsWith(fRootPath, null));
+ ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
+ ModelDelta baseDelta = getBaseDelta(rootDelta);
+ TreePath relativePath = getRelativePath(path);
+ TestElement element = getElement(relativePath);
+ ModelDelta delta = getElementDelta(baseDelta, relativePath);
element.setChecked(checked, grayed);
delta.setFlags(delta.getFlags() | IModelDelta.STATE);
- return baseDelta;
+ return rootDelta;
}
public ModelDelta setElementChildren(TreePath path, TestElement[] children) {
- ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE);
+ Assert.assertTrue(path.startsWith(fRootPath, null));
+ ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
+ ModelDelta baseDelta = getBaseDelta(rootDelta);
+ TreePath relativePath = getRelativePath(path);
// Find the parent element and generate the delta node for it.
- TestElement element = getElement(path);
- ModelDelta delta = getElementDelta(baseDelta, path);
+ TestElement element = getElement(relativePath);
+ ModelDelta delta = getElementDelta(baseDelta, relativePath);
// Set the new children array
element.fChildren = children;
@@ -307,28 +369,32 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
delta.setFlags(delta.getFlags() | IModelDelta.CONTENT);
delta.setChildCount(children.length);
- return baseDelta;
+ return rootDelta;
}
public ModelDelta replaceElementChild(TreePath parentPath, int index, TestElement child) {
- ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE);
+ ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
+ ModelDelta baseDelta = getBaseDelta(rootDelta);
+ TreePath relativePath = getRelativePath(parentPath);
- TestElement element = getElement(parentPath);
- ModelDelta delta= getElementDelta(baseDelta, parentPath);
+ TestElement element = getElement(relativePath);
+ ModelDelta delta= getElementDelta(baseDelta, relativePath);
TestElement oldChild = element.fChildren[index];
element.fChildren[index] = child;
delta.addNode(oldChild, child, IModelDelta.REPLACED);
// TODO: set replacement index!?!
- return baseDelta;
+ return rootDelta;
}
public ModelDelta addElementChild(TreePath parentPath, int index, TestElement newChild) {
- ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE);
+ ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
+ ModelDelta baseDelta = getBaseDelta(rootDelta);
+ TreePath relativePath = getRelativePath(parentPath);
// Find the parent element and generate the delta node for it.
- TestElement element = getElement(parentPath);
- ModelDelta delta= getElementDelta(baseDelta, parentPath);
+ TestElement element = getElement(relativePath);
+ ModelDelta delta= getElementDelta(baseDelta, relativePath);
// Add the new element
element.fChildren = doInsertElementInArray(element.fChildren, index, newChild);
@@ -337,15 +403,17 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
delta.setChildCount(element.getChildren().length);
delta.addNode(newChild, IModelDelta.ADDED);
- return baseDelta;
+ return rootDelta;
}
public ModelDelta insertElementChild(TreePath parentPath, int index, TestElement newChild) {
- ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE);
+ ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
+ ModelDelta baseDelta = getBaseDelta(rootDelta);
+ TreePath relativePath = getRelativePath(parentPath);
// Find the parent element and generate the delta node for it.
- TestElement element = getElement(parentPath);
- ModelDelta delta= getElementDelta(baseDelta, parentPath);
+ TestElement element = getElement(relativePath);
+ ModelDelta delta= getElementDelta(baseDelta, relativePath);
// Add the new element
element.fChildren = doInsertElementInArray(element.fChildren, index, newChild);
@@ -354,7 +422,7 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
delta.setChildCount(element.getChildren().length);
delta.addNode(newChild, index, IModelDelta.INSERTED);
- return baseDelta;
+ return rootDelta;
}
private TestElement[] doInsertElementInArray(TestElement[] children, int index, TestElement newChild) {
@@ -368,7 +436,8 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
}
public ModelDelta removeElementChild(TreePath parentPath, int index) {
- ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE);
+ ModelDelta rootDelta = new ModelDelta(fInput, IModelDelta.NO_CHANGE);
+ ModelDelta baseDelta = getBaseDelta(rootDelta);
// Find the parent element and generate the delta node for it.
TestElement element = getElement(parentPath);
@@ -386,7 +455,7 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
delta.setChildCount(element.getChildren().length);
delta.addNode(childToRemove, index, IModelDelta.REMOVED);
- return baseDelta;
+ return rootDelta;
}
public TreePath findElement(String label) {
@@ -410,46 +479,108 @@ public class TestModel implements IElementContentProvider, IElementLabelProvider
return null;
}
+ public String toString() {
+ return getElementString(fRoot, "");
+ }
+
+ public String getElementString(TestElement element, String indent) {
+ StringBuffer builder = new StringBuffer();
+ builder.append(indent);
+ builder.append(element.toString());
+ builder.append('\n');
+ TestElement[] children = element.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ builder.append(getElementString(children[i], indent + " "));
+ }
+ return builder.toString();
+ }
+
public static TestModel simpleSingleLevel() {
TestModel model = new TestModel();
- model.setRoot( model.new TestElement("root", new TestElement[] {
- model.new TestElement("1", true, true, new TestElement[0]),
- model.new TestElement("2", true, false, new TestElement[0]),
- model.new TestElement("3", false, true, new TestElement[0]),
- model.new TestElement("4", false, false, new TestElement[0]),
- model.new TestElement("5", new TestElement[0]),
- model.new TestElement("6", new TestElement[0])
+ model.setRoot( new TestElement(model, "root", new TestElement[] {
+ new TestElement(model, "1", true, true, new TestElement[0]),
+ new TestElement(model, "2", true, false, new TestElement[0]),
+ new TestElement(model, "3", false, true, new TestElement[0]),
+ new TestElement(model, "4", false, false, new TestElement[0]),
+ new TestElement(model, "5", new TestElement[0]),
+ new TestElement(model, "6", new TestElement[0])
}) );
return model;
}
public static TestModel simpleMultiLevel() {
TestModel model = new TestModel();
- model.setRoot( model.new TestElement("root", new TestElement[] {
- model.new TestElement("1", new TestElement[0]),
- model.new TestElement("2", true, false, new TestElement[] {
- model.new TestElement("2.1", true, true, new TestElement[0]),
- model.new TestElement("2.2", false, true, new TestElement[0]),
- model.new TestElement("2.3", true, false, new TestElement[0]),
+ model.setRoot( new TestElement(model, "root", new TestElement[] {
+ new TestElement(model, "1", new TestElement[0]),
+ new TestElement(model, "2", true, false, new TestElement[] {
+ new TestElement(model, "2.1", true, true, new TestElement[0]),
+ new TestElement(model, "2.2", false, true, new TestElement[0]),
+ new TestElement(model, "2.3", true, false, new TestElement[0]),
}),
- model.new TestElement("3", new TestElement[] {
- model.new TestElement("3.1", new TestElement[] {
- model.new TestElement("3.1.1", new TestElement[0]),
- model.new TestElement("3.1.2", new TestElement[0]),
- model.new TestElement("3.1.3", new TestElement[0]),
+ new TestElement(model, "3", new TestElement[] {
+ new TestElement(model, "3.1", new TestElement[] {
+ new TestElement(model, "3.1.1", new TestElement[0]),
+ new TestElement(model, "3.1.2", new TestElement[0]),
+ new TestElement(model, "3.1.3", new TestElement[0]),
}),
- model.new TestElement("3.2", new TestElement[] {
- model.new TestElement("3.2.1", new TestElement[0]),
- model.new TestElement("3.2.2", new TestElement[0]),
- model.new TestElement("3.2.3", new TestElement[0]),
+ new TestElement(model, "3.2", new TestElement[] {
+ new TestElement(model, "3.2.1", new TestElement[0]),
+ new TestElement(model, "3.2.2", new TestElement[0]),
+ new TestElement(model, "3.2.3", new TestElement[0]),
}),
- model.new TestElement("3.3", new TestElement[] {
- model.new TestElement("3.3.1", new TestElement[0]),
- model.new TestElement("3.3.2", new TestElement[0]),
- model.new TestElement("3.3.3", new TestElement[0]),
+ new TestElement(model, "3.3", new TestElement[] {
+ new TestElement(model, "3.3.1", new TestElement[0]),
+ new TestElement(model, "3.3.2", new TestElement[0]),
+ new TestElement(model, "3.3.3", new TestElement[0]),
}),
})
}) );
return model;
}
+
+ public static TestModel compositeMultiLevel() {
+ TestModel m2 = new TestModel();
+ m2.setRoot( new TestElement(m2, "m2.root", new TestElement[] {
+ new TestElement(m2, "m2.1", new TestElement[0]),
+ new TestElement(m2, "m2.2", true, false, new TestElement[] {
+ new TestElement(m2, "m2.2.1", true, true, new TestElement[0]),
+ new TestElement(m2, "m2.2.2", false, true, new TestElement[0]),
+ new TestElement(m2, "m2.2.3", true, false, new TestElement[0]),
+ }),
+ }) );
+
+ TestModel m3 = new TestModel();
+ m3.setRoot( new TestElement(m3, "m3.root", new TestElement[] {
+ new TestElement(m3, "m3.1", new TestElement[0]),
+ new TestElement(m3, "m3.2", true, false, new TestElement[] {
+ new TestElement(m3, "m3.2.1", true, true, new TestElement[0]),
+ new TestElement(m3, "m3.2.2", false, true, new TestElement[0]),
+ new TestElement(m3, "m3.2.3", true, false, new TestElement[0]),
+ }),
+ }) );
+
+ TestModel m4 = new TestModel();
+ m4.setRoot( new TestElement(m4, "m4.root", new TestElement[] {
+ new TestElement(m4, "m4.1", new TestElement[0]),
+ new TestElement(m4, "m4.2", true, false, new TestElement[] {
+ new TestElement(m4, "m4.2.1", true, true, new TestElement[0]),
+ new TestElement(m4, "m4.2.2", false, true, new TestElement[0]),
+ new TestElement(m4, "m4.2.3", true, false, new TestElement[0]),
+ }),
+ }) );
+
+ TestModel m1 = new TestModel();
+ m1.setRoot( new TestElement(m1, "m1.root", new TestElement[] {
+ new TestElement(m1, "m1.1", new TestElement[0]),
+ new TestElement(m1, "m1.2", true, false, new TestElement[] {
+ m2.fRoot,
+ m3.fRoot,
+ m4.fRoot,
+ }),
+ }) );
+
+
+ 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 d0995fe2a..e6e2ecf8d 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
@@ -12,6 +12,7 @@ package org.eclipe.debug.tests.viewer.model;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -39,13 +40,14 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
public static final int CHILDREN_COUNT_UPDATES = 0X0010;
public static final int CHILDREN_UPDATES = 0X0020;
public static final int MODEL_CHANGED_COMPLETE = 0X0040;
+ public static final int MODEL_PROXIES_INSTALLED = 0X0080;
public static final int LABEL_COMPLETE = LABEL_UPDATES_COMPLETE | LABEL_UPDATES;
public static final int CONTENT_COMPLETE =
CONTENT_UPDATES_COMPLETE | HAS_CHILDREN_UPDATES | CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES;
- public static final int ALL_UPDATES_COMPLETE = LABEL_COMPLETE | CONTENT_COMPLETE;
+ public static final int ALL_UPDATES_COMPLETE = LABEL_COMPLETE | CONTENT_COMPLETE | MODEL_PROXIES_INSTALLED;
private boolean fFailOnRedundantUpdates;
private boolean fFailOnMultipleUpdateSequences;
@@ -54,6 +56,7 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
private Map fChildrenUpdates = new HashMap();
private Set fChildCountUpdates = new HashSet();
private Set fLabelUpdates = new HashSet();
+ private Set fProxyModels = new HashSet();
private boolean fViewerUpdatesComplete;
private boolean fLabelUpdatesComplete;
private boolean fModelChangedComplete;
@@ -74,7 +77,8 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
public void reset(TreePath path, TestElement element, int levels, boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) {
reset();
- addUpdates(path, element, levels);
+ addUpdates(path, element, levels);
+ addProxies(element);
setFailOnRedundantUpdates(failOnRedundantUpdates);
setFailOnMultipleUpdateSequences(failOnMultipleUpdateSequences);
}
@@ -84,6 +88,7 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
fChildrenUpdates.clear();
fChildCountUpdates.clear();
fLabelUpdates.clear();
+ fProxyModels.clear();
fViewerUpdatesComplete = false;
fLabelUpdatesComplete = false;
fModelChangedComplete = false;
@@ -156,6 +161,17 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
}
}
}
+
+ private void addProxies(TestElement element) {
+ TestModel model = element.getModel();
+ if (model.getModelProxy() == null) {
+ fProxyModels.add(element.getModel());
+ }
+ TestElement[] children = element.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ addProxies(children[i]);
+ }
+ }
public boolean isFinished() {
return isFinished(ALL_UPDATES_COMPLETE);
@@ -183,6 +199,9 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
if ( (flags & MODEL_CHANGED_COMPLETE) != 0) {
if (!fModelChangedComplete) return false;
}
+ if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
+ if (fProxyModels.size() != 0) return false;
+ }
return true;
}
@@ -256,6 +275,14 @@ public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUp
Assert.fail("Multiple model changed sequences detected");
}
fModelChangedComplete = true;
+
+ for (Iterator itr = fProxyModels.iterator(); itr.hasNext();) {
+ TestModel model = (TestModel)itr.next();
+ if (model.getModelProxy() == proxy) {
+ itr.remove();
+ break;
+ }
+ }
}
}
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java
index 5bc65f6bb..eff52f495 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java
@@ -94,9 +94,9 @@ abstract public class UpdateTests extends TestCase {
TestElement root = model.getRootElement();
TreePath rootPath = new TreePath(new Object[] {});
TestElement[] newElements = new TestElement[] {
- model.new TestElement("1", new TestElement[0]),
- model.new TestElement("2", new TestElement[0]),
- model.new TestElement("3", new TestElement[0]),
+ new TestElement(model, "1", new TestElement[0]),
+ new TestElement(model, "2", new TestElement[0]),
+ new TestElement(model, "3", new TestElement[0]),
};
model.setElementChildren(rootPath, newElements);
@@ -133,9 +133,9 @@ abstract public class UpdateTests extends TestCase {
TestElement element = model.getRootElement().getChildren()[0];
TreePath elementPath = new TreePath(new Object[] { element });
TestElement[] newChildren = new TestElement[] {
- model.new TestElement("1.1", new TestElement[0]),
- model.new TestElement("1.2", new TestElement[0]),
- model.new TestElement("1.3", new TestElement[0]),
+ new TestElement(model, "1.1", new TestElement[0]),
+ new TestElement(model, "1.2", new TestElement[0]),
+ new TestElement(model, "1.3", new TestElement[0]),
};
model.setElementChildren(elementPath, newChildren);
@@ -166,7 +166,7 @@ abstract public class UpdateTests extends TestCase {
}
private void addElement(TestModel model, String label, int position) {
- ModelDelta delta = model.addElementChild(TreePath.EMPTY, position, model.new TestElement(label, new TestElement[0]));
+ ModelDelta delta = model.addElementChild(TreePath.EMPTY, position, new TestElement(model, label, new TestElement[0]));
// Remove delta should generate no new updates, but we still need to wait for the event to
// be processed.
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 c61ddad00..ff8e90bbd 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
@@ -45,6 +45,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor;
import org.eclipse.debug.internal.ui.viewers.model.provisional.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.IViewerUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
@@ -73,7 +74,20 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
*/
private boolean fSuppressModelControlRequests = false;
- private Map fModelProxies = new LinkedHashMap(); // model proxy by element
+ /**
+ * 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.
@@ -273,7 +287,7 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
cancelSubtreeUpdates(TreePath.EMPTY);
fTransform.clear();
if (newInput != null) {
- installModelProxy(newInput);
+ installModelProxy(newInput, TreePath.EMPTY);
restoreViewerState(newInput);
}
}
@@ -757,8 +771,12 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
*
* @param element
*/
- protected synchronized void disposeModelProxy(Object element) {
- IModelProxy proxy = (IModelProxy) fModelProxies.remove(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();
}
@@ -774,19 +792,36 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
proxy.dispose();
}
fModelProxies.clear();
+
+ updatePolicies = fTreeModelProxies.values().iterator();
+ while (updatePolicies.hasNext()) {
+ IModelProxy proxy = (IModelProxy) updatePolicies.next();
+ proxy.dispose();
+ }
+ fTreeModelProxies.clear();
}
protected synchronized IModelProxy[] getModelProxies() {
- return (IModelProxy[])fModelProxies.values().toArray(new IModelProxy[fModelProxies.size()]);
+ 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) {
- for (int i = path.getSegmentCount() - 1; i >= 0; i--) {
- IModelProxy proxy = (IModelProxy)fModelProxies.get(path.getSegment(i));
+ 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;
}
@@ -797,14 +832,30 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
* @param element
* element to install an update policy for
*/
- protected synchronized void installModelProxy(Object element) {
- if (!fModelProxies.containsKey(element)) {
- IModelProxyFactory modelProxyFactory = ViewerAdapterService.getModelProxyFactory(element);
- if (modelProxyFactory != null) {
- final IModelProxy proxy = modelProxyFactory.createModelProxy(
- element, getPresentationContext());
+ 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) {
+ fTreeModelProxies.put(path, proxy);
+ }
+ }
+ if (proxy == null) {
+ IModelProxyFactory modelProxyFactory = ViewerAdapterService.getModelProxyFactory(element);
+ if (modelProxyFactory != null) {
+ proxy = modelProxyFactory.createModelProxy(element, getPresentationContext());
+ if (proxy != null) {
+ fModelProxies.put(element, proxy);
+ }
+ }
+ }
+
+ if (proxy != null) {
+ final IModelProxy finalProxy = proxy;
if (proxy != null) {
- fModelProxies.put(element, proxy);
Job job = new Job("Model Proxy installed notification job") {//$NON-NLS-1$
protected IStatus run(IProgressMonitor monitor) {
if (!monitor.isCanceled()) {
@@ -816,10 +867,10 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
viewer = (Viewer)getViewer();
}
}
- if (context != null && !proxy.isDisposed()) {
- proxy.init(context);
- proxy.addModelChangedListener(ModelContentProvider.this);
- proxy.installed(viewer);
+ if (context != null && !finalProxy.isDisposed()) {
+ finalProxy.init(context);
+ finalProxy.addModelChangedListener(ModelContentProvider.this);
+ finalProxy.installed(viewer);
}
}
return Status.OK_STATUS;
@@ -975,14 +1026,30 @@ abstract class ModelContentProvider implements IContentProvider, IModelChangedLi
protected abstract void handleReveal(IModelDelta delta);
protected void handleInstall(IModelDelta delta) {
- installModelProxy(delta.getElement());
+ installModelProxy(getViewer().getInput(), getFullTreePath(delta));
}
protected void handleUninstall(IModelDelta delta) {
- disposeModelProxy(delta.getElement());
+ 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
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 0c550e8ba..07041e627 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
@@ -107,6 +107,7 @@ public class TreeModelContentProvider extends ModelContentProvider implements IT
System.out.println("handleAdd(" + delta.getElement() + ") viewIndex: " + viewCount + " modelIndex: " + modelIndex); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
getViewer().setChildCount(parentPath, viewCount);
+ getViewer().autoExpand(parentPath);
int viewIndex = modelToViewIndex(parentPath, modelIndex);
getViewer().replace(parentPath, viewIndex, element);
TreePath childPath = parentPath.createChildPath(element);
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ViewerAdapterService.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ViewerAdapterService.java
index 7f4a82268..539e806c4 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ViewerAdapterService.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/ViewerAdapterService.java
@@ -18,6 +18,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
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.IModelProxyFactory;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory2;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicyFactory;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
@@ -72,7 +73,7 @@ public class ViewerAdapterService {
}
/**
- * Returns the model proxy factory for the given element or
+ * Returns the model proxy factory for the given element or
* <code>null</code> if none.
*
* @param element element to retrieve adapter for
@@ -81,7 +82,18 @@ public class ViewerAdapterService {
public static IModelProxyFactory getModelProxyFactory(Object element) {
return (IModelProxyFactory)getAdapter(element, IModelProxyFactory.class);
}
-
+
+ /**
+ * Returns the model proxy factory v.2 for the given element or
+ * <code>null</code> if none.
+ *
+ * @param element element to retrieve adapter for
+ * @return model proxy factory or <code>null</code>
+ */
+ public static IModelProxyFactory2 getModelProxyFactory2(Object element) {
+ return (IModelProxyFactory2)getAdapter(element, IModelProxyFactory2.class);
+ }
+
/**
* Returns the memento provider for the given element or
* <code>null</code> if none.
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelProxyFactory2.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelProxyFactory2.java
new file mode 100644
index 000000000..2bbd8114e
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/viewers/model/provisional/IModelProxyFactory2.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Freescale Semiconductor 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:
+ * Freescale Semiconductor - initial API and implementation � Bug 241336
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.viewers.model.provisional;
+
+import org.eclipse.jface.viewers.TreePath;
+
+/**
+ * A model proxy factory creates model proxies for elements based on
+ * specific presentation contexts. A model proxy factory is provided for
+ * a model element by registering a model proxy factory adapter for
+ * an element.
+ * <p>
+ * This interface is an alternative to the {@link IModelProxyFactory}
+ * interface. Unlike its predecessor <code>IModelProxyFactory2</code> allows
+ * the full path to the tree element to be specified when creating an
+ * <code>IModelProxy<code> instance. Using the full patch allows models to
+ * provide proper model deltas even if the root element of this proxy is at
+ * variable or unknown location in the viewer.
+ * </p>
+ * <p>
+ * Clients may implement this interface.
+ * </p>
+ * @see IModelProxyFactory
+ * @see IModelProxy
+ * @see IModelDelta
+ *
+ * @since 3.6
+ */
+public interface IModelProxyFactory2 {
+ /**
+ * Creates and returns a model proxy for the given element in the specified
+ * context or <code>null</code> if none.
+ *
+ * @param input viewer input context
+ * @param path to model element to create a model proxy for
+ * @param context presentation context
+ * @return model proxy or <code>null</code>
+ */
+ public IModelProxy createTreeModelProxy(Object input, TreePath path, IPresentationContext context);
+}

Back to the top