[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-10851-g50815da

apavlov at chromium.org apavlov at chromium.org
Wed Dec 22 18:30:57 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 1faa001a91894b278135f71d9d1ff2d640ca9ddf
Author: apavlov at chromium.org <apavlov at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Dec 13 15:06:26 2010 +0000

    2010-12-08  Alexander Pavlov  <apavlov at chromium.org>
    
            Reviewed by Joseph Pecoraro.
    
            Web Inspector: Enable CSS property editing name/value-wise (like Firebug does)
            https://bugs.webkit.org/show_bug.cgi?id=50565
    
            For CSS property editing, the property name and value have become two fields separated
            by a colon (rather than one field containing the full property text.) A user can tab
            between the name and value fields forward and backward. A colon typed in the name field
            and a semicolon in the value field (unless found inside a string) act as a Tab and focus
            the next editable field (while applying the entire property value.)
    
            Now a user can tab through all editable styles for an element, even across rule boundaries.
    
            WebCore:
            * inspector/front-end/BreakpointsSidebarPane.js:
            (WebInspector.XHRBreakpointsSidebarPane.prototype._startEditingBreakpoint):
            * inspector/front-end/DataGrid.js:
            (WebInspector.DataGrid.prototype._startEditingColumnOfDataGridNode):
            (WebInspector.DataGrid.prototype._startEditing):
            * inspector/front-end/ElementsTreeOutline.js:
            (WebInspector.ElementsTreeElement.prototype._startEditingAttribute):
            (WebInspector.ElementsTreeElement.prototype._startEditingTextNode):
            (WebInspector.ElementsTreeElement.prototype._startEditingTagName):
            (WebInspector.ElementsTreeElement.prototype._startEditingAsHTML):
            * inspector/front-end/MetricsSidebarPane.js:
            (WebInspector.MetricsSidebarPane.prototype.startEditing):
            * inspector/front-end/ObjectPropertiesSection.js:
            (WebInspector.ObjectPropertyTreeElement.prototype.startEditing):
            * inspector/front-end/Section.js:
            (WebInspector.Section):
            (WebInspector.Section.prototype.get subtitleAsTextForTest):
            (WebInspector.Section.prototype.get nextSibling):
            (WebInspector.Section.prototype.get previousSibling):
            * inspector/front-end/SourceFrame.js:
            (WebInspector.SourceFrame.prototype._editBreakpointCondition):
            * inspector/front-end/StylesSidebarPane.js:
            (WebInspector.StylePropertiesSection.prototype.nextEditableSibling):
            (WebInspector.StylePropertiesSection.prototype.previousEditableSibling):
            (WebInspector.StylePropertiesSection.prototype.addNewBlankProperty):
            (WebInspector.StylePropertiesSection.prototype.startEditingSelector):
            (WebInspector.StylePropertiesSection.prototype.editingSelectorCommitted):
            (WebInspector.StylePropertyTreeElement.prototype.):
            (WebInspector.StylePropertyTreeElement.prototype):
            * inspector/front-end/TextViewer.js:
            (WebInspector.TextViewer.prototype._handleDoubleClick):
            * inspector/front-end/WatchExpressionsSidebarPane.js:
            (WebInspector.WatchExpressionTreeElement.prototype.startEditing):
            * inspector/front-end/inspector.css:
            (.child-editing):
            * inspector/front-end/inspector.js:
            (WebInspector.startEditing.defaultFinishHandler):
            (WebInspector.startEditing):
            * inspector/front-end/treeoutline.js:
            (TreeElement.prototype.select):
    
            LayoutTests:
            * inspector/console-dir.html:
            * inspector/styles-add-blank-property.html:
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73913 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 723267b..a58f503 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2010-12-08  Alexander Pavlov  <apavlov at chromium.org>
+
+        Reviewed by Joseph Pecoraro.
+
+        Web Inspector: Enable CSS property editing name/value-wise (like Firebug does)
+        https://bugs.webkit.org/show_bug.cgi?id=50565
+
+        * inspector/console-dir.html:
+        * inspector/styles-add-blank-property.html:
+
 2010-12-13  W. James MacLean  <wjmaclean at chromium.org>
 
         Reviewed by Csaba Osztrogonác.
diff --git a/LayoutTests/inspector/console-dir.html b/LayoutTests/inspector/console-dir.html
index 53f7dbe..192f710 100755
--- a/LayoutTests/inspector/console-dir.html
+++ b/LayoutTests/inspector/console-dir.html
@@ -37,9 +37,9 @@ function frontend_expandAndDumpConsoleMessages(testController)
         var element = messages[i].toMessageElement();
         var node = element.traverseNextNode(element);
         while (node) {
-            if (node.sectionForTest) {
-                messages[i].section = node.sectionForTest;
-                node.sectionForTest.expanded = true;
+            if (node._section) {
+                messages[i].section = node._section;
+                node._section.expanded = true;
                 break;
             }
             node = node.traverseNextNode(element);
diff --git a/LayoutTests/inspector/styles-add-blank-property.html b/LayoutTests/inspector/styles-add-blank-property.html
index 013c311..fd36a95 100644
--- a/LayoutTests/inspector/styles-add-blank-property.html
+++ b/LayoutTests/inspector/styles-add-blank-property.html
@@ -39,8 +39,9 @@ function frontend_dumpInspectedStyle(testController)
 
     var evt = document.createEvent("KeyboardEvent");
     evt.initKeyboardEvent("keydown", true /* can bubble */, true /* can cancel */, null /* view */, "Enter", "");
-    treeElement.listItemElement.textContent = "text-decoration: none";
-    treeElement.listItemElement.dispatchEvent(evt);
+    treeElement.nameElement.textContent = "text-decoration";
+    treeElement.valueElement.textContent = "none";
+    treeElement.nameElement.dispatchEvent(evt);
 
     testController.runAfterPendingDispatches(frontend_dumpResults.bind(this, testController));
 }
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index e071fce..84c0627 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,59 @@
+2010-12-08  Alexander Pavlov  <apavlov at chromium.org>
+
+        Reviewed by Joseph Pecoraro.
+
+        Web Inspector: Enable CSS property editing name/value-wise (like Firebug does)
+        https://bugs.webkit.org/show_bug.cgi?id=50565
+
+        For CSS property editing, the property name and value have become two fields separated
+        by a colon (rather than one field containing the full property text.) A user can tab
+        between the name and value fields forward and backward. A colon typed in the name field
+        and a semicolon in the value field (unless found inside a string) act as a Tab and focus
+        the next editable field (while applying the entire property value.)
+
+        Now a user can tab through all editable styles for an element, even across rule boundaries.
+
+        * inspector/front-end/BreakpointsSidebarPane.js:
+        (WebInspector.XHRBreakpointsSidebarPane.prototype._startEditingBreakpoint):
+        * inspector/front-end/DataGrid.js:
+        (WebInspector.DataGrid.prototype._startEditingColumnOfDataGridNode):
+        (WebInspector.DataGrid.prototype._startEditing):
+        * inspector/front-end/ElementsTreeOutline.js:
+        (WebInspector.ElementsTreeElement.prototype._startEditingAttribute):
+        (WebInspector.ElementsTreeElement.prototype._startEditingTextNode):
+        (WebInspector.ElementsTreeElement.prototype._startEditingTagName):
+        (WebInspector.ElementsTreeElement.prototype._startEditingAsHTML):
+        * inspector/front-end/MetricsSidebarPane.js:
+        (WebInspector.MetricsSidebarPane.prototype.startEditing):
+        * inspector/front-end/ObjectPropertiesSection.js:
+        (WebInspector.ObjectPropertyTreeElement.prototype.startEditing):
+        * inspector/front-end/Section.js:
+        (WebInspector.Section):
+        (WebInspector.Section.prototype.get subtitleAsTextForTest):
+        (WebInspector.Section.prototype.get nextSibling):
+        (WebInspector.Section.prototype.get previousSibling):
+        * inspector/front-end/SourceFrame.js:
+        (WebInspector.SourceFrame.prototype._editBreakpointCondition):
+        * inspector/front-end/StylesSidebarPane.js:
+        (WebInspector.StylePropertiesSection.prototype.nextEditableSibling):
+        (WebInspector.StylePropertiesSection.prototype.previousEditableSibling):
+        (WebInspector.StylePropertiesSection.prototype.addNewBlankProperty):
+        (WebInspector.StylePropertiesSection.prototype.startEditingSelector):
+        (WebInspector.StylePropertiesSection.prototype.editingSelectorCommitted):
+        (WebInspector.StylePropertyTreeElement.prototype.):
+        (WebInspector.StylePropertyTreeElement.prototype):
+        * inspector/front-end/TextViewer.js:
+        (WebInspector.TextViewer.prototype._handleDoubleClick):
+        * inspector/front-end/WatchExpressionsSidebarPane.js:
+        (WebInspector.WatchExpressionTreeElement.prototype.startEditing):
+        * inspector/front-end/inspector.css:
+        (.child-editing):
+        * inspector/front-end/inspector.js:
+        (WebInspector.startEditing.defaultFinishHandler):
+        (WebInspector.startEditing):
+        * inspector/front-end/treeoutline.js:
+        (TreeElement.prototype.select):
+
 2010-12-13  Yael Aharon  <yael.aharon at nokia.com>
 
         Unreviewed.
diff --git a/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
index 47194da..e794b82 100644
--- a/WebCore/inspector/front-end/BreakpointsSidebarPane.js
+++ b/WebCore/inspector/front-end/BreakpointsSidebarPane.js
@@ -145,7 +145,10 @@ WebInspector.XHRBreakpointsSidebarPane.prototype = {
 
         var commitHandler = this._hideEditBreakpointDialog.bind(this, inputElement, true, breakpointItem);
         var cancelHandler = this._hideEditBreakpointDialog.bind(this, inputElement, false, breakpointItem);
-        WebInspector.startEditing(inputElement, commitHandler, cancelHandler);
+        WebInspector.startEditing(inputElement, {
+            commitHandler: commitHandler,
+            cancelHandler: cancelHandler
+        });
     },
 
     _hideEditBreakpointDialog: function(inputElement, accept, breakpointItem)
diff --git a/WebCore/inspector/front-end/DataGrid.js b/WebCore/inspector/front-end/DataGrid.js
index 902062c..52995d4 100644
--- a/WebCore/inspector/front-end/DataGrid.js
+++ b/WebCore/inspector/front-end/DataGrid.js
@@ -169,7 +169,11 @@ WebInspector.DataGrid.prototype = {
         this._editingNode.select();
 
         var element = this._editingNode._element.children[column];
-        WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
+        WebInspector.startEditing(element, {
+            context: element.textContent,
+            commitHandler: this._editingCommitted.bind(this),
+            cancelHandler: this._editingCancelled.bind(this)
+        });
         window.getSelection().setBaseAndExtent(element, 0, element, 1);
     },
 
@@ -191,7 +195,11 @@ WebInspector.DataGrid.prototype = {
             return this._startEditingColumnOfDataGridNode(this._editingNode, 0);
 
         this._editing = true;
-        WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
+        WebInspector.startEditing(element, {
+            context: element.textContent,
+            commitHandler: this._editingCommitted.bind(this),
+            cancelHandler: this._editingCancelled.bind(this)
+        });
         window.getSelection().setBaseAndExtent(element, 0, element, 1);
     },
 
diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js
index 02a7911..919c8f6 100644
--- a/WebCore/inspector/front-end/ElementsTreeOutline.js
+++ b/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -872,7 +872,11 @@ WebInspector.ElementsTreeElement.prototype = {
         // Remove zero-width spaces that were added by nodeTitleInfo.
         removeZeroWidthSpaceRecursive(attribute);
 
-        this._editing = WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
+        this._editing = WebInspector.startEditing(attribute, {
+            context: attributeName,
+            commitHandler: this._attributeEditingCommitted.bind(this),
+            cancelHandler: this._editingCancelled.bind(this)
+        });
         window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);
 
         return true;
@@ -883,7 +887,11 @@ WebInspector.ElementsTreeElement.prototype = {
         if (WebInspector.isBeingEdited(textNode))
             return true;
 
-        this._editing = WebInspector.startEditing(textNode, this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this));
+        this._editing = WebInspector.startEditing(textNode, {
+            context: null,
+            commitHandler: this._textNodeEditingCommitted.bind(this),
+            cancelHandler: this._editingCancelled.bind(this)
+        });
         window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1);
 
         return true;
@@ -926,7 +934,11 @@ WebInspector.ElementsTreeElement.prototype = {
 
         tagNameElement.addEventListener('keyup', keyupListener, false);
 
-        this._editing = WebInspector.startEditing(tagNameElement, editingComitted.bind(this), editingCancelled.bind(this), tagName);
+        this._editing = WebInspector.startEditing(tagNameElement, {
+            context: tagName,
+            commitHandler: editingComitted.bind(this),
+            cancelHandler: editingCancelled.bind(this)
+        });
         window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1);
         return true;
     },
