From 6a403e441eb943454f2d1aba0a46dd965a168b28 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 18 Dec 2015 10:41:21 +0100 Subject: [PATCH] Start integrating tree-based LineTopIndex --- package.json | 1 + spec/lines-yardstick-spec.coffee | 2 +- spec/text-editor-presenter-spec.coffee | 2 +- src/block-decorations-presenter.js | 14 ++-- src/linear-line-top-index.js | 107 ------------------------- src/text-editor-component.coffee | 2 +- src/text-editor-presenter.coffee | 12 ++- 7 files changed, 18 insertions(+), 122 deletions(-) delete mode 100644 src/linear-line-top-index.js diff --git a/package.json b/package.json index 21e960477..63953b1b6 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "jquery": "^2.1.1", "key-path-helpers": "^0.4.0", "less-cache": "0.22", + "line-top-index": "0.1.0", "marked": "^0.3.4", "normalize-package-data": "^2.0.0", "nslog": "^3", diff --git a/spec/lines-yardstick-spec.coffee b/spec/lines-yardstick-spec.coffee index 0120b4ef4..ceae2a847 100644 --- a/spec/lines-yardstick-spec.coffee +++ b/spec/lines-yardstick-spec.coffee @@ -1,5 +1,5 @@ LinesYardstick = require '../src/lines-yardstick' -LineTopIndex = require '../src/linear-line-top-index' +LineTopIndex = require 'line-top-index' {toArray} = require 'underscore-plus' describe "LinesYardstick", -> diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 0014d8cce..9bd85c7a9 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -5,7 +5,7 @@ TextBuffer = require 'text-buffer' TextEditor = require '../src/text-editor' TextEditorPresenter = require '../src/text-editor-presenter' FakeLinesYardstick = require './fake-lines-yardstick' -LineTopIndex = require '../src/linear-line-top-index' +LineTopIndex = require 'line-top-index' describe "TextEditorPresenter", -> # These `describe` and `it` blocks mirror the structure of the ::state object. diff --git a/src/block-decorations-presenter.js b/src/block-decorations-presenter.js index 076cfea12..870d49dcd 100644 --- a/src/block-decorations-presenter.js +++ b/src/block-decorations-presenter.js @@ -29,10 +29,10 @@ class BlockDecorationsPresenter { observeModel () { this.disposables.add(this.model.onDidAddDecoration(this.didAddDecoration.bind(this))) - this.disposables.add(this.model.onDidChange((changeEvent) => { - let oldExtent = changeEvent.end - changeEvent.start - let newExtent = Math.max(0, changeEvent.end - changeEvent.start + changeEvent.screenDelta) - this.lineTopIndex.splice(changeEvent.start, oldExtent, newExtent) + this.disposables.add(this.model.buffer.onDidChange((changeEvent) => { + let oldExtent = changeEvent.oldRange.getExtent() + let newExtent = changeEvent.newRange.getExtent() + this.lineTopIndex.splice(changeEvent.oldRange.start, oldExtent, newExtent) })) for (let decoration of this.model.getDecorations({type: 'block'})) { @@ -79,8 +79,7 @@ class BlockDecorationsPresenter { this.didDestroyDecoration(decoration) }) - let screenRow = decoration.getMarker().getHeadScreenPosition().row - this.lineTopIndex.insertBlock(decoration.getId(), screenRow, 0) + this.lineTopIndex.insertBlock(decoration.getId(), decoration.getMarker().getHeadBufferPosition(), true, 0) this.observedDecorations.add(decoration) this.disposables.add(didMoveDisposable) @@ -94,8 +93,7 @@ class BlockDecorationsPresenter { return } - let newScreenRow = decoration.getMarker().getHeadScreenPosition().row - this.lineTopIndex.moveBlock(decoration.getId(), newScreenRow) + this.lineTopIndex.moveBlock(decoration.getId(), decoration.getMarker().getHeadBufferPosition()) this.emitter.emit('did-update-state') } diff --git a/src/linear-line-top-index.js b/src/linear-line-top-index.js deleted file mode 100644 index aad947dd8..000000000 --- a/src/linear-line-top-index.js +++ /dev/null @@ -1,107 +0,0 @@ -"use babel" - -export default class LineTopIndex { - constructor (params = {}) { - this.blocks = [] - this.maxRow = params.maxRow || 0 - this.setDefaultLineHeight(params.defaultLineHeight || 0) - } - - setDefaultLineHeight (lineHeight) { - this.defaultLineHeight = lineHeight - } - - getMaxRow () { - return this.maxRow - } - - insertBlock (id, row, height) { - this.blocks.push({id, row, height}) - this.blocks.sort((a, b) => a.row - b.row) - } - - resizeBlock (id, height) { - let block = this.blocks.find((block) => block.id === id) - if (block) { - block.height = height - } - } - - moveBlock (id, newRow) { - let block = this.blocks.find((block) => block.id === id) - if (block) { - block.row = newRow - this.blocks.sort((a, b) => a.row - b.row) - } - } - - removeBlock (id) { - let index = this.blocks.findIndex((block) => block.id === id) - if (index !== -1) { - this.blocks.splice(index, 1) - } - } - - allBlocks () { - return this.blocks - } - - blocksHeightForRow (row) { - let blocksForRow = this.blocks.filter((block) => block.row === row) - return blocksForRow.reduce((a, b) => a + b.height, 0) - } - - splice (startRow, oldExtent, newExtent) { - this.blocks.forEach(function (block) { - if (block.row >= startRow) { - if (block.row >= startRow + oldExtent) { - block.row += newExtent - oldExtent - } else { - block.row = startRow + newExtent - } - } - }) - - this.maxRow = this.maxRow + newExtent - oldExtent - } - - pixelPositionForRow (row) { - row = Math.min(row, this.maxRow) - let linesHeight = row * this.defaultLineHeight - let blocksHeight = this.blocks.filter((block) => block.row <= row).reduce((a, b) => a + b.height, 0) - return linesHeight + blocksHeight - } - - rowForPixelPosition (top, strategy) { - const roundingStrategy = strategy || 'floor' - let blocksHeight = 0 - let lastRow = 0 - let lastTop = 0 - for (let block of this.blocks) { - let nextBlocksHeight = blocksHeight + block.height - let linesHeight = block.row * this.defaultLineHeight - if (nextBlocksHeight + linesHeight > top) { - while (lastRow < block.row && lastTop + this.defaultLineHeight <= top) { - lastTop += this.defaultLineHeight - lastRow++ - } - return lastRow - } else { - blocksHeight = nextBlocksHeight - lastRow = block.row - lastTop = blocksHeight + linesHeight - } - } - - let remainingHeight = Math.max(0, top - lastTop) - let remainingRows = Math.min(this.maxRow, lastRow + remainingHeight / this.defaultLineHeight) - switch (roundingStrategy) { - case 'floor': - return Math.floor(remainingRows) - case 'ceil': - return Math.ceil(remainingRows) - default: - throw new Error(`Cannot use '${roundingStrategy}' as a rounding strategy!`) - } - } -} diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 531269366..266102cdd 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -14,7 +14,7 @@ OverlayManager = require './overlay-manager' DOMElementPool = require './dom-element-pool' LinesYardstick = require './lines-yardstick' BlockDecorationsComponent = require './block-decorations-component' -LineTopIndex = require './linear-line-top-index' +LineTopIndex = require 'line-top-index' module.exports = class TextEditorComponent diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index de98aa038..6c90c4f27 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -617,7 +617,8 @@ class TextEditorPresenter line = @model.tokenizedLineForScreenRow(screenRow) decorationClasses = @lineNumberDecorationClassesForRow(screenRow) foldable = @model.isFoldableAtScreenRow(screenRow) - blockDecorationsHeight = @lineTopIndex.blocksHeightForRow(screenRow) + previousRowBottomPixelPosition = @lineTopIndex.pixelPositionForRow(screenRow - 1) + @lineHeight + blockDecorationsHeight = @lineTopIndex.pixelPositionForRow(screenRow) - previousRowBottomPixelPosition tileState.lineNumbers[line.id] = {screenRow, bufferRow, softWrapped, decorationClasses, foldable, blockDecorationsHeight} visibleLineNumberIds[line.id] = true @@ -630,12 +631,15 @@ class TextEditorPresenter updateStartRow: -> return unless @scrollTop? and @lineHeight? - @startRow = Math.max(0, @lineTopIndex.rowForPixelPosition(@scrollTop, "floor")) + @startRow = Math.max(0, @lineTopIndex.rowForPixelPosition(@scrollTop)) updateEndRow: -> return unless @scrollTop? and @lineHeight? and @height? - @endRow = @lineTopIndex.rowForPixelPosition(@scrollTop + @height + @lineHeight, 'ceil') + @endRow = Math.min( + @model.getScreenLineCount(), + @lineTopIndex.rowForPixelPosition(@scrollTop + @height + @lineHeight) + ) updateRowsPerPage: -> rowsPerPage = Math.floor(@getClientHeight() / @lineHeight) @@ -667,7 +671,7 @@ class TextEditorPresenter updateVerticalDimensions: -> if @lineHeight? oldContentHeight = @contentHeight - @contentHeight = Math.round(@lineTopIndex.pixelPositionForRow(Infinity)) + @contentHeight = Math.round(@lineTopIndex.pixelPositionForRow(@model.getScreenLineCount())) if @contentHeight isnt oldContentHeight @updateHeight()