mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Start integrating tree-based LineTopIndex
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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", ->
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
|
||||
@@ -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!`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user