@@ -980,7 +992,12 @@ WebInspector.ElementsTreeElement.prototype = {
             this.updateSelection();
         }
 
-        this._editing = WebInspector.startEditing(this._htmlEditElement, commit.bind(this), dispose.bind(this), null, true);
+        this._editing = WebInspector.startEditing(this._htmlEditElement, {
+            context: null,
+            commitHandler: commit.bind(this),
+            cancelHandler: dispose.bind(this),
+            multiline: true
+        });
     },
 
     _attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
diff --git a/WebCore/inspector/front-end/MetricsSidebarPane.js b/WebCore/inspector/front-end/MetricsSidebarPane.js
index 3784ce8..3c0f315 100644
--- a/WebCore/inspector/front-end/MetricsSidebarPane.js
+++ b/WebCore/inspector/front-end/MetricsSidebarPane.js
@@ -175,7 +175,11 @@ WebInspector.MetricsSidebarPane.prototype = {
 
         var context = { box: box, styleProperty: styleProperty };
 
-        WebInspector.startEditing(targetElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+        WebInspector.startEditing(targetElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this)
+        });
     },
 
     editingCancelled: function(element, context)
diff --git a/WebCore/inspector/front-end/ObjectPropertiesSection.js b/WebCore/inspector/front-end/ObjectPropertiesSection.js
index 64e214f..e4794f3 100644
--- a/WebCore/inspector/front-end/ObjectPropertiesSection.js
+++ b/WebCore/inspector/front-end/ObjectPropertiesSection.js
@@ -238,7 +238,11 @@ WebInspector.ObjectPropertyTreeElement.prototype = {
 
         this.listItemElement.addStyleClass("editing-sub-part");
 
-        WebInspector.startEditing(this.valueElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+        WebInspector.startEditing(this.valueElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this)
+        });
     },
 
     editingEnded: function(context)
