Merge pull request #14929 from atom/as-resize-block-decorations-automatically

Invalidate block decoration dimensions automatically when their size changes
This commit is contained in:
Antonio Scandurra
2017-07-03 11:39:36 +02:00
committed by GitHub
2 changed files with 24 additions and 4 deletions

View File

@@ -1941,8 +1941,6 @@ describe('TextEditorComponent', () => {
item3.style.margin = '10px'
item2.style.height = '33px'
item2.style.margin = '0px'
component.invalidateBlockDecorationDimensions(decoration2)
component.invalidateBlockDecorationDimensions(decoration3)
await component.getNextUpdatePromise()
expect(component.getRenderedStartRow()).toBe(0)
expect(component.getRenderedEndRow()).toBe(9)
@@ -1973,7 +1971,6 @@ describe('TextEditorComponent', () => {
item3.style.wordWrap = 'break-word'
const contentWidthInCharacters = Math.floor(component.getScrollContainerClientWidth() / component.getBaseCharacterWidth())
item3.textContent = 'x'.repeat(contentWidthInCharacters * 2)
component.invalidateBlockDecorationDimensions(decoration3)
await component.getNextUpdatePromise()
// make the editor wider, so that the decoration doesn't wrap anymore.

View File

@@ -114,6 +114,9 @@ class TextEditorComponent {
this.horizontalPositionsToMeasure = new Map() // Keys are rows with positions we want to measure, values are arrays of columns to measure
this.horizontalPixelPositionsByScreenLineId = new Map() // Values are maps from column to horiontal pixel positions
this.blockDecorationsToMeasure = new Set()
this.blockDecorationsByElement = new WeakMap()
this.heightsByBlockDecoration = new WeakMap()
this.blockDecorationResizeObserver = new ResizeObserver(this.didResizeBlockDecorations.bind(this))
this.lineNodesByScreenLineId = new Map()
this.textNodesByScreenLineId = new Map()
this.overlayComponents = new Set()
@@ -322,6 +325,7 @@ class TextEditorComponent {
const decorationElement = TextEditor.viewForItem(item)
const {previousSibling, nextSibling} = decorationElement
const height = nextSibling.getBoundingClientRect().top - previousSibling.getBoundingClientRect().bottom
this.heightsByBlockDecoration.set(decoration, height)
this.lineTopIndex.resizeBlock(decoration, height)
})
@@ -2347,11 +2351,14 @@ class TextEditorComponent {
didAddBlockDecoration (decoration) {
const marker = decoration.getMarker()
const {position} = decoration.getProperties()
const {item, position} = decoration.getProperties()
const element = TextEditor.viewForItem(item)
const row = marker.getHeadScreenPosition().row
this.lineTopIndex.insertBlock(decoration, row, 0, position === 'after')
this.blockDecorationsToMeasure.add(decoration)
this.blockDecorationsByElement.set(element, decoration)
this.blockDecorationResizeObserver.observe(element)
const didUpdateDisposable = marker.bufferMarker.onDidChange((e) => {
if (!e.textChanged) {
@@ -2361,6 +2368,9 @@ class TextEditorComponent {
})
const didDestroyDisposable = decoration.onDidDestroy(() => {
this.blockDecorationsToMeasure.delete(decoration)
this.heightsByBlockDecoration.delete(decoration)
this.blockDecorationsByElement.delete(element)
this.blockDecorationResizeObserver.unobserve(element)
this.lineTopIndex.removeBlock(decoration)
didUpdateDisposable.dispose()
didDestroyDisposable.dispose()
@@ -2368,6 +2378,19 @@ class TextEditorComponent {
})
}
didResizeBlockDecorations (entries) {
if (!this.visible) return
for (let i = 0; i < entries.length; i++) {
const {target, contentRect} = entries[i]
const decoration = this.blockDecorationsByElement.get(target)
const previousHeight = this.heightsByBlockDecoration.get(decoration)
if (this.element.contains(target) && contentRect.height !== previousHeight) {
this.invalidateBlockDecorationDimensions(decoration)
}
}
}
invalidateBlockDecorationDimensions (decoration) {
this.blockDecorationsToMeasure.add(decoration)
this.scheduleUpdate()