Render only visible and yet-to-be-measured block decorations

This commit is contained in:
Antonio Scandurra
2015-12-03 11:26:45 +01:00
parent fcb8a13f4a
commit 937116a280
6 changed files with 78 additions and 59 deletions

View File

@@ -2129,62 +2129,61 @@ describe "TextEditorPresenter", ->
isVisible: false
}
waitsForStateToUpdate presenter, ->
editor.getBuffer().insert([0, 0], 'Hello world \n\n\n\n')
presenter.setBlockDecorationDimensions(blockDecoration1, 0, 10)
presenter.setBlockDecorationDimensions(blockDecoration4, 0, 20)
runs ->
expectValues stateForBlockDecoration(presenter, blockDecoration1), {
decoration: blockDecoration1
screenRow: 4
isVisible: true
}
expectValues stateForBlockDecoration(presenter, blockDecoration2), {
decoration: blockDecoration2
screenRow: 8
isVisible: false
}
expectValues stateForBlockDecoration(presenter, blockDecoration3), {
decoration: blockDecoration3
screenRow: 8
isVisible: false
}
expectValues stateForBlockDecoration(presenter, blockDecoration4), {
decoration: blockDecoration4
screenRow: 14
isVisible: false
}
expectValues stateForBlockDecoration(presenter, blockDecoration1), {
decoration: blockDecoration1
screenRow: 0
isVisible: true
}
expectValues stateForBlockDecoration(presenter, blockDecoration2), {
decoration: blockDecoration2
screenRow: 4
isVisible: false
}
expectValues stateForBlockDecoration(presenter, blockDecoration3), {
decoration: blockDecoration3
screenRow: 4
isVisible: false
}
expect(stateForBlockDecoration(presenter, blockDecoration4)).toBeUndefined()
waitsForStateToUpdate presenter, ->
blockDecoration2.destroy()
blockDecoration4.destroy()
presenter.setBlockDecorationDimensions(blockDecoration1, 0, 20)
presenter.setScrollTop(90)
runs ->
expectValues stateForBlockDecoration(presenter, blockDecoration1), {
decoration: blockDecoration1
screenRow: 4
isVisible: true
}
expect(stateForBlockDecoration(presenter, blockDecoration2)).toBeUndefined()
expectValues stateForBlockDecoration(presenter, blockDecoration3), {
decoration: blockDecoration3
screenRow: 8
isVisible: false
}
expect(stateForBlockDecoration(presenter, blockDecoration4)).toBeUndefined()
expect(stateForBlockDecoration(presenter, blockDecoration1)).toBeUndefined()
expectValues stateForBlockDecoration(presenter, blockDecoration2), {
decoration: blockDecoration2
screenRow: 4
isVisible: false
}
expectValues stateForBlockDecoration(presenter, blockDecoration3), {
decoration: blockDecoration3
screenRow: 4
isVisible: false
}
expectValues stateForBlockDecoration(presenter, blockDecoration4), {
decoration: blockDecoration4
screenRow: 10
isVisible: true
}
presenter.setScrollTop(80)
presenter.invalidateBlockDecorationDimensions(blockDecoration1)
presenter.setBlockDecorationDimensions(blockDecoration2, 0, 10)
presenter.setBlockDecorationDimensions(blockDecoration3, 0, 10)
expectValues stateForBlockDecoration(presenter, blockDecoration1), {
decoration: blockDecoration1
screenRow: 4
isVisible: false
}
expectValues stateForBlockDecoration(presenter, blockDecoration3), {
decoration: blockDecoration3
screenRow: 8
isVisible: true
}
expectValues stateForBlockDecoration(presenter, blockDecoration1), {
decoration: blockDecoration1
screenRow: 0
isVisible: false
}
expect(stateForBlockDecoration(presenter, blockDecoration2)).toBeUndefined()
expect(stateForBlockDecoration(presenter, blockDecoration3)).toBeUndefined()
expectValues stateForBlockDecoration(presenter, blockDecoration4), {
decoration: blockDecoration4
screenRow: 10
isVisible: true
}
describe ".overlays", ->
[item] = []

View File