diff --git a/WebCore/inspector/front-end/Section.js b/WebCore/inspector/front-end/Section.js
index a186d43..5caa78b 100644
--- a/WebCore/inspector/front-end/Section.js
+++ b/WebCore/inspector/front-end/Section.js
@@ -31,7 +31,7 @@ WebInspector.Section = function(title, subtitle)
 {
     this.element = document.createElement("div");
     this.element.className = "section";
-    this.element.sectionForTest = this;
+    this.element._section = this;
 
     this.headerElement = document.createElement("div");
     this.headerElement.className = "header";
@@ -85,15 +85,15 @@ WebInspector.Section.prototype = {
         this.subtitleElement.textContent = x;
     },
 
-    get subtitleAsTextForTest()
-    {
-        var result = this.subtitleElement.textContent;
-        var child = this.subtitleElement.querySelector("[data-uncopyable]");
-        if (child) {
-            var linkData = child.getAttribute("data-uncopyable");
-            if (linkData)
-                result += linkData;
-        }
+    get subtitleAsTextForTest()
+    {
+        var result = this.subtitleElement.textContent;
+        var child = this.subtitleElement.querySelector("[data-uncopyable]");
+        if (child) {
+            var linkData = child.getAttribute("data-uncopyable");
+            if (linkData)
+                result += linkData;
+        }
         return result;
     },
 
@@ -124,6 +124,26 @@ WebInspector.Section.prototype = {
         }
     },
 
+    get nextSibling()
+    {
+        var curElement = this.element;
+        do {
+            curElement = curElement.nextSibling;
+        } while (curElement && !curElement._section);
+
+        return curElement ? curElement._section : null;
+    },
+
+    get previousSibling()
+    {
+        var curElement = this.element;
+        do {
+            curElement = curElement.previousSibling;
+        } while (curElement && !curElement._section);
+
+        return curElement ? curElement._section : null;
+    },
+
     expand: function()
     {
         if (this._expanded)
diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js
index 557837d..ab03807 100644
--- a/WebCore/inspector/front-end/SourceFrame.js
+++ b/WebCore/inspector/front-end/SourceFrame.js
@@ -705,7 +705,11 @@ WebInspector.SourceFrame.prototype = {
         var dismissedHandler = dismissed.bind(this);
         this._conditionEditorElement.addEventListener("blur", dismissedHandler, false);
 
-        WebInspector.startEditing(this._conditionEditorElement, committed.bind(this), dismissedHandler);
+        WebInspector.startEditing(this._conditionEditorElement, {
+            context: null,
+            commitHandler: committed.bind(this),
+            cancelHandler: dismissedHandler
+        });
         this._conditionEditorElement.value = breakpoint.condition;
         this._conditionEditorElement.select();
     },
diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js
index db72486..a3d79c1 100644
--- a/WebCore/inspector/front-end/StylesSidebarPane.js
+++ b/WebCore/inspector/front-end/StylesSidebarPane.js
@@ -704,6 +704,26 @@ WebInspector.StylePropertiesSection.prototype = {
         return true;
     },
 
+    nextEditableSibling: function()
+    {
+        var curSection = this;
+        do {
+            curSection = curSection.nextSibling;
+        } while (curSection && !curSection.editable);
+
+        return curSection;
+    },
+
+    previousEditableSibling: function()
+    {
+        var curSection = this;
+        do {
+            curSection = curSection.previousSibling;
+        } while (curSection && !curSection.editable);
+
+        return curSection;
+    },
+
     update: function(full)
     {
         if (full) {
@@ -795,6 +815,7 @@ WebInspector.StylePropertiesSection.prototype = {
         this.propertiesTreeOutline.appendChild(item);
         item.listItemElement.textContent = "";
         item._newProperty = true;
+        item.updateTitle();
         return item;
     },
 
@@ -875,22 +896,35 @@ WebInspector.StylePropertiesSection.prototype = {
         if (WebInspector.isBeingEdited(element))
             return;
 
-        WebInspector.startEditing(this._selectorElement, this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this), null);
+        WebInspector.startEditing(this._selectorElement, {
+            context: null,
+            commitHandler: this.editingSelectorCommitted.bind(this),
+            cancelHandler: this.editingSelectorCancelled.bind(this)
+        });
         window.getSelection().setBaseAndExtent(element, 0, element, 1);
     },
 
     editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection)
     {
         function moveToNextIfNeeded() {
-            if (!moveDirection || moveDirection !== "forward")
+            if (!moveDirection)
                 return;
 
-            this.expand();
-            if (this.propertiesTreeOutline.children.length === 0)
-                this.addNewBlankProperty().startEditing();
-            else {
-                var item = this.propertiesTreeOutline.children[0]
-                item.startEditing(item.valueElement);
+            if (moveDirection === "forward") {
+                this.expand();
+                if (this.propertiesTreeOutline.children.length === 0)
+                    this.addNewBlankProperty().startEditing();
+                else {
+                    var item = this.propertiesTreeOutline.children[0]
+                    item.startEditing(item.nameElement);
+                }
+            } else {
+                var previousSection = this.previousEditableSibling();
+                if (!previousSection)
+                    return;
+
+                previousSection.expand();
+                previousSection.addNewBlankProperty().startEditing();
             }
         }
 
@@ -1346,8 +1380,11 @@ WebInspector.StylePropertyTreeElement.prototype = {
         this.listItemElement.appendChild(valueElement);
         this.listItemElement.appendChild(document.createTextNode(";"));
 
-        if (!this.parsedOk)
+        if (!this.parsedOk) {
+            // Avoid having longhands under an invalid shorthand.
+            this.hasChildren = false;
             this.listItemElement.addStyleClass("not-parsed-ok");
+        }
         if (this.property.inactive)
             this.listItemElement.addStyleClass("inactive");
 
@@ -1460,60 +1497,146 @@ WebInspector.StylePropertyTreeElement.prototype = {
         if (this.parent.shorthand)
             return;
 
-        if (WebInspector.isBeingEdited(this.listItemElement) || (this.treeOutline.section && !this.treeOutline.section.editable))
+        if (this.treeOutline.section && !this.treeOutline.section.editable)
+            return;
+
+        if (!selectElement)
+            selectElement = this.nameElement; // No arguments passed in - edit the name element by default.
+        else
+            selectElement = selectElement.enclosingNodeOrSelfWithClass("webkit-css-property") || selectElement.enclosingNodeOrSelfWithClass("value");
+
+        var isEditingName = selectElement === this.nameElement;
+        if (!isEditingName && selectElement !== this.valueElement) {
+            // Double-click in the LI - start editing value.
+            isEditingName = false;
+            selectElement = this.valueElement;
+        }
+
+        if (WebInspector.isBeingEdited(selectElement))
             return;
 
         var context = {
             expanded: this.expanded,
             hasChildren: this.hasChildren,
-            keyDownListener: this.editingKeyDown.bind(this),
-            keyPressListener: this.editingKeyPress.bind(this)
+            keyDownListener: isEditingName ? this.editingNameKeyDown.bind(this) : this.editingValueKeyDown.bind(this),
+            keyPressListener: isEditingName ? this.editingNameKeyPress.bind(this) : this.editingValueKeyPress.bind(this),
+            isEditingName: isEditingName,
         };
 
         // Lie about our children to prevent expanding on double click and to collapse shorthands.
         this.hasChildren = false;
 
-        if (!selectElement)
-            selectElement = this.listItemElement;
+        selectElement.addEventListener("keydown", context.keyDownListener, false);
+        selectElement.addEventListener("keypress", context.keyPressListener, false);
+        if (selectElement.parentElement)
+            selectElement.parentElement.addStyleClass("child-editing");
+        selectElement.textContent = selectElement.textContent; // remove color swatch and the like
+
+        function shouldCommitValueSemicolon(text, cursorPosition)
+        {
+            // FIXME: should this account for semicolons inside comments?
+            var openQuote = "";
+            for (var i = 0; i < cursorPosition; ++i) {
+                var ch = text[i];
+                if (ch === "\\" && openQuote !== "")
+                    ++i; // skip next character inside string
+                else if (!openQuote && (ch === "\"" || ch === "'"))
+                    openQuote = ch;
+                else if (openQuote === ch)
+                    openQuote = "";
+            }
+            return !openQuote;
+        }
 
-        this.listItemElement.addEventListener("keydown", context.keyDownListener, false);
-        this.listItemElement.addEventListener("keypress", context.keyPressListener, false);
+        function nameValueFinishHandler(context, isEditingName, event)
+        {
+            // FIXME: the ":"/";" detection does not work for non-US layouts due to the event being keydown rather than keypress.
+            var isFieldInputTerminated = (event.keyCode === WebInspector.KeyboardShortcut.Keys.Semicolon.code) &&
+                (isEditingName ? event.shiftKey : (!event.shiftKey && shouldCommitValueSemicolon(event.target.textContent, event.target.selectionLeftOffset)));
+            if (isEnterKey(event) || isFieldInputTerminated) {
+                // Enter or colon (for name)/semicolon outside of string (for value).
+                event.preventDefault();
+                return "move-forward";
+            } else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code)
+                return "cancel";
+            else if (event.keyIdentifier === "U+0009") // Tab key.
+                return "move-" + (event.shiftKey ? "backward" : "forward");
+        }
 
-        WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+        WebInspector.startEditing(selectElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this),
+            customFinishHandler: nameValueFinishHandler.bind(this, context, isEditingName)
+        });
         window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1);
     },
 
-    editingKeyPress: function(event)
+    editingNameKeyPress: function(event)
     {
-        var selection = window.getSelection();
-        var colonIndex = this.listItemElement.textContent.indexOf(":");
-        var selectionLeftOffset = event.target.selectionLeftOffset;
-
-        if (colonIndex < 0 || selectionLeftOffset <= colonIndex) {
-            // Complete property names.
-            var character = event.data.toLowerCase();
-            if (character && /[a-z-]/.test(character)) {
-                var prefix = selection.anchorNode.textContent.substring(0, selection.anchorOffset);
-                var property = WebInspector.CSSCompletions.firstStartsWith(prefix + character);
-
-                if (!selection.isCollapsed)
-                    selection.deleteFromDocument();
-
-                this.restoreNameElement();
-
-                if (property) {
-                    if (property !== this.nameElement.textContent)
-                        this.nameElement.textContent = property;
-                    this.nameElement.firstChild.select(prefix.length + 1);
-                    event.preventDefault();
-                }
+        // Complete property names.
+        var character = event.data.toLowerCase();
+        if (character && /[a-z-]/.test(character)) {
+            var selection = window.getSelection();
+            var prefix = selection.anchorNode.textContent.substring(0, selection.anchorOffset);
+            var property = WebInspector.CSSCompletions.firstStartsWith(prefix + character);
+
+            if (!selection.isCollapsed)
+                selection.deleteFromDocument();
+
+            this.restoreNameElement();
+
+            if (property) {
+                if (property !== this.nameElement.textContent)
+                    this.nameElement.textContent = property;
+                this.nameElement.firstChild.select(prefix.length + 1);
+                event.preventDefault();
             }
-        } else {
-            // FIXME: This should complete property values.
         }
     },
 
-    editingKeyDown: function(event)
+    editingValueKeyPress: function(event)
+    {
+        // FIXME: This should complete property values.
+    },
+
+    editingNameKeyDown: function(event)
+    {
+        var showNext;
+        if (event.keyIdentifier === "Up")
+            showNext = false;
+        else if (event.keyIdentifier === "Down")
+            showNext = true;
+        else
+            return;
+
+        var selection = window.getSelection();
+        if (!selection.rangeCount)
+            return;
+
+        var selectionRange = selection.getRangeAt(0);
+        if (selectionRange.commonAncestorContainer !== this.nameElement && !selectionRange.commonAncestorContainer.isDescendant(this.nameElement))
+            return;
+
+        const styleValueDelimeters = " \t\n\"':;,/()";
+        var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this.nameElement);
+        var wordString = wordRange.toString();
+        var prefix = selectionRange.startContainer.textContent.substring(0, selectionRange.startOffset);
+        var property;
+
+        if (showNext)
+            property = WebInspector.CSSCompletions.next(wordString, prefix);
+        else
+            property = WebInspector.CSSCompletions.previous(wordString, prefix);
+
+        if (property) {
+            this.nameElement.textContent = property;
+            this.nameElement.firstChild.select(selectionRange.startOffset);
+        }
+        event.preventDefault();
+    },
+
+    editingValueKeyDown: function(event)
     {
         var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down");
         var pageKeyPressed = (event.keyIdentifier === "PageUp" || event.keyIdentifier === "PageDown");
@@ -1525,33 +1648,11 @@ WebInspector.StylePropertyTreeElement.prototype = {
             return;
 
         var selectionRange = selection.getRangeAt(0);
-        if (selectionRange.commonAncestorContainer !== this.listItemElement && !selectionRange.commonAncestorContainer.isDescendant(this.listItemElement))
+        if (selectionRange.commonAncestorContainer !== this.valueElement && !selectionRange.commonAncestorContainer.isDescendant(this.valueElement))
             return;
 
-        // If there are several properties in the text, do not handle increments/decrements.
-        var text = event.target.textContent.trim();
-        var openQuote;
-        var wasEscape = false;
-        // Exclude the last character from the check since it is allowed to be ";".
-        for (var i = 0; i < text.length - 1; ++i) {
-            var ch = text.charAt(i);
-            if (ch === "\\") {
-                wasEscape = true;
-                continue;
-            }
-            if (ch === ";" && !openQuote)
-                return; // Do not handle name/value shifts if the property is compound.
-            if ((ch === "'" || ch === "\"") && !wasEscape) {
-                if (!openQuote)
-                    openQuote = ch;
-                else if (ch === openQuote)
-                    openQuote = null;
-            }
-            wasEscape = false;
-        }
-
         const styleValueDelimeters = " \t\n\"':;,/()";
-        var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this.listItemElement);
+        var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this.valueElement);
         var wordString = wordRange.toString();
         var replacementString = wordString;
 
@@ -1593,22 +1694,6 @@ WebInspector.StylePropertyTreeElement.prototype = {
             }
 
             replacementString = prefix + number + suffix;
-        } else if (selection.containsNode(this.nameElement, true)) {
-            var prefix = selectionRange.startContainer.textContent.substring(0, selectionRange.startOffset);
-            var property;
-
-            if (event.keyIdentifier === "Up")
-                property = WebInspector.CSSCompletions.previous(wordString, prefix);
-            else if (event.keyIdentifier === "Down")
-                property = WebInspector.CSSCompletions.next(wordString, prefix);
-
-            var startOffset = selectionRange.startOffset;
-            if (property) {
-                this.nameElement.textContent = property;
-                this.nameElement.firstChild.select(startOffset);
-            }
-            event.preventDefault();
-            return;
         } else {
             // FIXME: this should cycle through known keywords for the current property value.
         }
@@ -1632,7 +1717,9 @@ WebInspector.StylePropertyTreeElement.prototype = {
             // if the editing is canceled and before each apply.
             this.originalPropertyText = this.property.propertyText;
         }
-        this.applyStyleText(this.listItemElement.textContent);
+
+        // Synthesize property text disregarding any comments, custom whitespace etc.
+        this.applyStyleText(this.nameElement.textContent + ": " + this.valueElement.textContent);
     },
 
     editingEnded: function(context)
