Reviewed by Adam Roben.
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 16 Mar 2008 06:34:10 +0000 (06:34 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 16 Mar 2008 06:34:10 +0000 (06:34 +0000)
        Bug 17870: Web Inspector console should feel more like a terminal
        http://bugs.webkit.org/show_bug.cgi?id=17870

        Bug 14390: Console input area should be more noticeable
        http://bugs.webkit.org/show_bug.cgi?id=14390

        Adds tab completion, auto completion and a blended input prompt.
        The prompt is also focused when the console is shown.
           Implements a new look, that will be part of the UI refresh.

        * page/inspector/ConsolePanel.js:
        (WebInspector.ConsolePanel): Renamed a few properties.
        (WebInspector.ConsolePanel.get/set promptText): Property to set
        and get the current prompt text. Does not affect command history.
        (WebInspector.ConsolePanel.show): Make the prompt focus on show.
        (WebInspector.ConsolePanel.acceptAutoComplete): Accepts any
        pending auto complete text.
        (WebInspector.ConsolePanel.clearAutoComplete): Cancels any pending
        auto complete text.
        (WebInspector.ConsolePanel.autoCompleteSoon): Sets a timeout to auto
        complete in 250 ms, only if there isn't a pending auto complete.
        (WebInspector.ConsolePanel.complete):
        (WebInspector.ConsolePanel.completions): Generate a list of possible
        completions based on the prefix and the previous expression ranges.
        (WebInspector.ConsolePanel._backwardsRange): Helper to scan backwards
        from a node and offset to find a start node and offset of the first
        character found in the characters string.
        (WebInspector.ConsolePanel._evalInInspectedWindow): Helper to eval in the
        inspected window.
        (WebInspector.ConsolePanel._caretInsidePrompt): Returns true if the selection
        is collapsed and is inside the prompt element.
        (WebInspector.ConsolePanel._moveCaretToEndOfPrompt): Moves the selection
        to the end of the prompt.
        (WebInspector.ConsolePanel._onTabPressed): Calls complete on
        tab press.
        (WebInspector.ConsolePanel._onEnterPressed): Call clearAutoComplete so the
        autocompletion text is not evaluated.

        * page/inspector/Images/errorIcon.png: New image.
        * page/inspector/Images/userInputIcon.png: Added.
        * page/inspector/Images/userInputPreviousIcon.png: Added.
        * page/inspector/Images/warningIcon.png: New image.
        * page/inspector/inspector.css: New refreshed UI.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@31079 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/page/inspector/ConsolePanel.js
WebCore/page/inspector/Images/errorIcon.png
WebCore/page/inspector/Images/userInputIcon.png [new file with mode: 0644]
WebCore/page/inspector/Images/userInputPreviousIcon.png [new file with mode: 0644]
WebCore/page/inspector/Images/warningIcon.png
WebCore/page/inspector/inspector.css

index b8cc926..37ffe66 100644 (file)
@@ -1,3 +1,51 @@
+2008-03-15  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by Adam Roben.
+
+        Bug 17870: Web Inspector console should feel more like a terminal
+        http://bugs.webkit.org/show_bug.cgi?id=17870
+
+        Bug 14390: Console input area should be more noticeable
+        http://bugs.webkit.org/show_bug.cgi?id=14390
+
+        Adds tab completion, auto completion and a blended input prompt.
+        The prompt is also focused when the console is shown.
+           Implements a new look, that will be part of the UI refresh.
+
+        * page/inspector/ConsolePanel.js: 
+        (WebInspector.ConsolePanel): Renamed a few properties.
+        (WebInspector.ConsolePanel.get/set promptText): Property to set
+        and get the current prompt text. Does not affect command history.
+        (WebInspector.ConsolePanel.show): Make the prompt focus on show.
+        (WebInspector.ConsolePanel.acceptAutoComplete): Accepts any
+        pending auto complete text.
+        (WebInspector.ConsolePanel.clearAutoComplete): Cancels any pending
+        auto complete text.
+        (WebInspector.ConsolePanel.autoCompleteSoon): Sets a timeout to auto
+        complete in 250 ms, only if there isn't a pending auto complete.
+        (WebInspector.ConsolePanel.complete): 
+        (WebInspector.ConsolePanel.completions): Generate a list of possible
+        completions based on the prefix and the previous expression ranges.
+        (WebInspector.ConsolePanel._backwardsRange): Helper to scan backwards
+        from a node and offset to find a start node and offset of the first
+        character found in the characters string.
+        (WebInspector.ConsolePanel._evalInInspectedWindow): Helper to eval in the
+        inspected window.
+        (WebInspector.ConsolePanel._caretInsidePrompt): Returns true if the selection
+        is collapsed and is inside the prompt element.
+        (WebInspector.ConsolePanel._moveCaretToEndOfPrompt): Moves the selection
+        to the end of the prompt.
+        (WebInspector.ConsolePanel._onTabPressed): Calls complete on
+        tab press.
+        (WebInspector.ConsolePanel._onEnterPressed): Call clearAutoComplete so the
+        autocompletion text is not evaluated.
+
+        * page/inspector/Images/errorIcon.png: New image.
+        * page/inspector/Images/userInputIcon.png: Added.
+        * page/inspector/Images/userInputPreviousIcon.png: Added.
+        * page/inspector/Images/warningIcon.png: New image.
+        * page/inspector/inspector.css: New refreshed UI.
+
 2008-03-15  Mark Mentovai  <mark@moxienet.com>
 
         Reviewed and landed by Darin.
index 57bf331..035cd48 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,41 +35,67 @@ WebInspector.ConsolePanel = function()
     this.commandHistory = [];
     this.commandOffset = 0;
 
-    this.messageList = document.createElement("ol");
-    this.messageList.className = "console-message-list";
-    this.element.appendChild(this.messageList);
-
-    this.messageList.addEventListener("click", this.messageListClicked.bind(this), true);
-
-    this.consolePrompt = document.createElement("textarea");
-    this.consolePrompt.className = "console-prompt";
-    this.element.appendChild(this.consolePrompt);
-
-    this.consolePrompt.addEventListener("keydown", this.promptKeyDown.bind(this), false);
-
-    var clearButtonText = WebInspector.UIString("Clear");
-    this.clearMessagesElement = document.createElement("button");
-    this.clearMessagesElement.appendChild(document.createTextNode(clearButtonText));
-    this.clearMessagesElement.title = clearButtonText;
-    this.clearMessagesElement.addEventListener("click", this.clearButtonClicked.bind(this), false);
+    this.messagesElement = document.createElement("div");
+    this.messagesElement.id = "console-messages";
+    this.messagesElement.addEventListener("selectstart", this.messagesSelectStart.bind(this), true);
+    this.messagesElement.addEventListener("click", this.messagesClicked.bind(this), true);
+    this.element.appendChild(this.messagesElement);
+
+    this.promptElement = document.createElement("div");
+    this.promptElement.id = "console-prompt";
+    this.promptElement.addEventListener("keydown", this.promptKeyDown.bind(this), false);
+    this.promptElement.appendChild(document.createElement("br"));
+    this.messagesElement.appendChild(this.promptElement);
+
+    this.clearButton = document.createElement("button");
+    this.clearButton.title = WebInspector.UIString("Clear");
+    this.clearButton.textContent = WebInspector.UIString("Clear");
+    this.clearButton.addEventListener("click", this.clearButtonClicked.bind(this), false);
 }
 
 WebInspector.ConsolePanel.prototype = {
+    get promptText()
+    {
+        return this.promptElement.textContent;
+    },
+
+    set promptText(x)
+    {
+        if (!x) {
+            // Append a break element instead of setting textContent to make sure the selection is inside the prompt.
+            this.promptElement.removeChildren();
+            this.promptElement.appendChild(document.createElement("br"));
+        } else
+            this.promptElement.textContent = x;
+
+        this._moveCaretToEndOfPrompt();
+    },
+
     show: function()
     {
         WebInspector.Panel.prototype.show.call(this);
         WebInspector.consoleListItem.select();
 
-        this.clearMessagesElement.removeStyleClass("hidden");
-        if (!this.clearMessagesElement.parentNode)
-            document.getElementById("toolbarButtons").appendChild(this.clearMessagesElement);
+        this.clearButton.removeStyleClass("hidden");
+        if (!this.clearButton.parentNode)
+            document.getElementById("toolbarButtons").appendChild(this.clearButton);
+
+        WebInspector.currentFocusElement = document.getElementById("main");
+
+        function focusPrompt()
+        {
+            if (!this._caretInsidePrompt())
+                this._moveCaretToEndOfPrompt();
+        }
+
+        setTimeout(focusPrompt.bind(this), 0);
     },
 
     hide: function()
     {
         WebInspector.Panel.prototype.hide.call(this);
         WebInspector.consoleListItem.deselect();
-        this.clearMessagesElement.addStyleClass("hidden");
+        this.clearButton.addStyleClass("hidden");
     },
 
     addMessage: function(msg)
@@ -87,12 +113,12 @@ WebInspector.ConsolePanel.prototype = {
                     break;
             }
         }
