Changeset 185935 in webkit


Ignore:
Timestamp:
Jun 24, 2015 4:54:12 PM (9 years ago)
Author:
commit-queue@webkit.org
Message:

Web Inspector: Pressing tab in the styles sidebar shouldn't insert a tab character
https://bugs.webkit.org/show_bug.cgi?id=146189

Patch by Devin Rousso <Devin Rousso> on 2015-06-24
Reviewed by Timothy Hatcher.

  • UserInterface/Controllers/CodeMirrorCompletionController.js: Added variable to control whether semicolons are added to the end of autocompleted css values.

(WebInspector.CodeMirrorCompletionController):
(WebInspector.CodeMirrorCompletionController.prototype.set noEndingSemicolon):
(WebInspector.CodeMirrorCompletionController.prototype._generateCSSCompletions):

  • UserInterface/Views/CSSStyleDeclarationSection.js:

(WebInspector.CSSStyleDeclarationSection):
(WebInspector.CSSStyleDeclarationSection.prototype.cssStyleDeclarationTextEditorSwitchRule):
(WebInspector.CSSStyleDeclarationSection.prototype.focusRuleSelector):
(WebInspector.CSSStyleDeclarationSection.prototype.selectLastProperty):
(WebInspector.CSSStyleDeclarationSection.prototype.get selectorLocked):
(WebInspector.CSSStyleDeclarationSection.prototype.get locked):
(WebInspector.CSSStyleDeclarationSection.prototype._handleKeyDown):

  • UserInterface/Views/CSSStyleDeclarationTextEditor.js:

(WebInspector.CSSStyleDeclarationTextEditor): Added functions for "Tab", "Shift-Tab", and "Shift-Enter" keypresses to improve usability.
(WebInspector.CSSStyleDeclarationTextEditor.prototype.selectFirstProperty): Highlights the first property.
(WebInspector.CSSStyleDeclarationTextEditor.prototype.selectLastProperty): Highlights the last property.
(WebInspector.CSSStyleDeclarationTextEditor.prototype._insertNewlineAfterCurrentLine): Inserts a newline after the currently selected line.
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleShiftTabKey.switchRule):
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleShiftTabKey): Pressing shift-tab will move the cursor to the previous non-word character that is immediately after a word character.
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey.switchRule):
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey.highlightNextNameOrValue):
(WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey): Pressing tab will move the cursor to each space character until the end of the line is reached, at
which point the cursor will move to the beginning of the next line. Once the cursor is at the last line, pressing tab again will insert a newline.

  • UserInterface/Views/RulesStyleDetailsPanel.js:

(WebInspector.RulesStyleDetailsPanel.prototype.cssStyleDeclarationSectionEditorNextRule): Switches the focused rule to the next section.
(WebInspector.RulesStyleDetailsPanel.prototype.cssStyleDeclarationSectionEditorPrevRule): Switches the focused rule to the previous section.