@@ -1640,8 +1727,12 @@ WebInspector.StylePropertyTreeElement.prototype = {
         this.hasChildren = context.hasChildren;
         if (context.expanded)
             this.expand();
-        this.listItemElement.removeEventListener("keydown", context.keyDownListener, false);
-        this.listItemElement.removeEventListener("keypress", context.keyPressListener, false);
+        var editedElement = context.isEditingName ? this.nameElement : this.valueElement;
+        editedElement.removeEventListener("keydown", context.keyDownListener, false);
+        editedElement.removeEventListener("keypress", context.keyPressListener, false);
+        if (editedElement.parentElement)
+            editedElement.parentElement.removeStyleClass("child-editing");
+
         delete this.originalPropertyText;
     },
 
@@ -1661,61 +1752,96 @@ WebInspector.StylePropertyTreeElement.prototype = {
     editingCommitted: function(element, userInput, previousContent, context, moveDirection)
     {
         this.editingEnded(context);
+        var isEditingName = context.isEditingName;
 
         // Determine where to move to before making changes
-        var newProperty, moveToPropertyName, moveToSelector;
+        var createNewProperty, moveToPropertyName, moveToSelector;
         var moveTo = this;
-        do {
-            moveTo = (moveDirection === "forward" ? moveTo.nextSibling : moveTo.previousSibling);
-        } while(moveTo && !moveTo.selectable);
-
-        if (moveTo)
-            moveToPropertyName = moveTo.name;
-        else if (moveDirection === "forward")
-            newProperty = true;
-        else if (moveDirection === "backward" && this.treeOutline.section.rule)
-            moveToSelector = true;
+        var moveToOther = (isEditingName ^ (moveDirection === "forward"));
+        var abandonNewProperty = this._newProperty && !userInput && (moveToOther || isEditingName);
+        if (moveDirection === "forward" && !isEditingName || moveDirection === "backward" && isEditingName) {
+            do {
+                moveTo = (moveDirection === "forward" ? moveTo.nextSibling : moveTo.previousSibling);
+            } while(moveTo && !moveTo.selectable);
+
+           if (moveTo)
+                moveToPropertyName = moveTo.name;
+            else if (moveDirection === "forward" && (!this._newProperty || userInput))
+                createNewProperty = true;
+            else if (moveDirection === "backward" && this.treeOutline.section.rule)
+                moveToSelector = true;
+        }
 
-        // Make the Changes and trigger the moveToNextCallback after updating
+        // Make the Changes and trigger the moveToNextCallback after updating.
         var blankInput = /^\s*$/.test(userInput);
-        if (userInput !== previousContent || (this._newProperty && blankInput)) { // only if something changed, or adding a new style and it was blank
-            this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput);
-            this.applyStyleText(userInput, true);
-        } else
-            moveToNextCallback(this._newProperty, false, this.treeOutline.section, false);
+        var shouldCommitNewProperty = this._newProperty && (moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput));
 
