PIVOT-1021: Complete rearrangement of how undo in TextPane works:
* Save the removed characters all the time for undo purposes.
* Use the TextPane.insert() method to undo a delete.
* Reset the selection position after "undo".
* Change what is saved during undo to basically be the characters
and not the nodes themselves -- too much hassle to make that work.
* Also add an accessor method to set the flag saying whether or not
to save undo history. This is necessary so that node rearrangement
that doesn't change the text won't have to get saved for undo.
git-svn-id: https://svn.apache.org/repos/asf/pivot/trunk@1822149 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/wtk/src/org/apache/pivot/wtk/TextPane.java b/wtk/src/org/apache/pivot/wtk/TextPane.java
index 9d4f9eb..2593b3f 100644
--- a/wtk/src/org/apache/pivot/wtk/TextPane.java
+++ b/wtk/src/org/apache/pivot/wtk/TextPane.java
@@ -44,6 +44,7 @@
import org.apache.pivot.wtk.text.Paragraph;
import org.apache.pivot.wtk.text.PlainTextSerializer;
import org.apache.pivot.wtk.text.TextNode;
+import org.apache.pivot.wtk.text.TextSpan;
/**
* Component that allows a user to enter and edit multiple lines of (optionally
@@ -116,58 +117,12 @@
public void undo();
}
- private static class NodesRemovedEdit implements Edit {
- private final Node node;
- private final int offset;
- private final Sequence<Node> removed;
-
- public NodesRemovedEdit(Node node, Sequence<Node> removed, int offset) {
- this.node = node;
- this.offset = offset;
- this.removed = removed;
- }
-
- @Override
- public void undo() {
- int currentOffset = this.offset;
- for (int i = 0; i < removed.getLength(); i++) {
- Node removedNode = removed.get(i);
- node.insertRange(removedNode, currentOffset);
- currentOffset += removedNode.getCharacterCount();
- }
- }
- }
-
- private class RangeRemovedEdit implements Edit {
- private final Node node;
- private final int offset;
- private final int characterCount;
- private final CharSequence removedChars;
-
- public RangeRemovedEdit(Node node, int offset, int characterCount, CharSequence removedChars) {
- this.node = node;
- this.offset = offset;
- this.characterCount = characterCount;
- this.removedChars = removedChars;
- }
-
- @Override
- public void undo() {
- if (!(node instanceof TextNode)) {
- // TODO: can we / should we handle this?
- throw new IllegalArgumentException("Undo of removed characters must be to a TextNode.");
- }
- TextNode textNode = (TextNode)node;
- textNode.insertText(removedChars, offset - textNode.getDocumentOffset());
- }
- }
-
- private class RangeInsertedEdit implements Edit {
+ private class TextInsertedEdit implements Edit {
private final Node node;
private final int offset;
private final int characterCount;
- public RangeInsertedEdit(Node node, int offset, int characterCount) {
+ public TextInsertedEdit(Node node, int offset, int characterCount) {
this.node = node;
this.offset = offset;
this.characterCount = characterCount;
@@ -176,15 +131,28 @@
@Override
public void undo() {
node.removeRange(offset, characterCount);
- int newSelectionStart = selectionStart;
- int newSelectionLength = selectionLength;
- if (newSelectionStart >= document.getCharacterCount()) {
- newSelectionStart = document.getCharacterCount() - 1;
+ setSelection(offset, 0);
+ }
+ }
+
+ private class TextRemovedEdit implements Edit {
+ private final Node node;
+ private final int offset;
+ private final CharSequence removedChars;
+
+ public TextRemovedEdit(Node node, int offset, CharSequence removedChars) {
+ this.node = node;
+ this.offset = offset;
+ this.removedChars = removedChars;
+ }
+
+ @Override
+ public void undo() {
+ if (offset != selectionStart) {
+ setSelection(offset, 0);
}
- if (newSelectionStart + newSelectionLength > document.getCharacterCount()) {
- newSelectionLength = document.getCharacterCount() - newSelectionStart;
- }
- setSelection(newSelectionStart, newSelectionLength);
+ insert(removedChars.toString());
+ setSelection(offset + removedChars.length(), 0);
}
}
@@ -224,7 +192,7 @@
}
if (!undoingHistory) {
- editHistory.push(new RangeInsertedEdit(node, offset, characterCount));
+ editHistory.push(new TextInsertedEdit(node, offset, characterCount));
}
if (!bulkOperation) {
@@ -245,10 +213,6 @@
TextPane.super.remove(componentNode.getComponent());
}
}
-
- if (!undoingHistory) {
- editHistory.push(new NodesRemovedEdit(node, removed, offset));
- }
}
/**
@@ -286,7 +250,7 @@
}
if (!undoingHistory && removedChars != null) {
- editHistory.push(new RangeRemovedEdit(node, offset, characterCount, removedChars));
+ editHistory.push(new TextRemovedEdit(node, offset, removedChars));
}
if (!bulkOperation) {
@@ -388,6 +352,16 @@
}
}
+ /**
+ * Some document rearrangements might not be suitable for undoing,
+ * so allow users to specify when to do so.
+ *
+ * @param save Whether or not to save history at this time.
+ */
+ public void setSaveHistory(boolean save) {
+ this.undoingHistory = !save;
+ }
+
private Node getRightmostDescendant(Element element) {
int n = element.getLength();
if (n > 0) {
diff --git a/wtk/src/org/apache/pivot/wtk/text/Element.java b/wtk/src/org/apache/pivot/wtk/text/Element.java
index 9aef3c5..ecbaca7 100644
--- a/wtk/src/org/apache/pivot/wtk/text/Element.java
+++ b/wtk/src/org/apache/pivot/wtk/text/Element.java
@@ -370,6 +370,7 @@
// Remove the nodes
Sequence<Node> removed = nodes.remove(index, count);
count = removed.getLength();
+ StringBuilder removedChars = new StringBuilder();
if (count > 0) {
int removedCharacterCount = 0;
@@ -377,6 +378,11 @@
Node node = removed.get(i);
node.setParent(null);
removedCharacterCount += node.getCharacterCount();
+ if (node instanceof Element) {
+ removedChars.append(((Element)node).getText());
+ } else if (node instanceof TextNode) {
+ removedChars.append(((TextNode)node).getText());
+ }
}
// Update the character count
@@ -399,7 +405,7 @@
}
// Notify parent
- super.rangeRemoved(this, offset, removedCharacterCount, null);
+ super.rangeRemoved(this, offset, removedCharacterCount, removedChars);
super.nodesRemoved(this, removed, offset);
// Fire event
diff --git a/wtk/src/org/apache/pivot/wtk/text/TextNode.java b/wtk/src/org/apache/pivot/wtk/text/TextNode.java
index 60281a6..58e885d 100644
--- a/wtk/src/org/apache/pivot/wtk/text/TextNode.java
+++ b/wtk/src/org/apache/pivot/wtk/text/TextNode.java
@@ -129,7 +129,8 @@
@Override
public void insertRange(Node range, int offset) {
if (!(range instanceof TextNode)) {
- throw new IllegalArgumentException("range is not a text node.");
+ throw new IllegalArgumentException("Range node (" +
+ range.getClass().getSimpleName() + ") is not a text node.");
}
TextNode textNode = (TextNode) range;