Changeset 53052 in webkit
- Timestamp:
- Jan 10, 2010 11:15:04 AM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r53051 r53052 1 2010-01-10 Pavel Feldman <pfeldman@chromium.org> 2 3 Reviewed by Timothy Hatcher. 4 5 Web Inspector: Introduce support for flexible line height in the text editor. 6 7 https://bugs.webkit.org/show_bug.cgi?id=33431 8 9 * inspector/front-end/TextEditor.js: 10 (WebInspector.TextEditor): 11 (WebInspector.TextEditor.prototype._offsetToLineNumber): 12 (WebInspector.TextEditor.prototype._lineNumberToOffset): 13 (WebInspector.TextEditor.prototype._lineHeight): 14 (WebInspector.TextEditor.prototype.reveal): 15 (WebInspector.TextEditor.prototype._textChanged): 16 (WebInspector.TextEditor.prototype._selectionChanged): 17 (WebInspector.TextEditor.prototype._updateSize): 18 (WebInspector.TextEditor.prototype._paintLines): 19 (WebInspector.TextEditor.prototype._paintLinesContinuation): 20 (WebInspector.TextEditor.prototype._paintLineNumbers): 21 (WebInspector.TextEditor.prototype._paintCurrentLine): 22 (WebInspector.TextEditor.prototype._scroll): 23 (WebInspector.TextEditor.prototype._repaintOnScroll): 24 (WebInspector.TextEditor.prototype._caretForMouseEvent): 25 (WebInspector.TextEditor.prototype._handleNavigationKey): 26 (WebInspector.TextEditor.prototype._updateCursor): 27 (WebInspector.TextEditor.prototype._invalidateHighlight): 28 (WebInspector.TextEditor.prototype._paintSelection): 29 (WebInspector.TextEditor.prototype._initFont): 30 (WebInspector.TextCursor.prototype.setTextLineHeight): 31 1 32 2010-01-10 Pavel Feldman <pfeldman@chromium.org> 2 33 -
trunk/WebCore/inspector/front-end/TextEditor.js
r53051 r53052 90 90 this._highlightingEnabled = true; 91 91 this._debugMode = false; 92 this._lineAlignmentOffset = 0;93 92 94 93 this._textWidth = 0; 95 94 this._longestLineNumber = 0; 95 96 this._lineOffsetsCache = [0]; 96 97 } 97 98 … … 112 113 }, 113 114 115 _offsetToLineNumber: function(offset) 116 { 117 if (offset > this._lineOffsetsCache[this._lineOffsetsCache.length - 1]) { 118 // Seeking outside cached area. Fill the cache. 119 var lineNumber = this._lineOffsetsCache.length; 120 while (this._lineNumberToOffset(lineNumber) < offset) 121 lineNumber++; 122 return lineNumber; 123 } 124 125 // Bisect. 126 var from = 0; 127 var to = this._lineOffsetsCache.length; 128 while (to > from + 1) { 129 var mid = Math.floor((from + to) / 2); 130 if (this._lineOffsetsCache[mid] > offset) 131 to = mid; 132 else 133 from = mid; 134 } 135 return to; 136 }, 137 138 _lineNumberToOffset: function(lineNumber) 139 { 140 var offset = this._lineOffsetsCache[lineNumber]; 141 if (offset) 142 return offset; 143 for (var line = lineNumber; line > 0; --line) { 144 if (this._lineOffsetsCache[line]) 145 break; 146 } 147 offset = this._lineOffsetsCache[line]; 148 for (var i = line + 1; i <= lineNumber; ++i) { 149 offset += this._lineHeight(i - 1); 150 this._lineOffsetsCache[i] = offset; 151 } 152 return offset; 153 }, 154 155 _lineHeight: function(lineNumber) 156 { 157 return this._debugMode ? this._textLineHeight * (1 + lineNumber % 3) : this._textLineHeight; 158 }, 159 114 160 reveal: function(line, column) { 115 var firstLine = this._scrollTop / this._lineHeight; 116 var visibleLines = this._canvas.height / this._lineHeight; 117 var minTop = (line - visibleLines + 1) * this._lineHeight; 118 var maxTop = line * this._lineHeight; 119 if (this._scrollTop < minTop) { 120 this._lineAlignmentOffset = this._canvas.height % this._lineHeight; 121 this._container.scrollTop = minTop; 122 } else if (this._scrollTop > maxTop) { 123 this._lineAlignmentOffset = 0; 124 this._container.scrollTop = maxTop; 125 } 161 var maxScrollTop = this._lineNumberToOffset(line); 162 var minScrollTop = maxScrollTop + this._lineHeight(line) - this._canvas.height; 163 if (this._scrollTop > maxScrollTop) 164 this._container.scrollTop = maxScrollTop; 165 else if (this._scrollTop < minScrollTop) 166 this._container.scrollTop = minScrollTop; 126 167 127 168 var firstColumn = this._columnForOffset(line, this._scrollLeft); 128 var max Left = this._columnToOffset(line, column);129 var min Left = maxLeft - this._container.clientWidth + this._lineNumberOffset;130 if (this._scrollLeft < min Left)131 this._container.scrollLeft = min Left + 100;132 if (this._scrollLeft > max Left)133 this._container.scrollLeft = max Left;169 var maxScrollLeft = this._columnToOffset(line, column); 170 var minScrollLeft = maxScrollLeft - this._container.clientWidth + this._lineNumberOffset; 171 if (this._scrollLeft < minScrollLeft) 172 this._container.scrollLeft = minScrollLeft + 100; 173 if (this._scrollLeft > maxScrollLeft) 174 this._container.scrollLeft = maxScrollLeft; 134 175 }, 135 176 … … 145 186 this._invalidateHighlight(newRange.startLine); 146 187 this._updateSize(newRange.startLine, Math.max(newRange.endLine, oldRange.endLine)); 147 if (oldRange.linesCount !== newRange.linesCount) 188 if (oldRange.linesCount !== newRange.linesCount) { 189 // Invalidate offset cache. 190 this._lineOffsetsCache.length = oldRange.startLine + 1; 191 // Force linenumber cache to be continuous. 192 this._lineNumberToOffset(oldRange.startLine); 148 193 this._paintLineNumbers(); 194 } 149 195 this._paint(); 150 196 }, … … 157 203 return; 158 204 } 205 159 206 this._invalidateLines(oldRange.startLine, oldRange.endLine + 1); 160 207 this._invalidateLines(newRange.startLine, newRange.endLine + 1); … … 191 238 192 239 this._sheet.style.width = this._textWidth + this._lineNumberOffset + "px"; 193 this._sheet.style.height = this._line Height * this._textModel.linesCount+ "px";240 this._sheet.style.height = this._lineNumberToOffset(this._textModel.linesCount) + "px"; 194 241 195 242 if (this._canvas.width !== this._container.clientWidth || this._canvas.height !== this._container.clientHeight || newLineNumberDigits !== this._lineNumberDigits) { … … 240 287 this._ctx.font = this._font; 241 288 this._ctx.textBaseline = "bottom"; 242 243 firstLine = Math.max(firstLine, Math.floor(this._scrollTop / this._lineHeight) - 1);244 lastLine = Math.min(lastLine, Math.ceil((this._scrollTop + this._canvas.height) / this._lineHeight) + 1);289 290 firstLine = Math.max(firstLine, this._offsetToLineNumber(this._scrollTop) - 1); 291 lastLine = Math.min(lastLine, this._offsetToLineNumber(this._scrollTop + this._canvas.height) + 1); 245 292 if (firstLine > lastLine) 246 293 return; … … 249 296 WebInspector.log("Repaint %d:%d", firstLine, lastLine); 250 297 this._ctx.fillStyle = "rgb(255,255,0)"; 251 var height = (lastLine - firstLine) * this._lineHeight; 252 this._ctx.fillRect(this._lineNumberOffset - 1, this._lineHeight * firstLine - this._scrollTop, this._canvas.width - this._lineNumberOffset + 1, height); 298 var fromOffset = this._lineNumberToOffset(firstLine); 299 var toOffset = this._lineNumberToOffset(lastLine); 300 this._ctx.fillRect(this._lineNumberOffset - 1, fromOffset - this._scrollTop, this._canvas.width - this._lineNumberOffset + 1, toOffset - fromOffset); 253 301 setTimeout(this._paintLinesContinuation.bind(this, firstLine, lastLine), 100); 254 302 } else … … 264 312 265 313 // First clear the region, then update last line to fit model (this clears removed lines from the end of the document). 266 var height = (lastLine - firstLine) * this._lineHeight; 314 var fromOffset = this._lineNumberToOffset(firstLine); 315 var toOffset = lastLine < this._textModel.linesCount ? this._lineNumberToOffset(lastLine) : this._canvas.height + this._scrollTop; 267 316 // Do not clear region when paintCurrentLine is likely to do all the necessary work. 268 317 if (firstLine + 1 != lastLine || this._selection.endLine != firstLine) { 269 318 this._ctx.fillStyle = "rgb(255,255,255)"; 270 this._ctx.fillRect(0, this._lineHeight * firstLine - this._scrollTop, this._canvas.width, height);319 this._ctx.fillRect(0, fromOffset - this._scrollTop, this._canvas.width, toOffset - fromOffset); 271 320 } 272 321 lastLine = Math.min(lastLine, this._textModel.linesCount); … … 282 331 for (var i = firstLine; i < lastLine; ++i) { 283 332 var line = this._textModel.line(i); 333 var lineOffset = this._lineNumberToOffset(i) + this._textLineHeight - this._scrollTop; 334 284 335 if (!this._highlightingEnabled) { 285 this._ctx.fillText(line, this._lineNumberOffset - this._scrollLeft, this._lineHeight * (i + 1) - this._scrollTop); 336 this._ctx.fillStyle = "rgb(0,0,0)"; 337 this._ctx.fillText(line, this._lineNumberOffset - this._scrollLeft, lineOffset); 286 338 continue; 287 339 } … … 298 350 if (plainTextStart !== -1) { 299 351 this._ctx.fillStyle = "rgb(0,0,0)"; 300 this._ctx.fillText(line.substring(plainTextStart, j), this._lineNumberOffset - this._scrollLeft + this._columnToOffset(i, plainTextStart), this._lineHeight * (i + 1) - this._scrollTop);352 this._ctx.fillText(line.substring(plainTextStart, j), this._lineNumberOffset - this._scrollLeft + this._columnToOffset(i, plainTextStart), lineOffset); 301 353 plainTextStart = -1; 302 354 } 303 355 this._ctx.fillStyle = attribute.style; 304 this._ctx.fillText(line.substring(j, j + attribute.length), this._lineNumberOffset - this._scrollLeft + this._columnToOffset(i, j), this._lineHeight * (i + 1) - this._scrollTop);356 this._ctx.fillText(line.substring(j, j + attribute.length), this._lineNumberOffset - this._scrollLeft + this._columnToOffset(i, j), lineOffset); 305 357 j += attribute.length; 306 358 } … … 308 360 if (plainTextStart !== -1) { 309 361 this._ctx.fillStyle = "rgb(0,0,0)"; 310 this._ctx.fillText(line.substring(plainTextStart, line.length), this._lineNumberOffset - this._scrollLeft + this._columnToOffset(i, plainTextStart), this._lineHeight * (i + 1) - this._scrollTop);362 this._ctx.fillText(line.substring(plainTextStart, line.length), this._lineNumberOffset - this._scrollLeft + this._columnToOffset(i, plainTextStart), lineOffset); 311 363 } 312 364 } … … 320 372 321 373 this._ctx.fillStyle = "rgb(255,255,255)"; 322 this._ctx.fillRect(0, 0, this._lineNumberOffset - 3, this._canvas.height);374 this._ctx.fillRect(0, 0, this._lineNumberOffset - 2, this._canvas.height); 323 375 324 376 this._ctx.fillStyle = "rgb(235,235,235)"; 325 377 this._ctx.fillRect(this._lineNumberOffset - 2, 0, 1, this._canvas.height); 326 378 327 var firstLine = Math.m in(this._textModel.linesCount, Math.floor(this._scrollTop / this._lineHeight) - 1);328 var lastLine = Math.min(this._textModel.linesCount, Math.ceil((this._scrollTop + this._canvas.height) / this._lineHeight) + 1);379 var firstLine = Math.max(0, this._offsetToLineNumber(this._scrollTop) - 1); 380 var lastLine = Math.min(this._textModel.linesCount, this._offsetToLineNumber(this._scrollTop + this._canvas.height) + 1); 329 381 330 382 this._ctx.fillStyle = "rgb(155,155,155)"; 331 383 for (var i = firstLine; i < lastLine; ++i) 332 this._ctx.fillText(i + 1, (this._lineNumberDigits - this._decimalDigits(i + 1) + 1) * this._digitWidth, this._line Height * (i + 1)- this._scrollTop);384 this._ctx.fillText(i + 1, (this._lineNumberDigits - this._decimalDigits(i + 1) + 1) * this._digitWidth, this._lineNumberToOffset(i) + this._textLineHeight - this._scrollTop); 333 385 }, 334 386 … … 336 388 { 337 389 this._ctx.fillStyle = "rgb(232, 242, 254)"; 338 this._ctx.fillRect(0, this._line Height * line - this._scrollTop, this._canvas.width, this._lineHeight);390 this._ctx.fillRect(0, this._lineNumberToOffset(line) - this._scrollTop, this._canvas.width, this._lineHeight(line)); 339 391 this._ctx.fillStyle = "rgb(0, 0, 0)"; 340 392 }, … … 342 394 _scroll: function(e) 343 395 { 344 if (this._muteScroll)345 return;346 347 if (this._container.scrollTop === 0)348 this._lineAlignmentOffset = 0;349 else if (this._container.scrollTop + this._container.clientHeight === this._textModel.linesCount * this._lineHeight)350 this._lineAlignmentOffset = this._container.scrollTop % this._lineHeight;351 352 // Enforce line alignment.353 if (this._container.scrollTop % this._lineHeight !== this._lineAlignmentOffset) {354 var linesOffset = Math.floor(this._container.scrollTop / this._lineHeight);355 this._muteScroll = true;356 this._container.scrollTop = linesOffset * this._lineHeight + this._lineAlignmentOffset;357 delete this._muteScroll;358 }359 360 396 // Hide div-based cursor first. 361 397 this._cursor._cursorElement.style.display = "none"; … … 365 401 _repaintOnScroll: function() 366 402 { 367 var linesOffset = Math.floor(this._container.scrollTop / this._lineHeight);368 403 if (this._scrollTop !== this._container.scrollTop || this._scrollLeft !== this._container.scrollLeft) { 369 404 this._scrollTop = this._container.scrollTop; … … 411 446 _caretForMouseEvent: function(e) 412 447 { 413 var lineNumber = Math. floor((e.y + this._scrollTop - 4) / this._lineHeight);448 var lineNumber = Math.max(0, this._offsetToLineNumber(e.y + this._scrollTop) - 1); 414 449 var line = this._textModel.line(lineNumber); 415 450 var offset = e.x + this._scrollLeft - this._lineNumberOffset - this._digitWidth; … … 485 520 arrowAction.call(this, 0, 0, true); 486 521 else if (e.ctrlKey) 487 this._container.scrollTop -= this._lineHeight ;522 this._container.scrollTop -= this._lineHeight(caretLine); 488 523 else { 489 var jump = e.keyCode === keyCodes.Up ? 1 : Math.floor(this._canvas.height / this._lineHeight); 490 arrowAction.call(this, caretLine - jump, this._desiredCaretColumn, true); 524 if (e.keyCode === keyCodes.Up) 525 arrowAction.call(this, caretLine - 1, this._desiredCaretColumn, true); 526 else { 527 var offset = Math.max(0, this._lineNumberToOffset(caretLine) - this._canvas.height); 528 arrowAction.call(this, this._offsetToLineNumber(offset), this._desiredCaretColumn, true); 529 } 491 530 } 492 531 break; … … 496 535 arrowAction.call(this, this._textModel.linesCount - 1, this._textModel.lineLength(this._textModel.linesCount - 1), true); 497 536 else if (e.ctrlKey) 498 this._container.scrollTop += this._lineHeight ;537 this._container.scrollTop += this._lineHeight(caretLine); 499 538 else { 500 var jump = e.keyCode === keyCodes.Down ? 1 : Math.floor(this._canvas.height / this._lineHeight); 501 arrowAction.call(this, caretLine + jump, this._desiredCaretColumn, true); 539 if (e.keyCode === keyCodes.Down) 540 arrowAction.call(this, caretLine + 1, this._desiredCaretColumn, true); 541 else { 542 var offset = this._lineNumberToOffset(caretLine) + this._canvas.height; 543 arrowAction.call(this, this._offsetToLineNumber(offset), this._desiredCaretColumn, true); 544 } 502 545 } 503 546 break; … … 575 618 var offset = this._columnToOffset(line, column); 576 619 if (offset >= this._container.scrollLeft) 577 this._cursor.setLocation(this._lineNumberOffset + offset - 1, line * this._lineHeight);620 this._cursor.setLocation(this._lineNumberOffset + offset - 1, this._lineNumberToOffset(line)); 578 621 else 579 622 this._cursor.setLocation(0, 0); … … 592 635 if (!this._highlightingEnabled) 593 636 return; 594 var firstVisibleLine = Math.max(0, Math.floor(this._scrollTop / this._lineHeight) - 1);595 var lastVisibleLine = Math.min(this._textModel.linesCount, Math.ceil(firstVisibleLine + this._canvas.height / this._lineHeight + 1));637 var firstVisibleLine = Math.max(0, this._offsetToLineNumber(this._scrollTop) - 1); 638 var lastVisibleLine = Math.min(this._textModel.linesCount, this._offsetToLineNumber(this._scrollTop + this._canvas.height) + 1); 596 639 597 640 var damage = this._highlighter.highlight(startLine, lastVisibleLine); … … 626 669 to = this._canvas.width; 627 670 628 this._ctx.fillRect(from, this._line Height * i - this._scrollTop, to - from, this._lineHeight);671 this._ctx.fillRect(from, this._lineNumberToOffset(i) - this._scrollTop, to - from, this._textLineHeight); 629 672 } 630 673 this._ctx.fillStyle = "rgb(0, 0, 0)"; … … 723 766 this._digitWidth = this._ctx.measureText("0").width; 724 767 725 this._ lineHeight = Math.floor(this._fontSize * 1.4);726 this._cursor.set LineHeight(this._lineHeight);768 this._textLineHeight = Math.floor(this._fontSize * 1.4); 769 this._cursor.setTextLineHeight(this._textLineHeight); 727 770 }, 728 771 … … 914 957 }, 915 958 916 set LineHeight: function(lineHeight)917 { 918 this._cursorElement.style.height = lineHeight + "px";959 setTextLineHeight: function(textLineHeight) 960 { 961 this._cursorElement.style.height = textLineHeight + "px"; 919 962 }, 920 963
Note: See TracChangeset
for help on using the changeset viewer.