+
         this.messages.push(msg);
 
-        var item = msg.toListItem();
-        item.message = msg;
-        this.messageList.appendChild(item);
-        item.scrollIntoView(false);
+        var element = msg.toMessageElement();
+        this.messagesElement.insertBefore(element, this.promptElement);
+        this.promptElement.scrollIntoView(false);
     },
 
     clearMessages: function()
@@ -101,13 +127,187 @@ WebInspector.ConsolePanel.prototype = {
             var resource = this.messages[i].resource;
             if (!resource)
                 continue;
-
             resource.errors = 0;
             resource.warnings = 0;
         }
 
         this.messages = [];
-        this.messageList.removeChildren();
+
+        while (this.messagesElement.firstChild != this.promptElement)
+            this.messagesElement.removeChild(this.messagesElement.firstChild);
+    },
+
+    acceptAutoComplete: function()
+    {
+        if (!this.autoCompleteElement || !this.autoCompleteElement.parentNode)
+            return false;
+
+        var text = this.autoCompleteElement.textContent;
+        var textNode = document.createTextNode(text);
+        this.autoCompleteElement.parentNode.replaceChild(textNode, this.autoCompleteElement);
+        delete this.autoCompleteElement;
+
+        var finalSelectionRange = document.createRange();
+        finalSelectionRange.setStart(textNode, text.length);
+        finalSelectionRange.setEnd(textNode, text.length);
+
+        var selection = window.getSelection();
+        selection.removeAllRanges();
+        selection.addRange(finalSelectionRange);
+
+        return true;
+    },
+
+    clearAutoComplete: function(includeTimeout)
+    {
+        if (includeTimeout && "completeTimeout" in this) {
+            clearTimeout(this.completeTimeout);
+            delete this.completeTimeout;
+        }
+
+        if (!this.autoCompleteElement)
+            return;
+
+        if (this.autoCompleteElement.parentNode)
+            this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement);
+        delete this.autoCompleteElement;
+    },
+
+    autoCompleteSoon: function()
+    {
+        if (!("completeTimeout" in this))
+            this.completeTimeout = setTimeout(this.complete.bind(this, true), 250);
+    },
+
+    complete: function(auto)
+    {
+        this.clearAutoComplete(true);
+
+        var selection = window.getSelection();
+        if (!selection.rangeCount)
+            return;
+
+        var selectionRange = selection.getRangeAt(0);
+        if (!selectionRange.commonAncestorContainer.isDescendant(this.promptElement))
+            return;
+
+        if (auto) {
+            if (!selection.isCollapsed)
+                return;
+
+            var node = selectionRange.startContainer;
+            if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length)
+                return;
+
+            var foundNextText = false;
+            while (node) {
+                if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
+                    if (foundNextText)
+                        return;
+                    foundNextText = true;
+                }
+
+                node = node.traverseNextNode(false, this.promptElement);
+            }
+        }
+
+        var wordPrefixRange = this._backwardsRange(" .=:[({;", selectionRange.startContainer, selectionRange.startOffset, this.promptElement);
+
+        var completions = this.completions(wordPrefixRange, auto);
+
+        if (!completions || !completions.length)
+            return;
+
+        var fullWordRange = document.createRange();
+        fullWordRange.setStart(wordPrefixRange.startContainer, wordPrefixRange.startOffset);
+        fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);
+
+        if (completions.length === 1 || selection.isCollapsed || auto) {
+            var completionText = completions[0];
+        } else {
+            var currentText = fullWordRange.toString().trimTrailingWhitespace();
+
+            var foundIndex = null;
+            for (var i = 0; i < completions.length; ++i) {
+                if (completions[i] === currentText)
+                    foundIndex = i;
+            }
+
+            if (foundIndex === null || (foundIndex + 1) >= completions.length)
+                var completionText = completions[0];
+            else
+                var completionText = completions[foundIndex + 1];
+        }
+
+        var wordPrefixLength = wordPrefixRange.toString().length;
+
+        fullWordRange.deleteContents();
+
+        var finalSelectionRange = document.createRange();
+
+        if (auto) {
+            var prefixText = completionText.substring(0, wordPrefixLength);
+            var suffixText = completionText.substring(wordPrefixLength);
+
+            var prefixTextNode = document.createTextNode(prefixText);
+            fullWordRange.insertNode(prefixTextNode);           
+
+            this.autoCompleteElement = document.createElement("span");
+            this.autoCompleteElement.className = "auto-complete-text";
+            this.autoCompleteElement.textContent = suffixText;
+
+            prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);
+
+            finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
+            finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
+        } else {
+            var completionTextNode = document.createTextNode(completionText);
+            fullWordRange.insertNode(completionTextNode);           
+
+            if (completions.length > 1)
+                finalSelectionRange.setStart(completionTextNode, wordPrefixLength);
+            else
+                finalSelectionRange.setStart(completionTextNode, completionText.length);
+
+            finalSelectionRange.setEnd(completionTextNode, completionText.length);
+        }
+
+        selection.removeAllRanges();
+        selection.addRange(finalSelectionRange);
+    },
+
+    completions: function(wordRange, bestMatchOnly)
+    {
+        var prefix = wordRange.toString();
+        var expression = this._backwardsRange(" =:({;", wordRange.startContainer, wordRange.startOffset, this.promptElement);
+        var expressionString = expression.toString().replace(/\.+$/, "");
+
+        if (!expressionString && !prefix)
+            return;
+
+        var result = window;
+        if (expressionString) {
+            try {
+                result = this._evalInInspectedWindow(expressionString);
+            } catch(e) {
+                return;
+            }
+        }
+
+        var results = [];
+        var properties = Object.sortedProperties(result);
+        for (var i = 0; i < properties.length; ++i) {
+            var property = properties[i];
+            if (property.length < prefix.length)
+                continue;
+            if (property.indexOf(prefix) !== 0)
+                continue;
+            results.push(property);
+            if (bestMatchOnly)
+                break;
+        }
+
+        return results;
     },
 
     clearButtonClicked: function()
