Author: rwhitcomb
Date: Wed Jan 24 18:46:49 2018
New Revision: 1822149

URL: http://svn.apache.org/viewvc?rev=1822149&view=rev
Log:
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.

Modified:
    pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/text/Element.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/text/TextNode.java

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java
URL: 
http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java?rev=1822149&r1=1822148&r2=1822149&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java Wed Jan 24 18:46:49 
2018
@@ -44,6 +44,7 @@ import org.apache.pivot.wtk.text.NodeLis
 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,75 +117,42 @@ public class TextPane extends Container
         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 class TextInsertedEdit 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) {
+        public TextInsertedEdit(Node node, int offset, int characterCount) {
             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());
+            node.removeRange(offset, characterCount);
+            setSelection(offset, 0);
         }
     }
 
-    private class RangeInsertedEdit implements Edit {
+    private class TextRemovedEdit implements Edit {
         private final Node node;
         private final int offset;
-        private final int characterCount;
+        private final CharSequence removedChars;
 
-        public RangeInsertedEdit(Node node, int offset, int characterCount) {
+        public TextRemovedEdit(Node node, int offset, CharSequence 
removedChars) {
             this.node = node;
             this.offset = offset;
-            this.characterCount = characterCount;
+            this.removedChars = removedChars;
         }
 
         @Override
         public void undo() {
-            node.removeRange(offset, characterCount);
-            int newSelectionStart = selectionStart;
-            int newSelectionLength = selectionLength;
-            if (newSelectionStart >= document.getCharacterCount()) {
-                newSelectionStart = document.getCharacterCount() - 1;
-            }
-            if (newSelectionStart + newSelectionLength > 
document.getCharacterCount()) {
-                newSelectionLength = document.getCharacterCount() - 
newSelectionStart;
+            if (offset != selectionStart) {
+                setSelection(offset, 0);
             }
-            setSelection(newSelectionStart, newSelectionLength);
+            insert(removedChars.toString());
+            setSelection(offset + removedChars.length(), 0);
         }
     }
 
@@ -224,7 +192,7 @@ public class TextPane extends Container
             }
 
             if (!undoingHistory) {
-                editHistory.push(new RangeInsertedEdit(node, offset, 
characterCount));
+                editHistory.push(new TextInsertedEdit(node, offset, 
characterCount));
             }
 
             if (!bulkOperation) {
@@ -245,10 +213,6 @@ public class TextPane extends Container
                     TextPane.super.remove(componentNode.getComponent());
                 }
             }
-
-            if (!undoingHistory) {
-                editHistory.push(new NodesRemovedEdit(node, removed, offset));
-            }
         }
 
         /**
@@ -286,7 +250,7 @@ public class TextPane extends Container
             }
 
             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 @@ public class TextPane extends Container
         }
     }
 
+    /**
+     * 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) {

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/text/Element.java
URL: 
http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/text/Element.java?rev=1822149&r1=1822148&r2=1822149&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/text/Element.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/text/Element.java Wed Jan 24 
18:46:49 2018
@@ -370,6 +370,7 @@ public abstract class Element extends No
         // 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 @@ public abstract class Element extends No
                 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 @@ public abstract class Element extends No
             }
 
             // Notify parent
-            super.rangeRemoved(this, offset, removedCharacterCount, null);
+            super.rangeRemoved(this, offset, removedCharacterCount, 
removedChars);
             super.nodesRemoved(this, removed, offset);
 
             // Fire event

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/text/TextNode.java
URL: 
http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/text/TextNode.java?rev=1822149&r1=1822148&r2=1822149&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/text/TextNode.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/text/TextNode.java Wed Jan 24 
18:46:49 2018
@@ -129,7 +129,8 @@ public final class TextNode extends Node
     @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;


Reply via email to