Title: [143005] trunk
Revision
143005
Author
[email protected]
Date
2013-02-15 08:53:55 -0800 (Fri, 15 Feb 2013)

Log Message

Web Inspector: Several consecutive Backspace or Delete strikes should not be marked as undoable state.
https://bugs.webkit.org/show_bug.cgi?id=109915

Reviewed by Pavel Feldman.

Source/WebCore:

Extracted _isEditRangeUndoBoundary() and _isEditRangeAdjacentToLastCommand() in TextEditorModel
to detect if markUndoableState() call is needed before and after editRange.

* inspector/front-end/TextEditorModel.js:
(WebInspector.TextRange.prototype.immediatelyPrecedes):
(WebInspector.TextRange.prototype.immediatelyFollows):
(WebInspector.TextEditorModel.endsWithBracketRegex.):

LayoutTests:

* inspector/editor/text-editor-undo-redo-expected.txt:
* inspector/editor/text-editor-undo-redo.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (143004 => 143005)


--- trunk/LayoutTests/ChangeLog	2013-02-15 16:49:14 UTC (rev 143004)
+++ trunk/LayoutTests/ChangeLog	2013-02-15 16:53:55 UTC (rev 143005)
@@ -1,3 +1,13 @@
+2013-02-15  Vsevolod Vlasov  <[email protected]>
+
+        Web Inspector: Several consecutive Backspace or Delete strikes should not be marked as undoable state.
+        https://bugs.webkit.org/show_bug.cgi?id=109915
+
+        Reviewed by Pavel Feldman.
+
+        * inspector/editor/text-editor-undo-redo-expected.txt:
+        * inspector/editor/text-editor-undo-redo.html:
+
 2013-02-15  Sudarsana Nagineni  <[email protected]>
 
         Unreviewed EFL gardening.

Modified: trunk/LayoutTests/inspector/editor/text-editor-undo-redo-expected.txt (143004 => 143005)


--- trunk/LayoutTests/inspector/editor/text-editor-undo-redo-expected.txt	2013-02-15 16:49:14 UTC (rev 143004)
+++ trunk/LayoutTests/inspector/editor/text-editor-undo-redo-expected.txt	2013-02-15 16:53:55 UTC (rev 143005)
@@ -134,6 +134,266 @@
 }
 
 
+Running: testDelete
+Text before edit:
+function foo()
+{
+
+}
+
+Text after edit:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after deletes:
+function foo()
+{
+|
+}
+
+Text after first undo:
+function foo()
+{
+|    bar();
+    baz();
+    foo();
+}
+
+Text after second undo:
+function foo()
+{
+    bar();
+    baz();|
+}
+
+Text after first redo:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after second redo:
+function foo()
+{
+|
+}
+
+
+Running: testBackspace
+Text before edit:
+function foo()
+{
+
+}
+
+Text after edit:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after backspaces:
+function foo()
+{
+|
+}
+
+Text after first undo:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after second undo:
+function foo()
+{
+    bar();
+    baz();|
+}
+
+Text after first redo:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after second redo:
+function foo()
+{
+|
+}
+
+
+Running: testBackspaceAndDeleteInDifferentLines
+Text before edit:
+function foo()
+{
+
+}
+
+Text after edit:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after backspace:
+function foo()
+{
+    bar();
+    baz();
+    foo()|
+}
+
+Text after delete:
+function foo()
+{
+|   bar();
+    baz();
+    foo()
+}
+
+Text after first undo:
+function foo()
+{
+|    bar();
+    baz();
+    foo()
+}
+
+Text after second undo:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after third undo:
+function foo()
+{
+    bar();
+    baz();|
+}
+
+Text after first redo:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after second redo:
+function foo()
+{
+    bar();
+    baz();
+    foo()|
+}
+
+Text after third redo:
+function foo()
+{
+|   bar();
+    baz();
+    foo()
+}
+
+
+Running: testPasteSeveralTimes
+Text before edit:
+function foo()
+{
+
+}
+
+Text after edit:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after first paste:
+function foo()
+{
+    bar();
+    baz();
+    foo();42|
+}
+
+Text after second paste:
+function foo()
+{
+    bar();
+    baz();
+    foo();4242|
+}
+
+Text after first undo:
+function foo()
+{
+    bar();
+    baz();
+    foo();42|
+}
+
+Text after second undo:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after third undo:
+function foo()
+{
+    bar();
+    baz();|
+}
+
+Text after first redo:
+function foo()
+{
+    bar();
+    baz();
+    foo();|
+}
+
+Text after second redo:
+function foo()
+{
+    bar();
+    baz();
+    foo();42|
+}
+
+Text after third redo:
+function foo()
+{
+    bar();
+    baz();
+    foo();4242|
+}
+
+
 Running: testSelectionAfterUndoRedo
 Text before edit:
 function foo()

Modified: trunk/LayoutTests/inspector/editor/text-editor-undo-redo.html (143004 => 143005)