-        // The Callback to start editing the next property
+        if ((userInput !== previousContent && !this._newProperty) || shouldCommitNewProperty) {
+            this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, this.treeOutline.section);
+            var propertyText;
+            if (blankInput || (this._newProperty && /^\s*$/.test(this.valueElement.textContent)))
+                propertyText = "";
+            else {
+                if (isEditingName)
+                    propertyText = userInput + ": " + this.valueElement.textContent;
+                else
+                    propertyText = this.nameElement.textContent + ": " + userInput;
+            }
+            this.applyStyleText(propertyText, true);
+        } else {
+            if (!this._newProperty)
+                this.updateTitle();
+            moveToNextCallback(this._newProperty, false, this.treeOutline.section);
+        }
+
+        var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1;
+
+        // The Callback to start editing the next/previous property/selector.
         function moveToNextCallback(alreadyNew, valueChanged, section)
         {
             if (!moveDirection)
                 return;
 
-            // User just tabbed through without changes
+            // User just tabbed through without changes.
             if (moveTo && moveTo.parent) {
-                moveTo.startEditing(moveTo.valueElement);
+                moveTo.startEditing(!isEditingName ? moveTo.nameElement : moveTo.valueElement);
                 return;
             }
 
-            // User has made a change then tabbed, wiping all the original treeElements,
-            // recalculate the new treeElement for the same property we were going to edit next
-            // FIXME(apavlov): this will not work for multiple same-named properties in a style
-            //                 (the first one will always be returned).
+            // User has made a change then tabbed, wiping all the original treeElements.
+            // Recalculate the new treeElement for the same property we were going to edit next.
             if (moveTo && !moveTo.parent) {
-                var treeElement = section.findTreeElementWithName(moveToPropertyName);
-                if (treeElement)
-                    treeElement.startEditing(treeElement.valueElement);
-                return;
+                var propertyElements = section.propertiesTreeOutline.children;
+                if (moveDirection === "forward" && blankInput && !isEditingName)
+                    --moveToIndex;
+                if (moveToIndex >= propertyElements.length && !this._newProperty)
+                    createNewProperty = true;
+                else {
+                    var treeElement = moveToIndex >= 0 ? propertyElements[moveToIndex] : null;
+                    if (treeElement) {
+                        treeElement.startEditing(!isEditingName ? treeElement.nameElement : treeElement.valueElement);
+                        return;
+                    } else if (!alreadyNew)
+                        moveToSelector = true;
+                }
             }
 
-            // Create a new attribute in this section
-            if (newProperty) {
-                if (alreadyNew && !valueChanged)
+            // Create a new attribute in this section (or move to next editable selector if possible).
+            if (createNewProperty) {
+                if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === "backward")))
                     return;
 
                 section.addNewBlankProperty().startEditing();
                 return;
             }
 