@@ -115,7 +315,23 @@ WebInspector.ConsolePanel.prototype = {
         this.clearMessages();
     },
 
-    messageListClicked: function(event)
+    messagesSelectStart: function(event)
+    {
+        if (this._selectionTimeout)
+            clearTimeout(this._selectionTimeout);
+
+        function moveBackIfOutside()
+        {
+            delete this._selectionTimeout;
+            if (this._caretInsidePrompt() || !window.getSelection().isCollapsed)
+                return;
+            this._moveCaretToEndOfPrompt();
+        }
+
+        this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
+    },
+
+    messagesClicked: function(event)
     {
         var link = event.target.firstParentOrSelfWithNodeName("a");
         if (link && link.representedNode) {
@@ -123,11 +339,14 @@ WebInspector.ConsolePanel.prototype = {
             return;
         }
 
-        var item = event.target.firstParentOrSelfWithNodeName("li");
-        if (!item)
+        var messageElement = event.target.firstParentOrSelfWithClass("console-message");
+        if (!messageElement)
+            return;
+
+        if (!messageElement.message)
             return;
 
-        var resource = item.message.resource;
+        var resource = messageElement.message.resource;
         if (!resource)
             return;
 
@@ -152,38 +371,122 @@ WebInspector.ConsolePanel.prototype = {
             case "Down":
                 this._onDownPressed(event);
                 break;
+            case "U+0009": // Tab
+                this._onTabPressed(event);
+                break;
+            case "Right":
+                if (!this.acceptAutoComplete())
+                    this.autoCompleteSoon();
+                break;
+            default:
+                this.clearAutoComplete();
+                this.autoCompleteSoon();
+                break;
         }
     },
 
+    _backwardsRange: function(stopCharacters, endNode, endOffset, stayWithinElement)
+    {
+        var startNode;
+        var startOffset = 0;
+        var node = endNode;
+
+        while (node) {
+            if (node === stayWithinElement) {
+                if (!startNode)
+                    startNode = stayWithinElement;
+                break;
+            }
+
+            if (node.nodeType === Node.TEXT_NODE) {
+                var start = (node === endNode ? endOffset : node.nodeValue.length);
+                for (var i = (start - 1); i >= 0; --i) {
+                    var character = node.nodeValue[i];
+                    if (stopCharacters.indexOf(character) !== -1) {
+                        startNode = node;
+                        startOffset = i + 1;
+                        break;
+                    }
+                }
+            }
+
+            if (startNode)
+                break;
+
+            node = node.traversePreviousNode();
+        }
+
+        var result = document.createRange();
+        result.setStart(startNode, startOffset);
+        result.setEnd(endNode, endOffset);
+
+        return result;
+    },
+
+    _evalInInspectedWindow: function(expression)
+    {
+        // This with block is needed to work around http://bugs.webkit.org/show_bug.cgi?id=11399
+        with (InspectorController.inspectedWindow()) {
+            return eval(expression);
+        }
+    },
+
+    _caretInsidePrompt: function()
+    {
+        var selection = window.getSelection();
+        if (!selection.rangeCount || !selection.isCollapsed)
+            return false;
+        var selectionRange = selection.getRangeAt(0);
+        return selectionRange.startContainer === this.promptElement && selectionRange.startContainer.isDescendant(this.promptElement);
+    },
+
+    _moveCaretToEndOfPrompt: function()
+    {
+        var selection = window.getSelection();
+        var selectionRange = document.createRange();
+
+        var offset = this.promptElement.firstChild ? 1 : 0;
+        selectionRange.setStart(this.promptElement, offset);
+        selectionRange.setEnd(this.promptElement, offset);
+
+        selection.removeAllRanges();
+        selection.addRange(selectionRange);
+    },
+
+    _onTabPressed: function(event)
+    {
+        event.preventDefault();
+        event.stopPropagation();
+        this.complete();
+    },
+
     _onEnterPressed: function(event)
     {
         event.preventDefault();
         event.stopPropagation();
 
-        var str = this.consolePrompt.value;
+        this.clearAutoComplete(true);
+
+        var str = this.promptText;
         if (!str.length)
             return;
 
         this.commandHistory.push(str);
         this.commandOffset = 0;
 
-        this.consolePrompt.value = "";
+        this.promptText = "";
 
         var result;
         var exception = false;
         try {
-            // This with block is needed to work around http://bugs.webkit.org/show_bug.cgi?id=11399
-            with (InspectorController.inspectedWindow()) {
-                result = eval(str);
-            }
+            result = this._evalInInspectedWindow(str);
         } catch(e) {
             result = e;
             exception = true;
         }
 
         var level = exception ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log;
-
-        this.addMessage(new WebInspector.ConsoleCommand(str, this._format(result)));
+        this.addMessage(new WebInspector.ConsoleCommand(str, result, this._format(result), level));
     },
 
     _onUpPressed: function(event)
@@ -195,11 +498,10 @@ WebInspector.ConsolePanel.prototype = {
             return;
 
         if (this.commandOffset == 0)
-            this.tempSavedCommand = this.consolePrompt.value;
+            this.tempSavedCommand = this.promptText;
 
         ++this.commandOffset;
-        this.consolePrompt.value = this.commandHistory[this.commandHistory.length - this.commandOffset];
-        this.consolePrompt.moveCursorToEnd();
+        this.promptText = this.commandHistory[this.commandHistory.length - this.commandOffset];
     },
 
     _onDownPressed: function(event)
@@ -213,14 +515,12 @@ WebInspector.ConsolePanel.prototype = {
         --this.commandOffset;
 
         if (this.commandOffset == 0) {
-            this.consolePrompt.value = this.tempSavedCommand;
-            this.consolePrompt.moveCursorToEnd();
+            this.promptText = this.tempSavedCommand;
             delete this.tempSavedCommand;
             return;
         }
 
-        this.consolePrompt.value = this.commandHistory[this.commandHistory.length - this.commandOffset];
-        this.consolePrompt.moveCursorToEnd();
+        this.promptText = this.commandHistory[this.commandHistory.length - this.commandOffset];
     },
 
     _format: function(output)
@@ -319,46 +619,50 @@ WebInspector.ConsoleMessage.prototype = {
         return this.url;
     },
 
-    toListItem: function()
+    toMessageElement: function()
     {
-        var item = document.createElement("li");
-        item.className = "console-message";
+        var element = document.createElement("div");
+        element.message = this;
+        element.className = "console-message";
+
         switch (this.source) {
             case WebInspector.ConsoleMessage.MessageSource.HTML:
-                item.className += " console-html-source";
+                element.addStyleClass("console-html-source");
                 break;
             case WebInspector.ConsoleMessage.MessageSource.XML:
-                item.className += " console-xml-source";
+                element.addStyleClass("console-xml-source");
                 break;
             case WebInspector.ConsoleMessage.MessageSource.JS:
-                item.className += " console-js-source";
+                element.addStyleClass("console-js-source");
                 break;
             case WebInspector.ConsoleMessage.MessageSource.CSS:
-                item.className += " console-css-source";
+                element.addStyleClass("console-css-source");
                 break;
             case WebInspector.ConsoleMessage.MessageSource.Other:
-                item.className += " console-other-source";
+                element.addStyleClass("console-other-source");
                 break;
         }
 
         switch (this.level) {
             case WebInspector.ConsoleMessage.MessageLevel.Tip:
-                item.className += " console-tip-level";
+                element.addStyleClass("console-tip-level");
                 break;
             case WebInspector.ConsoleMessage.MessageLevel.Log:
-                item.className += " console-log-level";
+                element.addStyleClass("console-log-level");
                 break;
             case WebInspector.ConsoleMessage.MessageLevel.Warning:
-                item.className += " console-warning-level";
+                element.addStyleClass("console-warning-level");
                 break;
             case WebInspector.ConsoleMessage.MessageLevel.Error:
-                item.className += " console-error-level";
+                element.addStyleClass("console-error-level");
         }
 
-        var messageDiv = document.createElement("div");
-        messageDiv.className = "console-message-message";
-        messageDiv.textContent = this.message;
-        item.appendChild(messageDiv);
+        var messageTextElement = document.createElement("span");
+        messageTextElement.className = "console-message-text";
+        messageTextElement.textContent = this.message;
+        element.appendChild(messageTextElement);
+
+        element.appendChild(document.createTextNode(" "));
 
         if (this.url && this.url !== "undefined") {
             var urlElement = document.createElement("a");
@@ -369,10 +673,10 @@ WebInspector.ConsoleMessage.prototype = {
             else
                 urlElement.textContent = this.url;
 
-            item.appendChild(urlElement);
+            element.appendChild(urlElement);
         }
 
-        return item;
+        return element;
     },
 
     toString: function()
@@ -423,37 +727,54 @@ WebInspector.ConsoleMessage.MessageSource = {
     JS: 2,
     CSS: 3,
     Other: 4,
-};
+}
 
 WebInspector.ConsoleMessage.MessageLevel = {
     Tip: 0,
     Log: 1,
     Warning: 2,
-    Error: 3,
-};
+    Error: 3
+}
 