--- trunk/LayoutTests/inspector/editor/text-editor-undo-redo.html	2013-02-15 16:49:14 UTC (rev 143004)
+++ trunk/LayoutTests/inspector/editor/text-editor-undo-redo.html	2013-02-15 16:53:55 UTC (rev 143005)
@@ -19,6 +19,17 @@
         return range;
     }
 
+    function typeDelete(textModel, startRange, count)
+    {
+        var count = count || 1;
+        var range = startRange;
+        for (var i = 0; i < count; ++i) {
+            var deleteRange = range.isEmpty() ? textModel.growRangeRight(range) : range;
+            range = textModel.editRange(deleteRange, "", range).collapseToEnd();
+        }
+        return range;
+    }
+
     function typeBackspace(textModel, startRange, count)
     {
         var count = count || 1;
@@ -88,6 +99,102 @@
             next();
         },
 
+        function testDelete(next)
+        {
+            var textModel = new WebInspector.TextEditorModel();
+            var functionText = "    bar();\n    baz();\n    foo();";
+            textModel.setText("function foo()\n{\n\n}\n");
+            dumpTextModel("Text before edit:\n", textModel);
+            var range = typeText(textModel, new WebInspector.TextRange(2, 0, 2, 0), "    bar();\n    baz();\n    foo();");
+            dumpTextModel("Text after edit:\n", textModel, range);
+            range = typeDelete(textModel, new WebInspector.TextRange(2, 0, 2, 0), functionText.length);
+            dumpTextModel("Text after deletes:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after first undo:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after second undo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after first redo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after second redo:\n", textModel, range);
+            next();
+        },
+
+        function testBackspace(next)
+        {
+            var textModel = new WebInspector.TextEditorModel();
+            var functionText = "    bar();\n    baz();\n    foo();";
+            textModel.setText("function foo()\n{\n\n}\n");
+            dumpTextModel("Text before edit:\n", textModel);
+            var range = typeText(textModel, new WebInspector.TextRange(2, 0, 2, 0), "    bar();\n    baz();\n    foo();");
+            dumpTextModel("Text after edit:\n", textModel, range);
+            range = typeBackspace(textModel, range, functionText.length);
+            dumpTextModel("Text after backspaces:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after first undo:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after second undo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after first redo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after second redo:\n", textModel, range);
+            next();
+        },
+
+        function testBackspaceAndDeleteInDifferentLines(next)
+        {
+            var textModel = new WebInspector.TextEditorModel();
+            var functionText = "    bar();\n    baz();\n    foo();";
+            textModel.setText("function foo()\n{\n\n}\n");
+            dumpTextModel("Text before edit:\n", textModel);
+            var range = typeText(textModel, new WebInspector.TextRange(2, 0, 2, 0), "    bar();\n    baz();\n    foo();");
+            dumpTextModel("Text after edit:\n", textModel, range);
+            range = typeBackspace(textModel, range);
+            dumpTextModel("Text after backspace:\n", textModel, range);
+            range = typeDelete(textModel, new WebInspector.TextRange(2, 0, 2, 0));
+            dumpTextModel("Text after delete:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after first undo:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after second undo:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after third undo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after first redo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after second redo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after third redo:\n", textModel, range);
+            next();
+        },
+
+        function testPasteSeveralTimes(next)
+        {
+            var textModel = new WebInspector.TextEditorModel();
+            var functionText = "    bar();\n    baz();\n    foo();";
+            textModel.setText("function foo()\n{\n\n}\n");
+            dumpTextModel("Text before edit:\n", textModel);
+            var range = typeText(textModel, new WebInspector.TextRange(2, 0, 2, 0), "    bar();\n    baz();\n    foo();");
+            dumpTextModel("Text after edit:\n", textModel, range);
+            range = textModel.editRange(range, "42").collapseToEnd();
+            dumpTextModel("Text after first paste:\n", textModel, range);
+            range = textModel.editRange(range, "42").collapseToEnd();
+            dumpTextModel("Text after second paste:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after first undo:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after second undo:\n", textModel, range);
+            range = textModel.undo();
+            dumpTextModel("Text after third undo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after first redo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after second redo:\n", textModel, range);
+            range = textModel.redo();
+            dumpTextModel("Text after third redo:\n", textModel, range);
+            next();
+        },
+
         function testSelectionAfterUndoRedo(next)
         {
             var textModel = new WebInspector.TextEditorModel();

Modified: trunk/Source/WebCore/ChangeLog (143004 => 143005)


--- trunk/Source/WebCore/ChangeLog	2013-02-15 16:49:14 UTC (rev 143004)
+++ trunk/Source/WebCore/ChangeLog	2013-02-15 16:53:55 UTC (rev 143005)
@@ -1,3 +1,18 @@
+2013-02-15  Vsevolod Vlasov  <[email protected]>
+
+        Web Inspector: Several consecutive Backspace or Delete strikes should not be marked as undoable state.
+        https://bugs.webkit.org/show_bug.cgi?id=109915
+
+        Reviewed by Pavel Feldman.
+
+        Extracted _isEditRangeUndoBoundary() and _isEditRangeAdjacentToLastCommand() in TextEditorModel
+        to detect if markUndoableState() call is needed before and after editRange.
+
+        * inspector/front-end/TextEditorModel.js:
+        (WebInspector.TextRange.prototype.immediatelyPrecedes):
+        (WebInspector.TextRange.prototype.immediatelyFollows):
+        (WebInspector.TextEditorModel.endsWithBracketRegex.):
+
 2013-02-15  Andrey Adaikin  <[email protected]>
 
         Fix inconsistency in WebGLRenderingContext.idl for getAttribLocation

Modified: trunk/Source/WebCore/inspector/front-end/TextEditorModel.js (143004 => 143005)


--- trunk/Source/WebCore/inspector/front-end/TextEditorModel.js	2013-02-15 16:49:14 UTC (rev 143004)
+++ trunk/Source/WebCore/inspector/front-end/TextEditorModel.js	2013-02-15 16:53:55 UTC (rev 143005)
@@ -67,6 +67,28 @@
     },
 
     /**
+     * @param {WebInspector.TextRange} range
+     * @return {boolean}
+     */
+    immediatelyPrecedes: function(range)
+    {
+        if (!range)
+            return false;
+        return this.endLine === range.startLine && this.endColumn === range.startColumn;
+    },
+
+    /**
+     * @param {WebInspector.TextRange} range
+     * @return {boolean}
+     */
+    immediatelyFollows: function(range)
+    {
+        if (!range)
+            return false;
+        return range.immediatelyPrecedes(this);
+    },
+
+    /**
      * @return {number}
      */
     get linesCount()