@@ -60,9 +60,9 @@ class BlockDecorationsComponent
oldBlockDecorationState = @oldState.blockDecorations[id]
blockDecorationNode = @blockDecorationNodesById[id]
if newBlockDecorationState.isVisible and not oldBlockDecorationState.isVisible
if newBlockDecorationState.isVisible
blockDecorationNode.classList.remove("atom--invisible-block-decoration")
else if not newBlockDecorationState.isVisible and oldBlockDecorationState.isVisible
else
blockDecorationNode.classList.add("atom--invisible-block-decoration")
if newBlockDecorationState.screenRow isnt oldBlockDecorationState.screenRow

View File

@@ -14,6 +14,7 @@ class BlockDecorationsPresenter {
this.blocksByDecoration = new Map
this.decorationsByBlock = new Map
this.observedDecorations = new Set
this.measuredDecorations = new Set
this.observeModel()
}
@@ -62,6 +63,12 @@ class BlockDecorationsPresenter {
this.lineTopIndex.resizeBlock(block, height)
}
this.measuredDecorations.add(decoration)
this.emitter.emit("did-update-state")
}
invalidateDimensionsForDecoration (decoration) {
this.measuredDecorations.delete(decoration)
this.emitter.emit("did-update-state")
}
@@ -70,14 +77,16 @@ class BlockDecorationsPresenter {
return blocks.map((block) => this.decorationsByBlock.get(block.id)).filter((decoration) => decoration)
}
getAllDecorationsByScreenRow () {
decorationsForScreenRowRange (startRow, endRow) {
let blocks = this.lineTopIndex.allBlocks()
let decorationsByScreenRow = new Map
for (let block of blocks) {
let decoration = this.decorationsByBlock.get(block.id)
if (decoration) {
let hasntMeasuredDecoration = !this.measuredDecorations.has(decoration)
let isVisible = startRow <= block.row && block.row < endRow
if (decoration && (isVisible || hasntMeasuredDecoration)) {
let decorations = decorationsByScreenRow.get(block.row) || []
decorations.push(decoration)
decorations.push({decoration, isVisible})
decorationsByScreenRow.set(block.row, decorations)
}
}

View File

@@ -456,6 +456,9 @@ class TextEditorComponent
@editor.screenPositionForBufferPosition(bufferPosition)
)
invalidateBlockDecorationDimensions: ->
@presenter.invalidateBlockDecorationDimensions(arguments...)
onMouseDown: (event) =>
unless event.button is 0 or (event.button is 1 and process.platform is 'linux')
# Only handle mouse down events for left mouse button on all platforms

View File

@@ -347,4 +347,7 @@ class TextEditorElement extends HTMLElement
getHeight: ->
@offsetHeight
invalidateBlockDecorationDimensions: ->
@component.invalidateBlockDecorationDimensions(arguments...)
module.exports = TextEditorElement = document.registerElement 'atom-text-editor', prototype: TextEditorElement.prototype

View File

@@ -1213,9 +1213,11 @@ class TextEditorPresenter
updateBlockDecorationsState: ->
@state.content.blockDecorations = {}
@blockDecorationsPresenter.getAllDecorationsByScreenRow().forEach (decorations, screenRow) =>
for decoration in decorations
isVisible = @getStartTileRow() <= screenRow < @getEndTileRow() + @tileSize
startRow = @getStartTileRow()
endRow = @getEndTileRow() + @tileSize
decorations = @blockDecorationsPresenter.decorationsForScreenRowRange(startRow, endRow)
decorations.forEach (decorations, screenRow) =>
for {decoration, isVisible} in decorations
@state.content.blockDecorations[decoration.id] = {decoration, screenRow, isVisible}
updateLineDecorations: ->
@@ -1414,6 +1416,9 @@ class TextEditorPresenter
setBlockDecorationDimensions: ->
@blockDecorationsPresenter.setDimensionsForDecoration(arguments...)
invalidateBlockDecorationDimensions: ->
@blockDecorationsPresenter.invalidateDimensionsForDecoration(arguments...)
observeCursor: (cursor) ->
didChangePositionDisposable = cursor.onDidChangePosition =>
@shouldUpdateHiddenInputState = true if cursor.isLastCursor()