-WebInspector.ConsoleCommand = function(input, output)
+WebInspector.ConsoleCommand = function(command, result, formattedResultElement, level)
 {
-    this.input = input;
-    this.output = output;
+    this.command = command;
+    this.formattedResultElement = formattedResultElement;
+    this.level = level;
 }
 
 WebInspector.ConsoleCommand.prototype = {
-    toListItem: function()
+    toMessageElement: function()
     {
-        var item = document.createElement("li");
-        item.className = "console-command";
+        var element = document.createElement("div");
+        element.command = this;
+        element.className = "console-user-command";
+
+        var commandTextElement = document.createElement("span");
+        commandTextElement.className = "console-message-text";
+        commandTextElement.textContent = this.command;
+        element.appendChild(commandTextElement);
 
-        var inputDiv = document.createElement("div");
-        inputDiv.className = "console-command-input";
-        inputDiv.textContent = this.input;
-        item.appendChild(inputDiv);
+        var resultElement = document.createElement("div");
+        resultElement.className = "console-message";
+        element.appendChild(resultElement);
+
+        switch (this.level) {
+            case WebInspector.ConsoleMessage.MessageLevel.Log:
+                resultElement.addStyleClass("console-log-level");
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Warning:
+                resultElement.addStyleClass("console-warning-level");
+                break;
+            case WebInspector.ConsoleMessage.MessageLevel.Error:
+                resultElement.addStyleClass("console-error-level");
+        }
 
-        var outputDiv = document.createElement("div");
-        outputDiv.className = "console-command-output";
-        outputDiv.appendChild(this.output);
-        item.appendChild(outputDiv);
+        var resultTextElement = document.createElement("span");
+        resultTextElement.className = "console-message-text";
+        resultTextElement.appendChild(this.formattedResultElement);
+        resultElement.appendChild(resultTextElement);
 
-        return item;
+        return element;
     }
 }