@@ -251,15 +273,63 @@
 
     /**
      * @param {WebInspector.TextRange} range
+     * @return {boolean}
+     */
+    _rangeHasOneCharacter: function(range)
+    {
+        if (range.startLine === range.endLine && range.endColumn - range.startColumn === 1)
+            return true;
+        if (range.endLine - range.startLine === 1 && range.endColumn === 0 && range.startColumn === this.lineLength(range.startLine))
+            return true;
+        return false;
+    },
+
+    /**
+     * @param {WebInspector.TextRange} range
      * @param {string} text
      * @param {WebInspector.TextRange=} originalSelection
+     * @return {boolean}
+     */
+    _isEditRangeUndoBoundary: function(range, text, originalSelection)
+    {
+        if (originalSelection && !originalSelection.isEmpty())
+            return true;
+        if (text)
+            return text.length > 1 || !range.isEmpty();
+        return !this._rangeHasOneCharacter(range);
+    },
+
+    /**
+     * @param {WebInspector.TextRange} range
+     * @param {string} text
+     * @return {boolean}
+     */
+    _isEditRangeAdjacentToLastCommand: function(range, text)
+    {
+        if (!this._lastCommand)
+            return true;
+        if (!text) {
+            // FIXME: Distinguish backspace and delete in lastCommand.
+            return this._lastCommand.newRange.immediatelyPrecedes(range) || this._lastCommand.newRange.immediatelyFollows(range);
+        }
+        return text.indexOf("\n") === -1 && this._lastCommand.newRange.immediatelyPrecedes(range);
+    },
+
+    /**
+     * @param {WebInspector.TextRange} range
+     * @param {string} text
+     * @param {WebInspector.TextRange=} originalSelection
      * @return {WebInspector.TextRange}
      */
     editRange: function(range, text, originalSelection)
-    {   
-        if (this._lastEditedRange && (!text || text.indexOf("\n") !== -1 || this._lastEditedRange.endLine !== range.startLine || this._lastEditedRange.endColumn !== range.startColumn))
+    {
+        var undoBoundary = this._isEditRangeUndoBoundary(range, text, originalSelection);
+        if (undoBoundary || !this._isEditRangeAdjacentToLastCommand(range, text))
             this._markUndoableState();
-        return this._innerEditRange(range, text, originalSelection);
+        var newRange = this._innerEditRange(range, text, originalSelection);
+        if (undoBoundary)
+            this._markUndoableState();
+        return newRange;
     },
 
     /**
@@ -272,8 +342,7 @@
     {
         var originalText = this.copyRange(range);
         var newRange = this._innerSetText(range, text);
-        this._lastEditedRange = newRange;
-        this._pushUndoableCommand(newRange, originalText, originalSelection || range);
+        this._lastCommand = this._pushUndoableCommand(newRange, originalText, originalSelection || range);
         this.dispatchEventToListeners(WebInspector.TextEditorModel.Events.TextChanged, { oldRange: range, newRange: newRange, editRange: true });
         return newRange;
     },
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to