Location:
trunk/Source/WebInspectorUI
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r185933 r185935  
     12015-06-24  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Pressing tab in the styles sidebar shouldn't insert a tab character
     4        https://bugs.webkit.org/show_bug.cgi?id=146189
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        * UserInterface/Controllers/CodeMirrorCompletionController.js: Added variable to control whether semicolons are added to the end of autocompleted css values.
     9        (WebInspector.CodeMirrorCompletionController):
     10        (WebInspector.CodeMirrorCompletionController.prototype.set noEndingSemicolon):
     11        (WebInspector.CodeMirrorCompletionController.prototype._generateCSSCompletions):
     12        * UserInterface/Views/CSSStyleDeclarationSection.js:
     13        (WebInspector.CSSStyleDeclarationSection):
     14        (WebInspector.CSSStyleDeclarationSection.prototype.cssStyleDeclarationTextEditorSwitchRule):
     15        (WebInspector.CSSStyleDeclarationSection.prototype.focusRuleSelector):
     16        (WebInspector.CSSStyleDeclarationSection.prototype.selectLastProperty):
     17        (WebInspector.CSSStyleDeclarationSection.prototype.get selectorLocked):
     18        (WebInspector.CSSStyleDeclarationSection.prototype.get locked):
     19        (WebInspector.CSSStyleDeclarationSection.prototype._handleKeyDown):
     20        * UserInterface/Views/CSSStyleDeclarationTextEditor.js:
     21        (WebInspector.CSSStyleDeclarationTextEditor): Added functions for "Tab", "Shift-Tab", and "Shift-Enter" keypresses to improve usability.
     22        (WebInspector.CSSStyleDeclarationTextEditor.prototype.selectFirstProperty): Highlights the first property.
     23        (WebInspector.CSSStyleDeclarationTextEditor.prototype.selectLastProperty): Highlights the last property.
     24        (WebInspector.CSSStyleDeclarationTextEditor.prototype._insertNewlineAfterCurrentLine): Inserts a newline after the currently selected line.
     25        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleShiftTabKey.switchRule):
     26        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleShiftTabKey): Pressing shift-tab will move the cursor to the previous non-word character that is immediately after a word character.
     27        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey.switchRule):
     28        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey.highlightNextNameOrValue):
     29        (WebInspector.CSSStyleDeclarationTextEditor.prototype._handleTabKey): Pressing tab will move the cursor to each space character until the end of the line is reached, at
     30        which point the cursor will move to the beginning of the next line.  Once the cursor is at the last line, pressing tab again will insert a newline.
     31        * UserInterface/Views/RulesStyleDetailsPanel.js:
     32        (WebInspector.RulesStyleDetailsPanel.prototype.cssStyleDeclarationSectionEditorNextRule): Switches the focused rule to the next section.
     33        (WebInspector.RulesStyleDetailsPanel.prototype.cssStyleDeclarationSectionEditorPrevRule): Switches the focused rule to the previous section.
     34
    1352015-06-24  Joseph Pecoraro  <pecoraro@apple.com>
    236
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/CodeMirrorCompletionController.js

    r182113 r185935  
    4040        this._lineNumber = NaN;
    4141        this._prefix = "";
     42        this._noEndingSemicolon = false;
    4243        this._completions = [];
    4344        this._extendedCompletionProviders = {};
     
    186187    }
    187188
     189    set noEndingSemicolon(noEndingSemicolon)
     190    {
     191        this._noEndingSemicolon = noEndingSemicolon;
     192    }
     193
    188194    // Private
    189195
     
    525531            // If there is a suffix and it isn't a semicolon, then we should use a space since
    526532            // the user is editing in the middle.
    527             this._implicitSuffix = suffix && suffix !== ";" ? " " : ";";
     533            this._implicitSuffix = suffix && suffix !== ";" ? " " : (this._noEndingSemicolon ? "" : ";");
    528534
    529535            // Don't use an implicit suffix if it would be the same as the existing suffix.
  • trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js

    r185784 r185935  
    5151    this._selectorElement.addEventListener("mouseover", this._highlightNodesWithSelector.bind(this));
    5252    this._selectorElement.addEventListener("mouseout", this._hideHighlightOnNodesWithSelector.bind(this));
     53    this._selectorElement.addEventListener("keydown", this._handleKeyDown.bind(this));
    5354    this._headerElement.appendChild(this._selectorElement);
    5455
     
    334335    },
    335336
     337    cssStyleDeclarationTextEditorSwitchRule: function(reverse)
     338    {
     339        if (!this._delegate)
     340            return;
     341
     342        if (reverse && typeof this._delegate.cssStyleDeclarationSectionEditorPreviousRule === "function")
     343            this._delegate.cssStyleDeclarationSectionEditorPreviousRule(this);
     344        else if (!reverse && typeof this._delegate.cssStyleDeclarationSectionEditorNextRule === "function")
     345            this._delegate.cssStyleDeclarationSectionEditorNextRule(this);
     346    },
     347
     348    focusRuleSelector: function(reverse)
     349    {
     350        if (this.selectorLocked) {
     351            this.focus();
     352            return;
     353        }
     354
     355        if (this.locked) {
     356            this.cssStyleDeclarationTextEditorSwitchRule(reverse);
     357            return;
     358        }
     359
     360        var selection = window.getSelection();
     361        selection.removeAllRanges();
     362
     363        this._element.scrollIntoViewIfNeeded();
     364
     365        var range = document.createRange();
     366        range.selectNodeContents(this._selectorElement);
     367        selection.addRange(range);
     368    },
     369
     370    selectLastProperty: function()
     371    {
     372        this._propertiesTextEditor.selectLastProperty();
     373    },
     374
     375    get selectorLocked()
     376    {
     377        return !this.locked && !this._style.ownerRule;
     378    },
     379
     380    get locked()
     381    {
     382        return !this._style.editable;
     383    },
     384
    336385    // Private
    337386
     
    419468    },
    420469
     470    _handleKeyDown: function(event)
     471    {
     472        if (event.keyCode !== 9)
     473            return;
     474
     475        if (event.shiftKey && this._delegate && typeof this._delegate.cssStyleDeclarationSectionEditorPreviousRule === "function") {
     476            event.preventDefault();
     477            this._delegate.cssStyleDeclarationSectionEditorPreviousRule(this, true);
     478            return;
     479        }
     480
     481        if (!event.metaKey) {
     482            event.preventDefault();
     483            this.focus();
     484            this._propertiesTextEditor.selectFirstProperty();
     485            return;
     486        }
     487    },
     488
    421489    _commitSelector: function(mutations)
    422490    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js

    r185928 r185935  
    5858        });
    5959
     60        this._codeMirror.addKeyMap({
     61            "Shift-Enter": this._insertNewlineAfterCurrentLine.bind(this),
     62            "Shift-Tab": this._handleShiftTabKey.bind(this),
     63            "Tab": this._handleTabKey.bind(this)
     64        });
     65
    6066        this._completionController = new WebInspector.CodeMirrorCompletionController(this._codeMirror, this);
    6167        this._tokenTrackingController = new WebInspector.CodeMirrorTokenTrackingController(this._codeMirror, this);
     68
     69        this._completionController.noEndingSemicolon = true;
    6270
    6371        this._jumpToSymbolTrackingModeEnabled = false;
     
    334342
    335343        return true;
     344    }
     345
     346    selectFirstProperty()
     347    {
     348        var line = this._codeMirror.getLine(0);
     349        var trimmedLine = line.trimRight();
     350
     351        if (!line || !trimmedLine.trimLeft().length)
     352            this.clearSelection();
     353
     354        var index = line.indexOf(":");
     355        this._codeMirror.setSelection({line: 0, ch: 0}, {line: 0, ch: index < 0 ? trimmedLine.length : index});
     356    }
     357
     358    selectLastProperty()
     359    {
     360        var line = this._codeMirror.lineCount() - 1;
     361        var lineText = this._codeMirror.getLine(line);
     362        var trimmedLine = lineText.trimRight();
     363
     364        var colon = /(?::\s*)/.exec(lineText);
     365        this._codeMirror.setSelection({line, ch: colon ? colon.index + colon[0].length : 0}, {line, ch: trimmedLine.length - trimmedLine.endsWith(";")});
    336366    }
    337367
     
    359389
    360390    // Private
     391
     392    _insertNewlineAfterCurrentLine(codeMirror)
     393    {
     394        var cursor = codeMirror.getCursor();
     395        var line = codeMirror.getLine(cursor.line);
     396        var trimmedLine = line.trimRight();
     397
     398        cursor.ch = trimmedLine.length;
     399
     400        if (cursor.ch) {
     401            codeMirror.replaceRange(trimmedLine.endsWith(";") ? "\n" : ";\n", cursor);
     402            return;
     403        }
     404
     405        return CodeMirror.Pass;
     406    }
     407
     408    _handleShiftTabKey(codeMirror)
     409    {
     410        function switchRule()
     411        {
     412            if (this._delegate && typeof this._delegate.cssStyleDeclarationTextEditorSwitchRule === "function") {
     413                this._delegate.cssStyleDeclarationTextEditorSwitchRule(true);
     414                return;
     415            }
     416
     417            return CodeMirror.Pass;
     418        }
     419
     420        var cursor = codeMirror.getCursor();
     421        var line = codeMirror.getLine(cursor.line);
     422        var previousLine = codeMirror.getLine(cursor.line - 1);
     423        var trimmedPreviousLine = previousLine ? previousLine.trimRight() : "";
     424
     425        if (!line && !previousLine && !cursor.line)
     426            return switchRule.call(this);
     427
     428        if (cursor.ch === line.indexOf(":") || line.indexOf(":") < 0) {
     429            if (previousLine) {
     430                var colon = /(?::\s*)/.exec(previousLine);
     431                codeMirror.setSelection({line: cursor.line - 1, ch: colon ? colon.index + colon[0].length : 0}, {line: cursor.line - 1, ch: trimmedPreviousLine.length - trimmedPreviousLine.endsWith(";")});
     432                return;
     433            }
     434
     435            if (cursor.line) {
     436                codeMirror.setCursor(cursor.line - 1, 0);
     437                return;
     438            }
     439
     440            return switchRule.call(this);
     441        }
     442
     443        var match = line.match(/(?:[^:;\s]\s*)+/g);
     444        var lastMatch = line.indexOf(match.lastValue) + match.lastValue.length;
     445        var prevHead = cursor.ch > lastMatch ? line.indexOf(match.lastValue) : line.indexOf(match[0]);
     446        var prevAnchor = cursor.ch > lastMatch ? lastMatch : line.indexOf(match[0]) + match[0].length;
     447
     448        codeMirror.setSelection({line: cursor.line, ch: prevHead}, {line: cursor.line, ch: prevAnchor});
     449    }
     450
     451    _handleTabKey(codeMirror)
     452    {
     453        function switchRule() {
     454            if (this._delegate && typeof this._delegate.cssStyleDeclarationTextEditorSwitchRule === "function") {
     455                this._delegate.cssStyleDeclarationTextEditorSwitchRule();
     456                return;
     457            }
     458
     459            return CodeMirror.Pass;
     460        }
     461
     462        function highlightNextNameOrValue(text)
     463        {
     464            var match = text.match(/(?:[^:;\s]\s*)+/g);
     465            var firstMatch = text.indexOf(match[0]) + match[0].length;
     466            var nextHead = cursor.ch < firstMatch ? text.indexOf(match[0]) : text.indexOf(match[1]);
     467            var nextAnchor = cursor.ch < firstMatch ? firstMatch : text.indexOf(match[1]) + match[1].length;
     468
     469            codeMirror.setSelection({line: cursor.line, ch: nextHead}, {line: cursor.line, ch: nextAnchor});
     470        }
     471
     472        var cursor = codeMirror.getCursor();
     473        var line = codeMirror.getLine(cursor.line);
     474        var trimmedLine = line.trimRight();
     475        var lastLine = cursor.line === codeMirror.lineCount() - 1;
     476        var nextLine = codeMirror.getLine(cursor.line + 1);
     477        var trimmedNextLine = nextLine ? nextLine.trimRight() : "";
     478
     479        if (!trimmedLine.trimLeft().length) {
     480            if (lastLine)
     481                return switchRule.call(this);
     482
     483            if (!trimmedNextLine.trimLeft().length) {
     484                codeMirror.setCursor(cursor.line + 1, 0);
     485                return;
     486            }
     487
     488            ++cursor.line;
     489            highlightNextNameOrValue(nextLine);
     490            return;
     491        }
     492
     493        if (trimmedLine.endsWith(":")) {
     494            codeMirror.setCursor(cursor.line, line.length);
     495            this._completionController._completeAtCurrentPosition(true);
     496            return;
     497        }
     498
     499        var hasEndingSemicolon = trimmedLine.endsWith(";");
     500
     501        if (cursor.ch >= line.trimRight().length - hasEndingSemicolon) {
     502            if (!line.includes(":")) {
     503                codeMirror.setCursor(cursor.line, line.length);
     504                codeMirror.replaceRange(": ", cursor);
     505                return;
     506            }
     507
     508            var replacement = "";
     509
     510            if (!hasEndingSemicolon)
     511                replacement += ";";
     512
     513            if (lastLine)
     514                replacement += "\n";
     515
     516            if (replacement.length)
     517                codeMirror.replaceRange(replacement, {line: cursor.line, ch: trimmedLine.length});
     518
     519            if (!nextLine) {
     520                codeMirror.setCursor(cursor.line + 1, 0);
     521                return;
     522            }
     523
     524            var colon = nextLine.indexOf(":");
     525            codeMirror.setSelection({line: cursor.line + 1, ch: 0}, {line: cursor.line + 1, ch: colon < 0 ? trimmedNextLine.length : colon});
     526            return;
     527        }
     528
     529        highlightNextNameOrValue(line);
     530    }
    361531
    362532    _clearRemoveEditingLineClassesTimeout()
  • trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js

    r185845 r185935  
    303303    }
    304304
     305    cssStyleDeclarationSectionEditorNextRule(currentSection)
     306    {
     307        currentSection.clearSelection();
     308
     309        var index = this._sections.indexOf(currentSection);
     310        this._sections[index < this._sections.length - 1 ? index + 1 : 0].focusRuleSelector();
     311    }
     312
     313    cssStyleDeclarationSectionEditorPreviousRule(currentSection, selectLastProperty) {
     314        currentSection.clearSelection();
     315
     316        if (selectLastProperty || currentSection.selectorLocked) {
     317            var index = this._sections.indexOf(currentSection);
     318            index = index > 0 ? index - 1 : this._sections.length - 1;
     319
     320            var section = this._sections[index];
     321            while (section.locked) {
     322                index = index > 0 ? index - 1 : this._sections.length - 1;
     323                section = this._sections[index];
     324            }
     325
     326            section.focus();
     327            section.selectLastProperty();
     328            return;
     329        }
     330
     331        currentSection.focusRuleSelector(true);
     332    }
     333
    305334    filterDidChange(filterBar)
    306335    {
Note: See TracChangeset for help on using the changeset viewer.