From e686c4d7f84121afb368f74638b0139c41599feb Mon Sep 17 00:00:00 2001 From: Lukas Geiger Date: Tue, 20 Jun 2017 13:00:34 +0200 Subject: [PATCH 1/2] Remove `invalidateBlockDecorationDimensions` from tests This is now automatically called by the mutation observer. --- spec/text-editor-component-spec.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index b44838538..862018cf8 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -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. From b30f55bb576ca52782b6970c92223722309c556a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 30 Jun 2017 14:06:50 +0200 Subject: [PATCH 2/2] Invalidate block decorations height automatically if their size changes --- src/text-editor-component.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/text-editor-component.js b/src/text-editor-component.js index 0665bc185..ce332ed67 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -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()