index d6ec461..c697263 100644 (file)
Binary files a/WebCore/page/inspector/Images/errorIcon.png and b/WebCore/page/inspector/Images/errorIcon.png differ
diff --git a/WebCore/page/inspector/Images/userInputIcon.png b/WebCore/page/inspector/Images/userInputIcon.png
new file mode 100644 (file)
index 0000000..325023f
Binary files /dev/null and b/WebCore/page/inspector/Images/userInputIcon.png differ
diff --git a/WebCore/page/inspector/Images/userInputPreviousIcon.png b/WebCore/page/inspector/Images/userInputPreviousIcon.png
new file mode 100644 (file)
index 0000000..068d572
Binary files /dev/null and b/WebCore/page/inspector/Images/userInputPreviousIcon.png differ
index f37727e..d5e4c82 100644 (file)
Binary files a/WebCore/page/inspector/Images/warningIcon.png and b/WebCore/page/inspector/Images/warningIcon.png differ
index ed560fc..a3b3080 100644 (file)
@@ -1501,53 +1501,81 @@ body:not(.inactive) .focused .outline-disclosure li.selected * {
     text-align: center;
 }
 
-.console-message-list {
-    list-style: none;
-    margin: 0;
-    padding: 0;
+#console-messages {
     position: absolute;
     top: 0;
-    bottom: 20px;
     left: 0;
     right: 0;
-    overflow: auto;
+    bottom: 0;
+    font-size: 10px;
+    font-family: Monaco, Lucida Console, monospace;
+    padding: 2px 0;
+    overflow-y: overlay;
     -webkit-user-select: text;
-    cursor: auto;
+    -webkit-text-size-adjust: auto;
 }
 
