mirror of
https://github.com/atom/atom.git
synced 2026-01-25 14:59:03 -05:00
Remeasure block decorations when editor width changes
Signed-off-by: Nathan Sobo <nathan@github.com>
This commit is contained in:
@@ -1402,6 +1402,74 @@ describe('TextEditorComponent', () => {
|
||||
expect(element.contains(item4)).toBe(false)
|
||||
expect(element.contains(item5)).toBe(false)
|
||||
expect(element.contains(item6)).toBe(false)
|
||||
|
||||
// make decoration before row 0 as wide as the editor, and insert some text into it so that it wraps.
|
||||
item3.style.height = ''
|
||||
item3.style.margin = ''
|
||||
item3.style.width = ''
|
||||
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.
|
||||
component.element.style.width = (
|
||||
component.getGutterContainerWidth() +
|
||||
component.getScrollContainerClientWidth() * 2 +
|
||||
component.getVerticalScrollbarWidth()
|
||||
) + 'px'
|
||||
await component.getNextUpdatePromise()
|
||||
expect(component.getRenderedStartRow()).toBe(0)
|
||||
expect(component.getRenderedEndRow()).toBe(6)
|
||||
expect(component.getScrollHeight()).toBe(
|
||||
editor.getScreenLineCount() * component.getLineHeight() +
|
||||
getElementHeight(item2) + getElementHeight(item3) +
|
||||
getElementHeight(item4) + getElementHeight(item5) + getElementHeight(item6)
|
||||
)
|
||||
assertTilesAreSizedAndPositionedCorrectly(component, [
|
||||
{tileStartRow: 0, height: 3 * component.getLineHeight() + getElementHeight(item2) + getElementHeight(item3)},
|
||||
{tileStartRow: 3, height: 3 * component.getLineHeight()}
|
||||
])
|
||||
assertLinesAreAlignedWithLineNumbers(component)
|
||||
expect(element.querySelectorAll('.line').length).toBe(6)
|
||||
expect(element.contains(item1)).toBe(false)
|
||||
expect(item2.previousSibling).toBe(lineNodeForScreenRow(component, 0))
|
||||
expect(item2.nextSibling).toBe(lineNodeForScreenRow(component, 1))
|
||||
expect(item3.previousSibling).toBeNull()
|
||||
expect(item3.nextSibling).toBe(lineNodeForScreenRow(component, 0))
|
||||
expect(element.contains(item4)).toBe(false)
|
||||
expect(element.contains(item5)).toBe(false)
|
||||
expect(element.contains(item6)).toBe(false)
|
||||
|
||||
// make the editor taller and wider and the same time, ensuring the number
|
||||
// of rendered lines is correct.
|
||||
setEditorHeightInLines(component, 10)
|
||||
await setEditorWidthInCharacters(component, 50)
|
||||
expect(component.getRenderedStartRow()).toBe(0)
|
||||
expect(component.getRenderedEndRow()).toBe(9)
|
||||
expect(component.getScrollHeight()).toBe(
|
||||
editor.getScreenLineCount() * component.getLineHeight() +
|
||||
getElementHeight(item2) + getElementHeight(item3) +
|
||||
getElementHeight(item4) + getElementHeight(item5) + getElementHeight(item6)
|
||||
)
|
||||
assertTilesAreSizedAndPositionedCorrectly(component, [
|
||||
{tileStartRow: 0, height: 3 * component.getLineHeight() + getElementHeight(item2) + getElementHeight(item3)},
|
||||
{tileStartRow: 3, height: 3 * component.getLineHeight()},
|
||||
{tileStartRow: 6, height: 3 * component.getLineHeight() + getElementHeight(item4) + getElementHeight(item5)},
|
||||
])
|
||||
assertLinesAreAlignedWithLineNumbers(component)
|
||||
expect(element.querySelectorAll('.line').length).toBe(9)
|
||||
expect(element.contains(item1)).toBe(false)
|
||||
expect(item2.previousSibling).toBe(lineNodeForScreenRow(component, 0))
|
||||
expect(item2.nextSibling).toBe(lineNodeForScreenRow(component, 1))
|
||||
expect(item3.previousSibling).toBeNull()
|
||||
expect(item3.nextSibling).toBe(lineNodeForScreenRow(component, 0))
|
||||
expect(item4.previousSibling).toBe(lineNodeForScreenRow(component, 6))
|
||||
expect(item4.nextSibling).toBe(lineNodeForScreenRow(component, 7))
|
||||
expect(item5.previousSibling).toBe(lineNodeForScreenRow(component, 7))
|
||||
expect(item5.nextSibling).toBe(lineNodeForScreenRow(component, 8))
|
||||
expect(element.contains(item6)).toBe(false)
|
||||
})
|
||||
|
||||
function createBlockDecorationAtScreenRow(editor, screenRow, {height, margin, position}) {
|
||||
|
||||
@@ -182,6 +182,24 @@ class TextEditorComponent {
|
||||
}
|
||||
|
||||
measureBlockDecorations () {
|
||||
if (this.remeasureAllBlockDecorations) {
|
||||
this.remeasureAllBlockDecorations = false
|
||||
|
||||
const decorations = this.props.model.getDecorations()
|
||||
for (var i = 0; i < decorations.length; i++) {
|
||||
const decoration = decorations[i]
|
||||
if (decoration.getProperties().type === 'block') {
|
||||
this.blockDecorationsToMeasure.add(decoration)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the width of the line tiles to ensure block decorations are
|
||||
// measured with the most recent width.
|
||||
if (this.blockDecorationsToMeasure.size > 0) {
|
||||
this.updateSyncBeforeMeasuringContent()
|
||||
}
|
||||
}
|
||||
|
||||
if (this.blockDecorationsToMeasure.size > 0) {
|
||||
const {blockDecorationMeasurementArea} = this.refs
|
||||
const sentinelElements = new Set()
|
||||
@@ -1188,7 +1206,13 @@ class TextEditorComponent {
|
||||
}
|
||||
|
||||
didResize () {
|
||||
if (this.measureClientContainerDimensions()) {
|
||||
const clientContainerWidthChanged = this.measureClientContainerWidth()
|
||||
const clientContainerHeightChanged = this.measureClientContainerHeight()
|
||||
if (clientContainerWidthChanged || clientContainerHeightChanged) {
|
||||
if (clientContainerWidthChanged) {
|
||||
this.remeasureAllBlockDecorations = true
|
||||
}
|
||||
|
||||
this.scheduleUpdate()
|
||||
}
|
||||
}
|
||||
@@ -1646,7 +1670,8 @@ class TextEditorComponent {
|
||||
this.measurements = {}
|
||||
this.measureCharacterDimensions()
|
||||
this.measureGutterDimensions()
|
||||
this.measureClientContainerDimensions()
|
||||
this.measureClientContainerHeight()
|
||||
this.measureClientContainerWidth()
|
||||
this.measureScrollbarDimensions()
|
||||
}
|
||||
|
||||
@@ -1692,22 +1717,29 @@ class TextEditorComponent {
|
||||
return dimensionsChanged
|
||||
}
|
||||
|
||||
measureClientContainerDimensions () {
|
||||
measureClientContainerHeight () {
|
||||
if (!this.measurements) return false
|
||||
|
||||
let dimensionsChanged = false
|
||||
const clientContainerHeight = this.refs.clientContainer.offsetHeight
|
||||
const clientContainerWidth = this.refs.clientContainer.offsetWidth
|
||||
if (clientContainerHeight !== this.measurements.clientContainerHeight) {
|
||||
this.measurements.clientContainerHeight = clientContainerHeight
|
||||
dimensionsChanged = true
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
measureClientContainerWidth () {
|
||||
if (!this.measurements) return false
|
||||
|
||||
const clientContainerWidth = this.refs.clientContainer.offsetWidth
|
||||
if (clientContainerWidth !== this.measurements.clientContainerWidth) {
|
||||
this.measurements.clientContainerWidth = clientContainerWidth
|
||||
this.props.model.setEditorWidthInChars(this.getScrollContainerWidth() / this.getBaseCharacterWidth())
|
||||
dimensionsChanged = true
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return dimensionsChanged
|
||||
}
|
||||
|
||||
measureScrollbarDimensions () {
|
||||
|
||||
Reference in New Issue
Block a user