mirror of
https://github.com/atom/atom.git
synced 2026-01-25 06:48:28 -05:00
Measure the longest visible screen line on initial render
This commit is contained in:
committed by
Antonio Scandurra
parent
ede5d5e5f4
commit
19d1d148eb
@@ -4,6 +4,7 @@ import {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} from './a
|
||||
|
||||
const TextEditorComponent = require('../src/text-editor-component')
|
||||
const TextEditor = require('../src/text-editor')
|
||||
const TextBuffer = require('text-buffer')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
@@ -16,8 +17,8 @@ describe('TextEditorComponent', () => {
|
||||
})
|
||||
|
||||
function buildComponent (params = {}) {
|
||||
const editor = new TextEditor()
|
||||
editor.setText(SAMPLE_TEXT)
|
||||
const buffer = new TextBuffer({text: SAMPLE_TEXT})
|
||||
const editor = new TextEditor({buffer})
|
||||
const component = new TextEditorComponent({model: editor, rowsPerTile: params.rowsPerTile})
|
||||
const {element} = component
|
||||
element.style.width = params.width ? params.width + 'px' : '800px'
|
||||
@@ -76,6 +77,16 @@ describe('TextEditorComponent', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('bases the width of the lines div on the width of the longest initially-visible screen line', () => {
|
||||
const {component, element, editor} = buildComponent({rowsPerTile: 2, height: 20})
|
||||
|
||||
expect(editor.getApproximateLongestScreenRow()).toBe(3)
|
||||
const expectedWidth = element.querySelectorAll('.line')[3].offsetWidth
|
||||
expect(element.querySelector('.lines').style.width).toBe(expectedWidth + 'px')
|
||||
|
||||
// TODO: Confirm that we'll update this value as indexing proceeds
|
||||
})
|
||||
|
||||
it('gives the line number gutter an explicit width and height so its layout can be strictly contained', () => {
|
||||
const {component, element, editor} = buildComponent({rowsPerTile: 3})
|
||||
|
||||
|
||||
@@ -41,13 +41,23 @@ class TextEditorComponent {
|
||||
|
||||
updateSync () {
|
||||
if (this.nextUpdatePromise) {
|
||||
const resolveNextUpdatePromise = this.resolveNextUpdatePromise
|
||||
this.resolveNextUpdatePromise()
|
||||
this.nextUpdatePromise = null
|
||||
this.resolveNextUpdatePromise = null
|
||||
resolveNextUpdatePromise()
|
||||
}
|
||||
|
||||
if (this.staleMeasurements.editorDimensions) this.measureEditorDimensions()
|
||||
etch.updateSync(this)
|
||||
|
||||
const longestLine = this.getLongestScreenLine()
|
||||
if (longestLine !== this.previousLongestLine) {
|
||||
this.longestLineToMeasure = longestLine
|
||||
etch.updateSync(this)
|
||||
this.measureLongestLineWidth()
|
||||
this.previousLongestLine = longestLine
|
||||
etch.updateSync(this)
|
||||
} else {
|
||||
etch.updateSync(this)
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
@@ -170,12 +180,14 @@ class TextEditorComponent {
|
||||
}
|
||||
|
||||
renderLines () {
|
||||
let style, children
|
||||
let children
|
||||
let style = {
|
||||
contain: 'strict',
|
||||
overflow: 'hidden'
|
||||
}
|
||||
if (this.measurements) {
|
||||
style = {
|
||||
width: this.measurements.scrollWidth + 'px',
|
||||
height: this.getScrollHeight() + 'px'
|
||||
}
|
||||
style.width = this.measurements.scrollWidth + 'px',
|
||||
style.height = this.getScrollHeight() + 'px'
|
||||
children = this.renderLineTiles()
|
||||
} else {
|
||||
children = $.div({ref: 'characterMeasurementLine', className: 'line'},
|
||||
@@ -206,7 +218,13 @@ class TextEditorComponent {
|
||||
for (let row = tileStartRow; row < tileEndRow; row++) {
|
||||
const screenLine = screenLines[row - firstTileStartRow]
|
||||
if (!screenLine) break
|
||||
lineNodes.push($(LineComponent, {key: screenLine.id, displayLayer, screenLine}))
|
||||
|
||||
const lineProps = {key: screenLine.id, displayLayer, screenLine}
|
||||
if (screenLine === this.longestLineToMeasure) {
|
||||
lineProps.ref = 'longestLineToMeasure'
|
||||
this.longestLineToMeasure = null
|
||||
}
|
||||
lineNodes.push($(LineComponent, lineProps))
|
||||
}
|
||||
|
||||
const tileHeight = this.getRowsPerTile() * this.measurements.lineHeight
|
||||
@@ -226,6 +244,16 @@ class TextEditorComponent {
|
||||
}, lineNodes)
|
||||
}
|
||||
|
||||
if (this.longestLineToMeasure) {
|
||||
tileNodes.push($(LineComponent, {
|
||||
ref: 'longestLineToMeasure',
|
||||
key: this.longestLineToMeasure.id,
|
||||
displayLayer,
|
||||
screenLine: this.longestLineToMeasure
|
||||
}))
|
||||
this.longestLineToMeasure = null
|
||||
}
|
||||
|
||||
return tileNodes
|
||||
}
|
||||
|
||||
@@ -245,7 +273,7 @@ class TextEditorComponent {
|
||||
didShow () {
|
||||
this.getModel().setVisible(true)
|
||||
if (!this.measurements) this.performInitialMeasurements()
|
||||
etch.updateSync(this)
|
||||
this.updateSync()
|
||||
}
|
||||
|
||||
didHide () {
|
||||
@@ -268,7 +296,6 @@ class TextEditorComponent {
|
||||
this.measureEditorDimensions()
|
||||
this.measureScrollPosition()
|
||||
this.measureCharacterDimensions()
|
||||
this.measureLongestLineWidth()
|
||||
this.measureGutterDimensions()
|
||||
}
|
||||
|
||||
@@ -290,9 +317,7 @@ class TextEditorComponent {
|
||||
}
|
||||
|
||||
measureLongestLineWidth () {
|
||||
const displayLayer = this.getModel().displayLayer
|
||||
const rightmostPosition = displayLayer.getRightmostScreenPosition()
|
||||
this.measurements.scrollWidth = rightmostPosition.column * this.measurements.baseCharacterWidth
|
||||
this.measurements.scrollWidth = this.refs.longestLineToMeasure.element.firstChild.offsetWidth
|
||||
}
|
||||
|
||||
measureGutterDimensions () {
|
||||
@@ -352,6 +377,15 @@ class TextEditorComponent {
|
||||
return this.getModel().getApproximateScreenLineCount() * this.measurements.lineHeight
|
||||
}
|
||||
|
||||
getLongestScreenLine () {
|
||||
const model = this.getModel()
|
||||
// Ensure the spatial index is populated with rows that are currently
|
||||
// visible so we *at least* get the longest row in the visible range.
|
||||
const renderedEndRow = this.getTileStartRow(this.getLastVisibleRow()) + this.getRowsPerTile()
|
||||
model.displayLayer.populateSpatialIndexIfNeeded(Infinity, renderedEndRow)
|
||||
return model.screenLineForScreenRow(model.getApproximateLongestScreenRow())
|
||||
}
|
||||
|
||||
getNextUpdatePromise () {
|
||||
if (!this.nextUpdatePromise) {
|
||||
this.nextUpdatePromise = new Promise((resolve) => {
|
||||
@@ -370,7 +404,8 @@ class LineComponent {
|
||||
|
||||
const textNodes = []
|
||||
let startIndex = 0
|
||||
let openScopeNode = this.element
|
||||
let openScopeNode = document.createElement('span')
|
||||
this.element.appendChild(openScopeNode)
|
||||
for (let i = 0; i < tagCodes.length; i++) {
|
||||
const tagCode = tagCodes[i]
|
||||
if (tagCode !== 0) {
|
||||
|
||||
Reference in New Issue
Block a user