Changeset 54110 in webkit
- Timestamp:
- Jan 31, 2010 8:36:39 AM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 1 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r54109 r54110 1 2010-01-31 Pavel Feldman <pfeldman@chromium.org> 2 3 Reviewed by Timothy Hatcher. 4 5 Web Inspector: Introduce NativeTextViewer. 6 7 This change handles rendering highlighted text, using browser's 8 selection/drag/drop/click logic. Breakpoint decorations and 9 program counter is working. 10 11 Todo: line numbers are painted 'under' the text when scrolling 12 horizontally, search is not yet implemented. 13 14 https://bugs.webkit.org/show_bug.cgi?id=34391 15 16 * WebCore.gypi: 17 * WebCore.vcproj/WebCore.vcproj: 18 * inspector/front-end/DivBasedTextViewer.js: Added. 19 (WebInspector.DivBasedTextViewer): 20 (WebInspector.DivBasedTextViewer.prototype._textChanged): 21 (WebInspector.DivBasedTextViewer.prototype._createLineDivs): 22 (WebInspector.DivBasedTextViewer.prototype._updatePreferredSize): 23 (WebInspector.DivBasedTextViewer.prototype._scroll): 24 (WebInspector.DivBasedTextViewer.prototype._registerMouseListeners): 25 (WebInspector.DivBasedTextViewer.prototype._registerKeyboardListeners): 26 (WebInspector.DivBasedTextViewer.prototype._registerClipboardListeners): 27 (WebInspector.DivBasedTextViewer.prototype._paintSelection): 28 (WebInspector.DivBasedTextViewer.prototype._positionDivDecoration): 29 (WebInspector.DivBasedTextViewer.prototype._mouseDown): 30 (WebInspector.DivBasedTextViewer.prototype._contextMenu): 31 (WebInspector.DivBasedTextViewer.prototype._caretForMouseEvent): 32 (WebInspector.DivBasedTextViewer.prototype._paintLine): 33 (WebInspector.DivBasedTextViewer.prototype._createSpan): 34 * inspector/front-end/Settings.js: 35 * inspector/front-end/SourceFrame.js: 36 (WebInspector.SourceFrame.prototype.clearMessages): 37 (WebInspector.SourceFrame.prototype.sizeToFitContentHeight): 38 (WebInspector.SourceFrame.prototype._createEditorIfNeeded): 39 (WebInspector.SourceFrame.prototype._addMessageToSource): 40 (WebInspector.SourceFrame.prototype.resize): 41 * inspector/front-end/TextEditor.js: 42 (WebInspector.TextEditor): 43 (WebInspector.TextEditor.prototype.setDivDecoration): 44 (WebInspector.TextEditor.prototype._registerMouseListeners): 45 (WebInspector.TextEditor.prototype._registerKeyboardListeners): 46 (WebInspector.TextEditor.prototype._registerClipboardListeners): 47 (WebInspector.TextEditor.prototype.reveal): 48 (WebInspector.TextEditor.prototype._textChanged): 49 (WebInspector.TextEditor.prototype.revalidateDecorationsAndPaint): 50 (WebInspector.TextEditor.prototype._updatePreferredSize): 51 (WebInspector.TextEditor.prototype.resize): 52 (WebInspector.TextEditor.prototype._paintLinesContinuation): 53 (WebInspector.TextEditor.prototype._paintLine): 54 (WebInspector.TextEditor.prototype._contextMenu): 55 (WebInspector.TextEditor.prototype._caretForMouseEvent): 56 (WebInspector.TextEditor.prototype._changeFont): 57 * inspector/front-end/TextEditorHighlighter.js: 58 (WebInspector.TextEditorHighlighter.prototype._lex): 59 * inspector/front-end/WebKit.qrc: 60 * inspector/front-end/inspector.html: 61 * inspector/front-end/textEditor.css: 62 1 63 2010-01-31 Benjamin Poulain <benjamin.poulain@nokia.com> 2 64 -
trunk/WebCore/WebCore.gypi
r54085 r54110 3717 3717 'inspector/front-end/KeyboardShortcut.js', 3718 3718 'inspector/front-end/MetricsSidebarPane.js', 3719 'inspector/front-end/NativeTextViewer.js', 3719 3720 'inspector/front-end/Object.js', 3720 3721 'inspector/front-end/ObjectProxy.js', -
trunk/WebCore/WebCore.vcproj/WebCore.vcproj
r54053 r54110 42817 42817 </File> 42818 42818 <File 42819 RelativePath="..\inspector\front-end\NativeTextViewer.js" 42820 > 42821 </File> 42822 <File 42819 42823 RelativePath="..\inspector\front-end\Object.js" 42820 42824 > -
trunk/WebCore/inspector/front-end/Settings.js
r53794 r54110 39 39 showMissingLocalizedStrings: false, 40 40 samplingCPUProfiler: false, 41 showColorNicknames: true 41 showColorNicknames: true, 42 useCanvasBasedEditor: true 42 43 } 43 44 -
trunk/WebCore/inspector/front-end/SourceFrame.js
r54052 r54110 115 115 this._messageBubbles = {}; 116 116 if (this._editor) 117 this._editor. packAndRepaintAll();117 this._editor.revalidateDecorationsAndPaint(); 118 118 }, 119 119 … … 121 121 { 122 122 if (this._editor) 123 this._editor. packAndRepaintAll();123 this._editor.revalidateDecorationsAndPaint(); 124 124 }, 125 125 … … 137 137 return; 138 138 139 this._editor = new WebInspector.TextEditor(this._textModel, WebInspector.platform); 139 var editorConstructor = Preferences.useCanvasBasedEditor ? WebInspector.TextEditor : WebInspector.NativeTextViewer; 140 this._editor = new editorConstructor(this._textModel, WebInspector.platform); 140 141 this._editor.lineNumberDecorator = new WebInspector.BreakpointLineNumberDecorator(this, this._editor.textModel); 141 142 this._editor.lineDecorator = new WebInspector.ExecutionLineDecorator(this); … … 151 152 152 153 this._editor.setCoalescingUpdate(true); 153 this._editor. updateCanvasSize();154 this._editor. packAndRepaintAll();154 this._editor.resize(); 155 this._editor.revalidateDecorationsAndPaint(); 155 156 156 157 if (this._executionLine) … … 273 274 if (rowMessages[i].isEqual(msg, true)) { 274 275 this._incrementMessageRepeatCount(rowMessages[i], msg.repeatDelta); 275 this._editor. packAndRepaintAll();276 this._editor.revalidateDecorationsAndPaint(); 276 277 return; 277 278 } … … 305 306 msg._resourceMessageLineElement = messageLineElement; 306 307 307 this._editor. packAndRepaintAll();308 this._editor.revalidateDecorationsAndPaint(); 308 309 }, 309 310 … … 462 463 { 463 464 if (this._editor) 464 this._editor. updateCanvasSize();465 this._editor.resize(); 465 466 } 466 467 } -
trunk/WebCore/inspector/front-end/TextEditor.js
r54059 r54110 37 37 this.element = document.createElement("div"); 38 38 this.element.className = "text-editor"; 39 this.element.tabIndex = 0;40 39 41 40 this._canvas = document.createElement("canvas"); … … 45 44 this._container = document.createElement("div"); 46 45 this._container.className = "text-editor-container"; 46 this._container.tabIndex = 0; 47 47 this.element.appendChild(this._container); 48 48 49 49 this._sheet = document.createElement("div"); 50 this._sheet.className = "text-editor-sheet";51 50 this._container.appendChild(this._sheet); 52 51 … … 57 56 58 57 this._container.addEventListener("scroll", this._scroll.bind(this), false); 59 this._sheet.addEventListener("mouseup", this._mouseUp.bind(this), false);60 this._sheet.addEventListener("mousedown", this._mouseDown.bind(this), false);61 this._sheet.addEventListener("mousemove", this._mouseMove.bind(this), false);62 this._sheet.addEventListener("mouseout", this._mouseOut.bind(this), false);63 this._sheet.addEventListener("dblclick", this._dblClick.bind(this), false);64 58 this._sheet.addEventListener("contextmenu", this._contextMenu.bind(this), false); 65 this.element.addEventListener("keydown", this._keyDown.bind(this), false); 66 this.element.addEventListener("textInput", this._textInput.bind(this), false); 67 this.element.addEventListener("beforecopy", this._beforeCopy.bind(this), false); 68 this.element.addEventListener("copy", this._copy.bind(this), false); 69 this.element.addEventListener("beforecut", this._beforeCut.bind(this), false); 70 this.element.addEventListener("cut", this._cut.bind(this), false); 71 this.element.addEventListener("beforepaste", this._beforePaste.bind(this), false); 72 this.element.addEventListener("paste", this._paste.bind(this), false); 59 60 this._registerMouseListeners(); 61 this._registerKeyboardListeners(); 62 this._registerClipboardListeners(); 73 63 74 64 this._desiredCaretColumn = 0; … … 149 139 setDivDecoration: function(lineNumber, element) 150 140 { 151 var divDecoration= this._textModel.getAttribute(lineNumber, "div-decoration");152 if ( divDecoration && divDecoration.element && divDecoration.element.parentNode)153 divDecoration.element.parentNode.removeChild(divDecoration.element);141 var existingElement = this._textModel.getAttribute(lineNumber, "div-decoration"); 142 if (existingElement && existingElement.parentNode) 143 existingElement.parentNode.removeChild(existingElement); 154 144 this._textModel.removeAttribute(lineNumber, "div-decoration"); 155 145 156 146 if (element) { 157 divDecoration = { element: element };158 147 this.element.appendChild(element); 159 160 this._textModel.setAttribute(lineNumber, "div-decoration", divDecoration); 161 } 162 163 this.packAndRepaintAll(); 148 this._textModel.setAttribute(lineNumber, "div-decoration", element); 149 } 150 this.revalidateDecorationsAndPaint(); 151 }, 152 153 _registerMouseListeners: function() 154 { 155 this._sheet.addEventListener("mouseup", this._mouseUp.bind(this), false); 156 this._sheet.addEventListener("mousedown", this._mouseDown.bind(this), false); 157 this._sheet.addEventListener("mousemove", this._mouseMove.bind(this), false); 158 this._sheet.addEventListener("mouseout", this._mouseOut.bind(this), false); 159 this._sheet.addEventListener("dblclick", this._dblClick.bind(this), false); 160 }, 161 162 _registerKeyboardListeners: function() 163 { 164 this._container.addEventListener("keydown", this._keyDown.bind(this), false); 165 this._container.addEventListener("textInput", this._textInput.bind(this), false); 166 }, 167 168 _registerClipboardListeners: function() 169 { 170 this._container.addEventListener("beforecopy", this._beforeCopy.bind(this), false); 171 this._container.addEventListener("copy", this._copy.bind(this), false); 172 this._container.addEventListener("beforecut", this._beforeCut.bind(this), false); 173 this._container.addEventListener("cut", this._cut.bind(this), false); 174 this._container.addEventListener("beforepaste", this._beforePaste.bind(this), false); 175 this._container.addEventListener("paste", this._paste.bind(this), false); 164 176 }, 165 177 … … 206 218 _lineHeight: function(lineNumber) 207 219 { 208 var divDecoration= this._textModel.getAttribute(lineNumber, "div-decoration");209 if ( divDecoration)210 return 2 * this._textLineHeight + divDecoration.element.clientHeight;220 var element = this._textModel.getAttribute(lineNumber, "div-decoration"); 221 if (element) 222 return 2 * this._textLineHeight + element.clientHeight; 211 223 return this._textLineHeight; 212 224 }, 213 225 214 reveal: function(line, column) { 226 reveal: function(line, column) 227 { 215 228 var maxScrollTop = this._lineToOffset(line); 216 229 var minScrollTop = maxScrollTop + this._lineHeight(line) - this._canvas.height; … … 243 256 } 244 257 245 this._update Size(newRange.startLine, Math.max(newRange.endLine, oldRange.endLine));258 this._updatePreferredSize(newRange.startLine, Math.max(newRange.endLine, oldRange.endLine)); 246 259 if (oldRange.linesCount !== newRange.linesCount) { 247 260 // Invalidate offset cache. … … 276 289 }, 277 290 278 packAndRepaintAll: function()291 revalidateDecorationsAndPaint: function() 279 292 { 280 293 this.setCoalescingUpdate(true); 281 294 this._lineOffsetsCache = [0]; 282 this._update Size(0, this._textModel.linesCount);295 this._updatePreferredSize(0, this._textModel.linesCount); 283 296 this.repaintAll(); 284 297 this.setCoalescingUpdate(false); 285 298 }, 286 299 287 _updateSize: function(startLine, endLine) 288 { 300 _updatePreferredSize: function(startLine, endLine) 301 { 302 this._ctx.font = this._font; 289 303 this.setCoalescingUpdate(true); 290 304 var guardedEndLine = Math.min(this._textModel.linesCount, endLine + 1); … … 325 339 326 340 // Changes to size can change the client area (scrollers can appear/disappear) 327 this. updateCanvasSize();341 this.resize(); 328 342 this.setCoalescingUpdate(false); 329 343 }, 330 344 331 updateCanvasSize: function()345 resize: function() 332 346 { 333 347 if (this._canvas.width !== this._container.clientWidth || this._canvas.height !== this._container.clientHeight) { … … 427 441 } 428 442 for (var i = firstLine; i < lastLine; ++i) { 429 var line = this._textModel.line(i);430 443 var lineOffset = this._lineToOffset(i) - this._scrollTop; 431 444 … … 433 446 this._lineDecorator.decorate(i, this._ctx, this._lineNumberWidth - 1, lineOffset, this._canvas.width - this._lineNumberWidth + 1, this._lineHeight(i), this._textLineHeight); 434 447 435 var divDecoration = this._textModel.getAttribute(i, "div-decoration"); 436 if (divDecoration) 437 this._positionDivDecoration(i, divDecoration, true); 438 439 if (!this._highlightingEnabled) { 440 this._ctx.fillStyle = "rgb(0,0,0)"; 441 this._ctx.fillText(line, this._lineNumberWidth - this._scrollLeft, lineOffset + this._textLineHeight); 448 var element = this._textModel.getAttribute(i, "div-decoration"); 449 if (element) 450 this._positionDivDecoration(i, element, true); 451 452 this._paintLine(i, lineOffset); 453 } 454 this._ctx.restore(); 455 }, 456 457 _paintLine: function(lineNumber, lineOffset) 458 { 459 var line = this._textModel.line(lineNumber); 460 if (!this._highlightingEnabled) { 461 this._ctx.fillStyle = "rgb(0,0,0)"; 462 this._ctx.fillText(line, this._lineNumberWidth - this._scrollLeft, lineOffset + this._textLineHeight); 463 return; 464 } 465 466 if (line.length > 1000) { 467 // Optimization: no need to paint decorations outside visible area. 468 var firstColumn = this._columnForOffset(lineNumber, this._scrollLeft); 469 var lastColumn = this._columnForOffset(lineNumber, this._scrollLeft + this._canvas.width); 470 } 471 var highlighterState = this._textModel.getAttribute(lineNumber, "highlighter-state"); 472 var plainTextStart = -1; 473 for (var j = 0; j < line.length;) { 474 var attribute = highlighterState && highlighterState.attributes[j]; 475 if (attribute && firstColumn && j + attribute.length < firstColumn) { 476 j += attribute.length; 442 477 continue; 443 478 } 444 445 if (line.length > 1000) { 446 // Optimization: no need to paint decorations outside visible area. 447 var firstColumn = this._columnForOffset(i, this._scrollLeft); 448 var lastColumn = this._columnForOffset(i, this._scrollLeft + this._canvas.width); 479 if (attribute && lastColumn && j > lastColumn) 480 break; 481 if (!attribute || !attribute.style) { 482 if (plainTextStart === -1) 483 plainTextStart = j; 484 j++; 485 } else { 486 if (plainTextStart !== -1) { 487 this._ctx.fillStyle = "rgb(0,0,0)"; 488 this._ctx.fillText(line.substring(plainTextStart, j), this._lineNumberWidth - this._scrollLeft + this._columnToOffset(lineNumber, plainTextStart), lineOffset + this._textLineHeight); 489 plainTextStart = -1; 490 } 491 this._ctx.fillStyle = attribute.style; 492 this._ctx.fillText(line.substring(j, j + attribute.length), this._lineNumberWidth - this._scrollLeft + this._columnToOffset(lineNumber, j), lineOffset + this._textLineHeight); 493 j += attribute.length; 449 494 } 450 var highlighterState = this._textModel.getAttribute(i, "highlighter-state"); 451 var plainTextStart = -1; 452 for (var j = 0; j < line.length;) { 453 var attribute = highlighterState && highlighterState.attributes[j]; 454 if (attribute && firstColumn && j + attribute.length < firstColumn) { 455 j += attribute.length; 456 continue; 457 } 458 if (attribute && lastColumn && j > lastColumn) 459 break; 460 if (!attribute || !attribute.style) { 461 if (plainTextStart === -1) 462 plainTextStart = j; 463 j++; 464 } else { 465 if (plainTextStart !== -1) { 466 this._ctx.fillStyle = "rgb(0,0,0)"; 467 this._ctx.fillText(line.substring(plainTextStart, j), this._lineNumberWidth - this._scrollLeft + this._columnToOffset(i, plainTextStart), lineOffset + this._textLineHeight); 468 plainTextStart = -1; 469 } 470 this._ctx.fillStyle = attribute.style; 471 this._ctx.fillText(line.substring(j, j + attribute.length), this._lineNumberWidth - this._scrollLeft + this._columnToOffset(i, j), lineOffset + this._textLineHeight); 472 j += attribute.length; 473 } 474 } 475 if (plainTextStart !== -1) { 476 this._ctx.fillStyle = "rgb(0,0,0)"; 477 this._ctx.fillText(line.substring(plainTextStart, j), this._lineNumberWidth - this._scrollLeft + this._columnToOffset(i, plainTextStart), lineOffset + this._textLineHeight); 478 } 479 } 480 this._ctx.restore(); 495 } 496 if (plainTextStart !== -1) { 497 this._ctx.fillStyle = "rgb(0,0,0)"; 498 this._ctx.fillText(line.substring(plainTextStart, j), this._lineNumberWidth - this._scrollLeft + this._columnToOffset(lineNumber, plainTextStart), lineOffset + this._textLineHeight); 499 } 481 500 }, 482 501 … … 574 593 if (e.offsetX < this._lineNumberWidth && this._lineNumberDecorator) { 575 594 var location = this._caretForMouseEvent(e); 576 var line = location.line;577 595 if (this._lineNumberDecorator.contextMenu(location.line, e)) 578 596 return; … … 591 609 { 592 610 var lineNumber = Math.max(0, this._offsetToLine(e.offsetY) - 1); 593 var line = this._textModel.line(lineNumber);594 611 var offset = e.offsetX + this._scrollLeft - this._lineNumberWidth; 595 612 return { line: lineNumber, column: this._columnForOffset(lineNumber, offset) }; … … 794 811 var linesCount = this._textModel.linesCount; 795 812 for (var i = 0; i < linesCount; ++i) { 796 var divDecoration= this._textModel.getAttribute(i, "div-decoration");797 if ( divDecoration)798 this._positionDivDecoration(i, divDecoration, i > firstLine && i < lastLine);799 } 800 }, 801 802 _positionDivDecoration: function(lineNumber, divDecoration, visible)803 { 804 divDecoration.element.style.position = "absolute";805 divDecoration.element.style.top = this._lineToOffset(lineNumber) - this._scrollTop + this._textLineHeight + "px";806 divDecoration.element.style.left = this._lineNumberWidth + "px";807 divDecoration.element.style.setProperty("max-width", this._canvas.width + "px");813 var element = this._textModel.getAttribute(i, "div-decoration"); 814 if (element) 815 this._positionDivDecoration(i, element, i > firstLine && i < lastLine); 816 } 817 }, 818 819 _positionDivDecoration: function(lineNumber, element, visible) 820 { 821 element.style.position = "absolute"; 822 element.style.top = this._lineToOffset(lineNumber) - this._scrollTop + this._textLineHeight + "px"; 823 element.style.left = this._lineNumberWidth + "px"; 824 element.style.setProperty("max-width", this._canvas.width + "px"); 808 825 }, 809 826 … … 1073 1090 _changeFont: function(sansSerif, fontSize) { 1074 1091 this._initFont(sansSerif, fontSize); 1075 this._update Size(0, this._textModel.linesCount);1092 this._updatePreferredSize(0, this._textModel.linesCount); 1076 1093 this.repaintAll(); 1077 1094 }, -
trunk/WebCore/inspector/front-end/TextEditorHighlighter.js
r54053 r54110 189 189 var tokenType = this._tokenizer.tokenType; 190 190 if (tokenType) 191 attributes[column] = { length: newColumn - column, style: this._styles[tokenType] };191 attributes[column] = { length: newColumn - column, tokenType: tokenType, style: this._styles[tokenType] }; 192 192 column = newColumn; 193 193 } while (column < line.length) -
trunk/WebCore/inspector/front-end/WebKit.qrc
r54053 r54110 38 38 <file>KeyboardShortcut.js</file> 39 39 <file>MetricsSidebarPane.js</file> 40 <file>NativeTextViewer.js</file> 40 41 <file>Object.js</file> 41 42 <file>ObjectPropertiesSection.js</file> -
trunk/WebCore/inspector/front-end/inspector.css
r54068 r54110 3816 3816 3817 3817 .source-breakpoint-condition { 3818 position: absolute;3819 3818 z-index: 30; 3820 3819 padding: 4px; -
trunk/WebCore/inspector/front-end/inspector.html
r54053 r54110 98 98 <script type="text/javascript" src="TextEditor.js"></script> 99 99 <script type="text/javascript" src="TextEditorHighlighter.js"></script> 100 <script type="text/javascript" src="NativeTextViewer.js"></script> 100 101 <script type="text/javascript" src="SourceTokenizer.js"></script> 101 102 <script type="text/javascript" src="SourceCSSTokenizer.js"></script> -
trunk/WebCore/inspector/front-end/textEditor.css
r53941 r54110 45 45 } 46 46 47 .native-text-editor-line { 48 height: 14px; 49 white-space: pre; 50 } 51 47 52 .webkit-html-message-bubble { 48 53 -webkit-box-shadow: black 0px 2px 5px;
Note: See TracChangeset
for help on using the changeset viewer.