Avoid forcing computation of all screen lines when opening a file

This commit is contained in:
Max Brunsfeld
2016-10-06 16:52:21 -07:00
parent 99dec68f02
commit 1e3443e6c1
4 changed files with 42 additions and 29 deletions

View File

@@ -58,7 +58,7 @@
"sinon": "1.17.4",
"source-map-support": "^0.3.2",
"temp": "0.8.1",
"text-buffer": "9.3.0",
"text-buffer": "9.3.1-1",
"typescript-simple": "1.0.0",
"underscore-plus": "^1.6.6",
"winreg": "^1.2.1",

View File

@@ -13,19 +13,20 @@ class LinesYardstick
measuredRowForPixelPosition: (pixelPosition) ->
targetTop = pixelPosition.top
row = Math.floor(targetTop / @model.getLineHeightInPixels())
row if 0 <= row <= @model.getLastScreenRow()
row if 0 <= row
screenPositionForPixelPosition: (pixelPosition) ->
targetTop = pixelPosition.top
targetLeft = pixelPosition.left
row = @lineTopIndex.rowForPixelPosition(targetTop)
targetLeft = 0 if targetTop < 0 or targetLeft < 0
targetLeft = Infinity if row > @model.getLastScreenRow()
row = Math.min(row, @model.getLastScreenRow())
row = Math.max(0, row)
row = Math.max(0, @lineTopIndex.rowForPixelPosition(targetTop))
lineNode = @lineNodesProvider.lineNodeForScreenRow(row)
return Point(row, 0) unless lineNode
unless lineNode
if row > @model.getLastScreenRow()
return Point(@model.getLastScreenRow(), Infinity)
else
return Point(row, 0)
targetLeft = pixelPosition.left
targetLeft = 0 if targetTop < 0 or targetLeft < 0
textNodes = @lineNodesProvider.textNodesForScreenRow(row)
lineOffset = lineNode.getBoundingClientRect().left

View File