+            if (abandonNewProperty) {
+                var sectionToEdit = moveDirection === "backward" ? section : section.nextEditableSibling();
+                if (sectionToEdit && sectionToEdit.rule)
+                    sectionToEdit.startEditingSelector();
+                return;
+            }
+
             if (moveToSelector)
                 section.startEditingSelector();
         }
@@ -1725,16 +1851,13 @@ WebInspector.StylePropertyTreeElement.prototype = {
     {
         var section = this.treeOutline.section;
         var elementsPanel = WebInspector.panels.elements;
-        styleText = styleText.replace(/\s/g, " ").trim(); // replace &nbsp; with whitespace.
+        styleText = styleText.replace(/\s/g, " ").trim(); // Replace &nbsp; with whitespace.
         var styleTextLength = styleText.length;
-        if (!styleTextLength && updateInterface) {
-            if (this._newProperty) {
-                // The user deleted everything, so remove the tree element and update.
-                this.parent.removeChild(this);
-                section.afterUpdate();
-                return;
-            } else
-                delete section._afterUpdate;
+        if (!styleTextLength && updateInterface && this._newProperty) {
+            // The user deleted everything, so remove the tree element and update.
+            this.parent.removeChild(this);
+            section.afterUpdate();
+            return;
         }
 
         function callback(newStyle)
diff --git a/WebCore/inspector/front-end/TextViewer.js b/WebCore/inspector/front-end/TextViewer.js
index 9ad5e49..f116dea 100644
--- a/WebCore/inspector/front-end/TextViewer.js
+++ b/WebCore/inspector/front-end/TextViewer.js
@@ -268,7 +268,12 @@ WebInspector.TextViewer.prototype = {
         var oldContent = lineRow.lastChild.innerHTML;
         var cancelEditingCallback = this._cancelEditingLine.bind(this, lineRow.lastChild, oldContent);
         var commitEditingCallback = this._commitEditingLine.bind(this, lineRow.lineNumber, lineRow.lastChild, cancelEditingCallback);
-        this._editingLine = WebInspector.startEditing(lineRow.lastChild, commitEditingCallback, cancelEditingCallback, null, true);
+        this._editingLine = WebInspector.startEditing(lineRow.lastChild, {
+            context: null,
+            commitHandler: commitEditingCallback,
+            cancelHandler: cancelEditingCallback,
+            multiline: true
+        });
     },
 
     _commitEditingLine: function(lineNumber, element, cancelEditingCallback)
diff --git a/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js b/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
index 44063a3..a01046b 100644
--- a/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
+++ b/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
@@ -240,7 +240,11 @@ WebInspector.WatchExpressionTreeElement.prototype = {
 
         this.listItemElement.addStyleClass("editing-sub-part");
 
-        WebInspector.startEditing(this.nameElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+        WebInspector.startEditing(this.nameElement, {
+            context: context,
+            commitHandler: this.editingCommitted.bind(this),
+            cancelHandler: this.editingCancelled.bind(this)
+        });
     },
 
     editingCancelled: function(element, context)
diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css
index 965689b..c908427 100644
--- a/WebCore/inspector/front-end/inspector.css
+++ b/WebCore/inspector/front-end/inspector.css
@@ -1424,6 +1424,12 @@ body.inactive .placard.selected {
     text-decoration: none !important;
 }
 
+.child-editing {
+    color: black !important;
+    text-decoration: none !important;
+    overflow: visible !important;
+}
+
 .editing br {
     display: none;
 }
diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js
index 8e165dc..e0d8e65 100644
--- a/WebCore/inspector/front-end/inspector.js
+++ b/WebCore/inspector/front-end/inspector.js
@@ -1915,13 +1915,23 @@ WebInspector.isEditingAnyField = function()
     return this.__editing;
 }
 
-WebInspector.startEditing = function(element, committedCallback, cancelledCallback, context, multiline)
+// Available config fields (all optional):
+// context: Object - an arbitrary context object to be passed to the commit and cancel handlers
+// commitHandler: Function - handles editing "commit" outcome
+// cancelHandler: Function - handles editing "cancel" outcome
+// customFinishHandler: Function - custom finish handler for the editing session (invoked on keydown)
+// multiline: Boolean - whether the edited element is multiline
+WebInspector.startEditing = function(element, config)
 {
     if (element.__editing)
         return;
     element.__editing = true;
     WebInspector.__editing = true;
 
+    config = config || {};
+    var committedCallback = config.commitHandler;
+    var cancelledCallback = config.cancelHandler;
+    var context = config.context;
     var oldText = getContent(element);
     var moveDirection = "";
 
@@ -1977,20 +1987,36 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba
             committedCallback(this, getContent(this), oldText, context, moveDirection);
     }
 
-    function keyDownEventListener(event) {
+    function defaultFinishHandler(event)
+    {
         var isMetaOrCtrl = WebInspector.isMac() ?
             event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey :
             event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
-        if (isEnterKey(event) && (!multiline || isMetaOrCtrl)) {
+        if (isEnterKey(event) && (!config.multiline || isMetaOrCtrl))
+            return "commit";
+        else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code)
+            return "cancel";
+        else if (event.keyIdentifier === "U+0009") // Tab key
+            return "move-" + (event.shiftKey ? "backward" : "forward");
+    }
+
+    function keyDownEventListener(event)
+    {
+        var handler = config.customFinishHandler || defaultFinishHandler;
+        var result = handler(event);
+        if (result === "commit") {
             editingCommitted.call(element);
             event.preventDefault();
             event.stopPropagation();
-        } else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
+        } else if (result === "cancel") {
             editingCancelled.call(element);
             event.preventDefault();
             event.stopPropagation();
-        } else if (event.keyIdentifier === "U+0009") // Tab key
-            moveDirection = (event.shiftKey ? "backward" : "forward");
+        } else if (result && result.indexOf("move-") === 0) {
+            moveDirection = result.substring(5);
+            if (event.keyIdentifier !== "U+0009")
+                blurEventListener();
+        }
     }
 
     element.addEventListener("blur", blurEventListener, false);
diff --git a/WebCore/inspector/front-end/treeoutline.js b/WebCore/inspector/front-end/treeoutline.js
index a1e052f..27bc839 100644
--- a/WebCore/inspector/front-end/treeoutline.js
+++ b/WebCore/inspector/front-end/treeoutline.js
@@ -821,6 +821,10 @@ TreeElement.prototype.select = function(supressOnSelect, selectedByUser)
 
     this.selected = true;
     this.treeOutline._childrenListNode.focus();
+
+    // Focusing on another node may detach "this" from tree.
+    if (!this.treeOutline)
+        return;
     this.treeOutline.selectedTreeElement = this;
     if (this._listItemNode)
         this._listItemNode.addStyleClass("selected");

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list