-.console-prompt {
-    font-family: monospace;
-    font-size: 11px;
-    margin: 0;
-    padding: 2px 0 0;
-    position: absolute;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    height: 18px;
-    resize: none;
+#console-prompt {
+    position: relative;
     outline: none;
-    border: none;
-    border-top: 1px solid rgb(64%, 64%, 64%);
+    padding: 1px 22px 1px 24px;
+    min-height: 16px; 
+    white-space: pre-wrap;
+    -webkit-user-modify: read-write-plaintext-only;
 }
 
-.console-message, .console-command {
-    font-size: 10px;
-    margin: 0;
-    padding: 3px 3px 3px 24px;
-    border-bottom: 1px solid rgb(75%, 75%, 75%);
-    word-break: break-word;
+#console-prompt::before {
+    background-image: url(Images/userInputIcon.png);
+}
+
+.console-message, .console-user-command {
     position: relative;
+    border-bottom: 1px solid rgb(240, 240, 240);
+    padding: 1px 22px 1px 24px;
+    min-height: 16px; 
+    white-space: pre-wrap;
 }
 
-.console-command a:hover {
-    text-decoration: underline;
-    cursor: pointer;
+.console-message::before, .console-user-command::before, #console-prompt::before {
+    position: absolute;
+    display: block;
+    content: "";
+    left: 7px;
+    top: 0.8em;
+    width: 10px;
+    height: 10px;
+    margin-top: -5px;
+    -webkit-user-select: none;
 }
 
