do not reference IElement in ChangeAttributeEdit

When an element is deleted, it gets dissociated from the document. While
it can still be referenced by an ChangeAttributeEdit, it is useless for
undo/redo, because its ContentRange gets lost when it is dissociated.
Hence instead of referencing the element, the document and the current
caret offset where the edit took place are stored in
ChangeAttributeEdit.

Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
index 62057ab..2d4a9db 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
@@ -573,8 +573,26 @@
 		widget.moveTo(para.getEndOffset(), true);

 		widget.deleteSelection();

 

-		widget.undo();

-		widget.undo();

+		widget.undo(); // delete

+		widget.undo(); // declare namespace

+

+		assertEquals(expectedXml, getCurrentXML(widget));

+	}

+

+	@Test

+	public void undoRedoChangeAttributeWithSubsequentDelete() throws Exception {

+		widget.insertElement(TITLE);

+		widget.moveBy(1);

+		final IElement para = widget.insertElement(PARA);

+		final String expectedXml = getCurrentXML(widget);

+

+		widget.setAttribute("id", "newParaElement");

+		widget.moveTo(para.getStartOffset());

+		widget.moveTo(para.getEndOffset(), true);

+		widget.deleteSelection();

+

+		widget.undo(); // delete

+		widget.undo(); // set attribute

 

 		assertEquals(expectedXml, getCurrentXML(widget));

 	}

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeAttributeEdit.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeAttributeEdit.java
index 058cb7c..9d383c1 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeAttributeEdit.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/undo/ChangeAttributeEdit.java
@@ -13,18 +13,21 @@
 

 import org.eclipse.core.runtime.QualifiedName;

 import org.eclipse.vex.core.provisional.dom.DocumentValidationException;

+import org.eclipse.vex.core.provisional.dom.IDocument;

 import org.eclipse.vex.core.provisional.dom.IElement;

 

 public class ChangeAttributeEdit extends AbstractUndoableEdit {

 

-	private final IElement element;

+	private final IDocument document;

+	private final int offset;

 	private final QualifiedName attributeName;

 	private final String oldValue;

 	private final String newValue;

 

-	public ChangeAttributeEdit(final IElement element, final QualifiedName attributeName, final String oldValue, final String newValue) {

+	public ChangeAttributeEdit(final IDocument document, final int offset, final QualifiedName attributeName, final String oldValue, final String newValue) {

 		super();

-		this.element = element;

+		this.document = document;

+		this.offset = offset;

 		this.attributeName = attributeName;

 		this.oldValue = oldValue;

 		this.newValue = newValue;

@@ -33,18 +36,20 @@
 	@Override

 	protected void performUndo() throws CannotUndoException {

 		try {

+			final IElement element = document.getElementForInsertionAt(offset);

 			element.setAttribute(attributeName, oldValue);

-		} catch (final DocumentValidationException ex) {

-			throw new CannotUndoException();

+		} catch (final DocumentValidationException e) {

+			throw new CannotUndoException(e);

 		}

 	}

 

 	@Override

 	protected void performRedo() throws CannotRedoException {

 		try {

+			final IElement element = document.getElementForInsertionAt(offset);

 			element.setAttribute(attributeName, newValue);

-		} catch (final DocumentValidationException ex) {

-			throw new CannotRedoException();

+		} catch (final DocumentValidationException e) {

+			throw new CannotRedoException(e);

 		}

 	}

 }

diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/BaseVexWidget.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/BaseVexWidget.java
index dc3c26d..9dc13db 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/BaseVexWidget.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/BaseVexWidget.java
@@ -1358,7 +1358,7 @@
 		if (value == null) {
 			removeAttribute(attributeName);
 		} else if (!value.equals(currentAttributeValue)) {
-			applyEdit(new ChangeAttributeEdit(element, qualifiedAttributeName, currentAttributeValue, value), getCaretOffset());
+			applyEdit(new ChangeAttributeEdit(document, getCaretOffset(), qualifiedAttributeName, currentAttributeValue, value), getCaretOffset());
 		}
 	}
 
@@ -1389,7 +1389,7 @@
 		final QualifiedName qualifiedAttributeName = element.qualify(attributeName);
 		final String currentAttributeValue = element.getAttributeValue(qualifiedAttributeName);
 		if (currentAttributeValue != null) {
-			applyEdit(new ChangeAttributeEdit(element, qualifiedAttributeName, currentAttributeValue, null), getCaretOffset());
+			applyEdit(new ChangeAttributeEdit(document, getCaretOffset(), qualifiedAttributeName, currentAttributeValue, null), getCaretOffset());
 		}
 	}