Use an updated version of LineTopIndex

This commit is contained in:
Antonio Scandurra
2015-12-14 15:04:54 +01:00
parent c578f221bf
commit cfb30c795d
9 changed files with 56 additions and 258 deletions

View File

@@ -31,9 +31,6 @@ class BlockDecorationsPresenter {
}
observeModel () {
this.lineTopIndex.setMaxRow(this.model.getScreenLineCount())
this.lineTopIndex.setDefaultLineHeight(this.model.getLineHeightInPixels())
this.disposables.add(this.model.onDidAddDecoration(this.observeDecoration.bind(this)))
this.disposables.add(this.model.onDidChange((changeEvent) => {
let oldExtent = changeEvent.end - changeEvent.start
@@ -54,11 +51,10 @@ class BlockDecorationsPresenter {
setDimensionsForDecoration (decoration, width, height) {
let block = this.blocksByDecoration.get(decoration)
if (block) {
this.lineTopIndex.resizeBlock(block, height)
this.lineTopIndex.resizeBlock(decoration.getMarker().id, height)
} else {
this.observeDecoration(decoration)
block = this.blocksByDecoration.get(decoration)
this.lineTopIndex.resizeBlock(block, height)
this.lineTopIndex.resizeBlock(decoration.getMarker().id, height)
}
this.measuredDecorations.add(decoration)
@@ -124,9 +120,9 @@ class BlockDecorationsPresenter {
didAddDecoration (decoration) {
let screenRow = decoration.getMarker().getHeadScreenPosition().row
let block = this.lineTopIndex.insertBlock(screenRow, 0)
this.decorationsByBlock.set(block, decoration)
this.blocksByDecoration.set(decoration, block)
this.lineTopIndex.insertBlock(decoration.getMarker().id, screenRow, 0)
this.decorationsByBlock.set(decoration.getMarker().id, decoration)
this.blocksByDecoration.set(decoration, decoration.getMarker().id)
this.emitter.emit('did-update-state')
}
@@ -136,16 +132,15 @@ class BlockDecorationsPresenter {
return
}
let block = this.blocksByDecoration.get(decoration)
let newScreenRow = decoration.getMarker().getHeadScreenPosition().row
this.lineTopIndex.moveBlock(block, newScreenRow)
this.lineTopIndex.moveBlock(decoration.getMarker().id, newScreenRow)
this.emitter.emit('did-update-state')
}
didDestroyDecoration (decoration) {
let block = this.blocksByDecoration.get(decoration)
if (block) {
this.lineTopIndex.removeBlock(block)
this.lineTopIndex.removeBlock(decoration.getMarker().id)
this.blocksByDecoration.delete(decoration)
this.decorationsByBlock.delete(block)
}

View File

@@ -1,27 +1,23 @@
'use strict'
"use babel"
module.exports =
class LineTopIndex {
constructor () {
this.idCounter = 1
export default class LineTopIndex {
constructor (params = {}) {
this.blocks = []
this.maxRow = 0
this.defaultLineHeight = 0
this.maxRow = params.maxRow || 0
this.setDefaultLineHeight(params.defaultLineHeight || 0)
}
setDefaultLineHeight (lineHeight) {
this.defaultLineHeight = lineHeight
}
setMaxRow (maxRow) {
this.maxRow = maxRow
getMaxRow () {
return this.maxRow
}
insertBlock (row, height) {
let id = this.idCounter++
insertBlock (id, row, height) {
this.blocks.push({id, row, height})
this.blocks.sort((a, b) => a.row - b.row)
return id
}
resizeBlock (id, height) {
@@ -62,26 +58,21 @@ class LineTopIndex {
block.row += newExtent - oldExtent
} else {
block.row = startRow + newExtent
// invalidate marker?
}
}
})
this.setMaxRow(this.maxRow + newExtent - oldExtent)
this.maxRow = this.maxRow + newExtent - oldExtent
}
topPixelPositionForRow (row) {
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)
let blocksHeight = this.blocks.filter((block) => block.row <= row).reduce((a, b) => a + b.height, 0)
return linesHeight + blocksHeight
}
bottomPixelPositionForRow (row) {
return this.topPixelPositionForRow(row + 1) - this.defaultLineHeight
}
rowForTopPixelPosition (top, strategy) {
rowForPixelPosition (top, strategy) {
const roundingStrategy = strategy || 'floor'
let blocksHeight = 0
let lastRow = 0

View File

@@ -22,7 +22,7 @@ class LinesYardstick
targetTop = pixelPosition.top
targetLeft = pixelPosition.left
defaultCharWidth = @model.getDefaultCharWidth()
row = @lineTopIndex.rowForTopPixelPosition(targetTop, 'floor')
row = @lineTopIndex.rowForPixelPosition(targetTop, 'floor')
targetLeft = 0 if targetTop < 0
targetLeft = Infinity if row > @model.getLastScreenRow()
row = Math.min(row, @model.getLastScreenRow())
@@ -91,7 +91,7 @@ class LinesYardstick
@prepareScreenRowsForMeasurement([targetRow]) unless measureVisibleLinesOnly
top = @lineTopIndex.bottomPixelPositionForRow(targetRow)
top = @lineTopIndex.pixelPositionForRow(targetRow)
left = @leftPixelPositionForScreenPosition(targetRow, targetColumn)
@clearScreenRowsForMeasurement() unless measureVisibleLinesOnly
@@ -174,14 +174,14 @@ class LinesYardstick
left + width - offset
pixelRectForScreenRange: (screenRange, measureVisibleLinesOnly) ->
top = @lineTopIndex.pixelPositionForRow(screenRange.start.row)
if screenRange.end.row > screenRange.start.row
top = @pixelPositionForScreenPosition(screenRange.start, true, measureVisibleLinesOnly).top
left = 0
height = @lineTopIndex.topPixelPositionForRow(screenRange.end.row + 1) - top
height = @lineTopIndex.pixelPositionForRow(screenRange.end.row) - top + @model.getLineHeightInPixels()
width = @presenter.getScrollWidth()
else
{top, left} = @pixelPositionForScreenPosition(screenRange.start, false, measureVisibleLinesOnly)
height = @lineTopIndex.topPixelPositionForRow(screenRange.end.row + 1) - top
{left} = @pixelPositionForScreenPosition(screenRange.start, false, measureVisibleLinesOnly)
height = @lineTopIndex.pixelPositionForRow(screenRange.end.row) - top + @model.getLineHeightInPixels()
width = @pixelPositionForScreenPosition(screenRange.end, false, measureVisibleLinesOnly).left - left
{top, left, width, height}

View File

@@ -50,7 +50,10 @@ class TextEditorComponent
@observeConfig()
@setScrollSensitivity(@config.get('editor.scrollSensitivity'))
lineTopIndex = new LineTopIndex(@editor)
lineTopIndex = new LineTopIndex({
maxRow: @editor.getScreenLineCount(),
defaultLineHeight: @editor.getLineHeightInPixels()
})
@presenter = new TextEditorPresenter
model: @editor
tileSize: tileSize

View File

@@ -442,8 +442,8 @@ class TextEditorPresenter
continue if rowsWithinTile.length is 0
top = Math.round(@lineTopIndex.topPixelPositionForRow(tileStartRow))
bottom = Math.round(@lineTopIndex.topPixelPositionForRow(tileEndRow))
top = Math.round(@lineTopIndex.pixelPositionForRow(tileStartRow - 1) + @lineHeight)
bottom = Math.round(@lineTopIndex.pixelPositionForRow(tileEndRow - 1) + @lineHeight)
height = bottom - top
tile = @state.content.tiles[tileStartRow] ?= {}
@@ -659,8 +659,8 @@ class TextEditorPresenter
continue unless @gutterIsVisible(gutter)
for decorationId, {properties, screenRange} of @customGutterDecorationsByGutterName[gutterName]
top = @lineTopIndex.topPixelPositionForRow(screenRange.start.row)
bottom = @lineTopIndex.topPixelPositionForRow(screenRange.end.row + 1)
top = @lineTopIndex.pixelPositionForRow(screenRange.start.row)
bottom = @lineTopIndex.pixelPositionForRow(screenRange.end.row) + @lineHeight
@customGutterDecorations[gutterName][decorationId] =
top: top
height: bottom - top
@@ -724,12 +724,12 @@ class TextEditorPresenter
updateStartRow: ->
return unless @scrollTop? and @lineHeight?
@startRow = Math.max(0, @lineTopIndex.rowForTopPixelPosition(@scrollTop, "floor"))
@startRow = Math.max(0, @lineTopIndex.rowForPixelPosition(@scrollTop, "floor"))
updateEndRow: ->
return unless @scrollTop? and @lineHeight? and @height?
@endRow = @lineTopIndex.rowForTopPixelPosition(@scrollTop + @height + @lineHeight, 'ceil')
@endRow = @lineTopIndex.rowForPixelPosition(@scrollTop + @height + @lineHeight, 'ceil')
updateRowsPerPage: ->
rowsPerPage = Math.floor(@getClientHeight() / @lineHeight)
@@ -761,7 +761,7 @@ class TextEditorPresenter
updateVerticalDimensions: ->
if @lineHeight?
oldContentHeight = @contentHeight
@contentHeight = Math.round(@lineTopIndex.topPixelPositionForRow(Infinity))
@contentHeight = Math.round(@lineTopIndex.pixelPositionForRow(Infinity))
if @contentHeight isnt oldContentHeight
@updateHeight()
@@ -1340,7 +1340,7 @@ class TextEditorPresenter
screenRange.end.column = 0
repositionRegionWithinTile: (region, tileStartRow) ->
region.top += @scrollTop - @lineTopIndex.topPixelPositionForRow(tileStartRow)
region.top += @scrollTop - (@lineTopIndex.pixelPositionForRow(tileStartRow - 1) + @lineHeight)
region.left += @scrollLeft
buildHighlightRegions: (screenRange) ->
@@ -1495,7 +1495,7 @@ class TextEditorPresenter
@emitDidUpdateState()
didChangeFirstVisibleScreenRow: (screenRow) ->
@updateScrollTop(@lineTopIndex.topPixelPositionForRow(screenRow))
@updateScrollTop(@lineTopIndex.pixelPositionForRow(screenRow))
getVerticalScrollMarginInPixels: ->
Math.round(@model.getVerticalScrollMargin() * @lineHeight)
@@ -1516,8 +1516,8 @@ class TextEditorPresenter
verticalScrollMarginInPixels = @getVerticalScrollMarginInPixels()
top = @lineTopIndex.bottomPixelPositionForRow(screenRange.start.row)
bottom = @lineTopIndex.bottomPixelPositionForRow(screenRange.end.row + 1)
top = @lineTopIndex.pixelPositionForRow(screenRange.start.row)
bottom = @lineTopIndex.pixelPositionForRow(screenRange.end.row) + @lineHeight
if options?.center
desiredScrollCenter = (top + bottom) / 2
@@ -1589,7 +1589,7 @@ class TextEditorPresenter
restoreScrollTopIfNeeded: ->
unless @scrollTop?
@updateScrollTop(@lineTopIndex.topPixelPositionForRow(@model.getFirstVisibleScreenRow()))
@updateScrollTop(@lineTopIndex.pixelPositionForRow(@model.getFirstVisibleScreenRow()))
restoreScrollLeftIfNeeded: ->
unless @scrollLeft?