-.console-message-message {
-    font-size: 11px;
-    white-space: pre-wrap;
+.console-message-text {
+//    vertical-align: middle;
+}
+
+.console-error-level .console-message-text {
+    color: red;
+}
+
+.console-error-level::before {
+    background-image: url(Images/errorIcon.png);
+}
+
+.console-warning-level::before {
+    background-image: url(Images/warningIcon.png);
+}
+
+.console-user-command .console-message {
+    margin-left: -24px;
+    padding-right: 0;
+    border-bottom: none;
+}
+
+.console-user-command::before {
+    background-image: url(Images/userInputPreviousIcon.png);
+}
+
+.console-user-command > .console-message-text {
+    color: rgb(0, 128, 255);
 }
 
 .console-message-url {
@@ -1556,12 +1584,13 @@ body:not(.inactive) .focused .outline-disclosure li.selected * {
 }
 
 .console-message-url::after {
+    display: inline-block;
     content: url(Images/goArrow.png);
     margin-left: 3px;
     width: 12px;
     height: 12px;
-    vertical-align: middle;
     opacity: 0.75;
+    vertical-align: top;
     -webkit-user-select: none;
 }
 
@@ -1573,36 +1602,10 @@ body:not(.inactive) .focused .outline-disclosure li.selected * {
     opacity: 1;
 }
 
-.console-error-level::before {
-    content: url(Images/errorMediumIcon.png);
-    position: absolute;
-    left: 5px;
-    top: 2px;
-    -webkit-user-select: none;
-}
-
-.console-warning-level::before {
-    content: url(Images/warningMediumIcon.png);
-    position: absolute;
-    left: 4px;
-    top: 2px;
-    -webkit-user-select: none;
-}
-
-.console-command-input, .console-command-output {
-    font-size: 11px;
-    white-space: pre-wrap;
-}
-
-.console-command-input::before {
-    content: ">";
-    font-weight: bold;
-    font-size: 15px;
-    color: blue;
-    position: absolute;
-    left: 8px;
-    top: 1px;
+.auto-complete-text {
+    color: rgb(128, 128, 128);
     -webkit-user-select: none;
+    -webkit-user-modify: read-only;
 }
 
 .view-button-browse img {