@@ -137,6 +137,11 @@ class TextEditorPresenter
@shouldUpdateDecorations = true
observeModel: ->
@disposables.add @model.displayLayer.onDidReset =>
@spliceBlockDecorationsInRange(0, Infinity, Infinity)
@shouldUpdateDecorations = true
@emitDidUpdateState()
@disposables.add @model.displayLayer.onDidChangeSync (changes) =>
for change in changes
startRow = change.start.row
@@ -291,24 +296,21 @@ class TextEditorPresenter
tileForRow: (row) ->
row - (row % @tileSize)
constrainRow: (row) ->
Math.max(0, Math.min(row, @model.getScreenLineCount()))
getStartTileRow: ->
@constrainRow(@tileForRow(@startRow ? 0))
@tileForRow(@startRow ? 0)
getEndTileRow: ->
@constrainRow(@tileForRow(@endRow ? 0))
@tileForRow(@endRow ? 0)
isValidScreenRow: (screenRow) ->
screenRow >= 0 and screenRow < @model.getScreenLineCount()
screenRow >= 0 and screenRow < @model.getApproximateScreenLineCount()
getScreenRowsToRender: ->
startRow = @getStartTileRow()
endRow = @constrainRow(@getEndTileRow() + @tileSize)
endRow = @getEndTileRow() + @tileSize
screenRows = [startRow...endRow]
longestScreenRow = @model.getLongestScreenRow()
longestScreenRow = @model.getApproximateLongestScreenRow()
if longestScreenRow?
screenRows.push(longestScreenRow)
if @screenRowsToMeasure?
@@ -354,7 +356,7 @@ class TextEditorPresenter
zIndex = 0
for tileStartRow in [@tileForRow(endRow)..@tileForRow(startRow)] by -@tileSize
tileEndRow = @constrainRow(tileStartRow + @tileSize)
tileEndRow = tileStartRow + @tileSize
rowsWithinTile = []
while screenRowIndex >= 0
@@ -389,7 +391,7 @@ class TextEditorPresenter
visibleTiles[tileStartRow] = true
zIndex++
if @mouseWheelScreenRow? and 0 <= @mouseWheelScreenRow < @model.getScreenLineCount()
if @mouseWheelScreenRow? and 0 <= @mouseWheelScreenRow < @model.getApproximateScreenLineCount()
mouseWheelTile = @tileForRow(@mouseWheelScreenRow)
unless visibleTiles[mouseWheelTile]?
@@ -408,8 +410,7 @@ class TextEditorPresenter
visibleLineIds = {}
for screenRow in screenRows
line = @linesByScreenRow.get(screenRow)
unless line?
throw new Error("No line exists for row #{screenRow}. Last screen row: #{@model.getLastScreenRow()}")
continue unless line?
visibleLineIds[line.id] = true
precedingBlockDecorations = @precedingBlockDecorationsByScreenRow[screenRow] ? []
@@ -597,7 +598,9 @@ class TextEditorPresenter
visibleLineNumberIds = {}
for screenRow in screenRows when @isRowRendered(screenRow)
lineId = @linesByScreenRow.get(screenRow).id
line = @linesByScreenRow.get(screenRow)
continue unless line?
lineId = line.id
{bufferRow, softWrappedAtStart: softWrapped} = @displayLayer.softWrapDescriptorForScreenRow(screenRow)
foldable = not softWrapped and @model.isFoldableAtBufferRow(bufferRow)
decorationClasses = @lineNumberDecorationClassesForRow(screenRow)
@@ -624,7 +627,7 @@ class TextEditorPresenter
return unless @scrollTop? and @lineHeight? and @height?
@endRow = Math.min(
@model.getScreenLineCount(),
@model.getApproximateScreenLineCount(),
@lineTopIndex.rowForPixelPosition(@scrollTop + @height + @lineHeight - 1) + 1
)
@@ -658,7 +661,7 @@ class TextEditorPresenter
updateVerticalDimensions: ->
if @lineHeight?
oldContentHeight = @contentHeight
@contentHeight = Math.round(@lineTopIndex.pixelPositionAfterBlocksForRow(@model.getScreenLineCount()))
@contentHeight = Math.round(@lineTopIndex.pixelPositionAfterBlocksForRow(@model.getApproximateScreenLineCount()))
if @contentHeight isnt oldContentHeight
@updateHeight()
@@ -668,7 +671,7 @@ class TextEditorPresenter
updateHorizontalDimensions: ->
if @baseCharacterWidth?
oldContentWidth = @contentWidth
rightmostPosition = @model.getRightmostScreenPosition()
rightmostPosition = @model.getApproximateRightmostScreenPosition()
@contentWidth = @pixelPositionForScreenPosition(rightmostPosition).left
@contentWidth += @scrollLeft
@contentWidth += 1 unless @model.isSoftWrapped() # account for cursor width
@@ -1529,7 +1532,7 @@ class TextEditorPresenter
[@startRow, @endRow]
isRowRendered: (row) ->
@getStartTileRow() <= row < @constrainRow(@getEndTileRow() + @tileSize)
@getStartTileRow() <= row < @getEndTileRow() + @tileSize
isOpenTagCode: (tagCode) ->
@displayLayer.isOpenTagCode(tagCode)

View File

@@ -391,6 +391,9 @@ class TextEditor extends Model
@disposables.add @displayLayer.onDidChangeSync (e) =>
@mergeIntersectingSelections()
@emitter.emit 'did-change', e
@disposables.add @displayLayer.onDidReset =>
@mergeIntersectingSelections()
@emitter.emit 'did-change', {}
destroyed: ->
@disposables.dispose()
@@ -907,6 +910,8 @@ class TextEditor extends Model
# editor. This accounts for folds.
getScreenLineCount: -> @displayLayer.getScreenLineCount()
getApproximateScreenLineCount: -> @displayLayer.getApproximateScreenLineCount()
# Essential: Returns a {Number} representing the last zero-indexed buffer row
# number of the editor.
getLastBufferRow: -> @buffer.getLastRow()
@@ -953,8 +958,8 @@ class TextEditor extends Model
tokens
screenLineForScreenRow: (screenRow) ->
return if screenRow < 0 or screenRow > @getLastScreenRow()
@displayLayer.getScreenLines(screenRow, screenRow + 1)[0]
result = @displayLayer.getScreenLines(screenRow, screenRow + 1)
result[0] if result
bufferRowForScreenRow: (screenRow) ->
@displayLayer.translateScreenPosition(Point(screenRow, 0)).row
@@ -971,10 +976,14 @@ class TextEditor extends Model
getRightmostScreenPosition: -> @displayLayer.getRightmostScreenPosition()
getApproximateRightmostScreenPosition: -> @displayLayer.getApproximateRightmostScreenPosition()
getMaxScreenLineLength: -> @getRightmostScreenPosition().column
getLongestScreenRow: -> @getRightmostScreenPosition().row
getApproximateLongestScreenRow: -> @getApproximateRightmostScreenPosition().row
lineLengthForScreenRow: (screenRow) -> @displayLayer.lineLengthForScreenRow(screenRow)
# Returns the range for the given buffer row.