mirror of
https://github.com/atom/atom.git
synced 2026-01-25 06:48:28 -05:00
WIP: Render gutters before initial measurement
The shouldUpdate method is just returning true for now. We probably need to find a new approach to representing line number decorations that's easier to diff, perhaps a sparse array?
This commit is contained in:
committed by
Antonio Scandurra
parent
d5d3cfc5a9
commit
4e834da3e3
@@ -1,6 +1,4 @@
|
||||
/** @babel */
|
||||
|
||||
import {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} from './async-spec-helpers'
|
||||
const {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} = require('./async-spec-helpers')
|
||||
|
||||
const TextEditorComponent = require('../src/text-editor-component')
|
||||
const TextEditor = require('../src/text-editor')
|
||||
@@ -21,7 +19,7 @@ document.registerElement('text-editor-component-test-element', {
|
||||
})
|
||||
})
|
||||
|
||||
describe('TextEditorComponent', () => {
|
||||
fdescribe('TextEditorComponent', () => {
|
||||
beforeEach(() => {
|
||||
jasmine.useRealClock()
|
||||
})
|
||||
@@ -30,12 +28,12 @@ describe('TextEditorComponent', () => {
|
||||
it('renders lines and line numbers for the visible region', async () => {
|
||||
const {component, element, editor} = buildComponent({rowsPerTile: 3, autoHeight: false})
|
||||
|
||||
expect(element.querySelectorAll('.line-number').length).toBe(13)
|
||||
expect(element.querySelectorAll('.line-number').length).toBe(13 + 1) // +1 for placeholder line number
|
||||
expect(element.querySelectorAll('.line').length).toBe(13)
|
||||
|
||||
element.style.height = 4 * component.measurements.lineHeight + 'px'
|
||||
await component.getNextUpdatePromise()
|
||||
expect(element.querySelectorAll('.line-number').length).toBe(9)
|
||||
expect(element.querySelectorAll('.line-number').length).toBe(9 + 1) // +1 for placeholder line number
|
||||
expect(element.querySelectorAll('.line').length).toBe(9)
|
||||
|
||||
await setScrollTop(component, 5 * component.getLineHeight())
|
||||
@@ -43,7 +41,7 @@ describe('TextEditorComponent', () => {
|
||||
// After scrolling down beyond > 3 rows, the order of line numbers and lines
|
||||
// in the DOM is a bit weird because the first tile is recycled to the bottom
|
||||
// when it is scrolled out of view
|
||||
expect(Array.from(element.querySelectorAll('.line-number')).map(element => element.textContent.trim())).toEqual([
|
||||
expect(Array.from(element.querySelectorAll('.line-number')).slice(1).map(element => element.textContent.trim())).toEqual([
|
||||
'10', '11', '12', '4', '5', '6', '7', '8', '9'
|
||||
])
|
||||
expect(Array.from(element.querySelectorAll('.line')).map(element => element.textContent)).toEqual([
|
||||
@@ -59,7 +57,7 @@ describe('TextEditorComponent', () => {
|
||||
])
|
||||
|
||||
await setScrollTop(component, 2.5 * component.getLineHeight())
|
||||
expect(Array.from(element.querySelectorAll('.line-number')).map(element => element.textContent.trim())).toEqual([
|
||||
expect(Array.from(element.querySelectorAll('.line-number')).slice(1).map(element => element.textContent.trim())).toEqual([
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||
])
|
||||
expect(Array.from(element.querySelectorAll('.line')).map(element => element.textContent)).toEqual([
|
||||
@@ -107,18 +105,19 @@ describe('TextEditorComponent', () => {
|
||||
expect(component.getFirstVisibleRow()).toBe(editor.getScreenLineCount() + 1)
|
||||
})
|
||||
|
||||
it('gives the line number gutter an explicit width and height so its layout can be strictly contained', () => {
|
||||
it('gives the line number tiles an explicit width and height so their layout can be strictly contained', async () => {
|
||||
const {component, element, editor} = buildComponent({rowsPerTile: 3})
|
||||
|
||||
const gutterElement = element.querySelector('.gutter.line-numbers')
|
||||
expect(gutterElement.style.width).toBe(element.querySelector('.line-number').offsetWidth + 'px')
|
||||
expect(gutterElement.style.height).toBe(editor.getScreenLineCount() * component.measurements.lineHeight + 'px')
|
||||
expect(gutterElement.style.contain).toBe('strict')
|
||||
const gutterElement = component.refs.lineNumberGutter.element
|
||||
for (const child of gutterElement.children) {
|
||||
expect(child.offsetWidth).toBe(gutterElement.offsetWidth)
|
||||
}
|
||||
|
||||
// Tile nodes also have explicit width and height assignment
|
||||
expect(gutterElement.firstChild.style.width).toBe(element.querySelector('.line-number').offsetWidth + 'px')
|
||||
expect(gutterElement.firstChild.style.height).toBe(3 * component.measurements.lineHeight + 'px')
|
||||
expect(gutterElement.firstChild.style.contain).toBe('strict')
|
||||
editor.setText('\n'.repeat(99))
|
||||
await component.getNextUpdatePromise()
|
||||
for (const child of gutterElement.children) {
|
||||
expect(child.offsetWidth).toBe(gutterElement.offsetWidth)
|
||||
}
|
||||
})
|
||||
|
||||
it('renders dummy vertical and horizontal scrollbars when content overflows', async () => {
|
||||
@@ -994,26 +993,30 @@ describe('TextEditorComponent', () => {
|
||||
const {component, element, editor} = buildComponent()
|
||||
const {scrollContainer, gutterContainer} = component.refs
|
||||
|
||||
expect(scrollContainer.getBoundingClientRect().left).toBe(gutterContainer.getBoundingClientRect().right)
|
||||
function checkScrollContainerLeft () {
|
||||
expect(scrollContainer.getBoundingClientRect().left).toBe(Math.round(gutterContainer.getBoundingClientRect().right))
|
||||
}
|
||||
|
||||
checkScrollContainerLeft()
|
||||
const gutterA = editor.addGutter({name: 'a'})
|
||||
await component.getNextUpdatePromise()
|
||||
expect(scrollContainer.getBoundingClientRect().left).toBe(gutterContainer.getBoundingClientRect().right)
|
||||
checkScrollContainerLeft()
|
||||
|
||||
const gutterB = editor.addGutter({name: 'b'})
|
||||
await component.getNextUpdatePromise()
|
||||
expect(scrollContainer.getBoundingClientRect().left).toBe(gutterContainer.getBoundingClientRect().right)
|
||||
checkScrollContainerLeft()
|
||||
|
||||
gutterA.getElement().style.width = 100 + 'px'
|
||||
await component.getNextUpdatePromise()
|
||||
expect(scrollContainer.getBoundingClientRect().left).toBe(gutterContainer.getBoundingClientRect().right)
|
||||
checkScrollContainerLeft()
|
||||
|
||||
gutterA.destroy()
|
||||
await component.getNextUpdatePromise()
|
||||
expect(scrollContainer.getBoundingClientRect().left).toBe(gutterContainer.getBoundingClientRect().right)
|
||||
checkScrollContainerLeft()
|
||||
|
||||
gutterB.destroy()
|
||||
await component.getNextUpdatePromise()
|
||||
expect(scrollContainer.getBoundingClientRect().left).toBe(gutterContainer.getBoundingClientRect().right)
|
||||
checkScrollContainerLeft()
|
||||
})
|
||||
|
||||
it('allows the element of custom gutters to be retrieved before being rendered in the editor component', async () => {
|
||||
@@ -1858,7 +1861,7 @@ function lineNumberNodeForScreenRow (component, row) {
|
||||
const gutterElement = component.refs.lineNumberGutter.element
|
||||
const tileStartRow = component.tileStartRowForRow(row)
|
||||
const tileIndex = component.tileIndexForTileStartRow(tileStartRow)
|
||||
return gutterElement.children[tileIndex].children[row - tileStartRow]
|
||||
return gutterElement.children[tileIndex + 1].children[row - tileStartRow]
|
||||
}
|
||||
|
||||
function lineNodeForScreenRow (component, row) {
|
||||
|
||||
@@ -74,8 +74,14 @@ class TextEditorComponent {
|
||||
this.lastKeydown = null
|
||||
this.lastKeydownBeforeKeypress = null
|
||||
this.accentedCharacterMenuIsOpen = false
|
||||
this.remeasureGutterContainer = false
|
||||
this.guttersToRender = []
|
||||
this.remeasureGutterDimensions = false
|
||||
this.guttersToRender = [this.props.model.getLineNumberGutter()]
|
||||
this.lineNumbersToRender = {
|
||||
maxDigits: 2,
|
||||
numbers: [],
|
||||
keys: [],
|
||||
foldableFlags: []
|
||||
}
|
||||
this.decorationsToRender = {
|
||||
lineNumbers: new Map(),
|
||||
lines: new Map(),
|
||||
@@ -89,6 +95,9 @@ class TextEditorComponent {
|
||||
cursors: []
|
||||
}
|
||||
|
||||
this.queryGuttersToRender()
|
||||
this.queryMaxLineNumberDigits()
|
||||
|
||||
etch.updateSync(this)
|
||||
|
||||
this.observeModel()
|
||||
@@ -140,6 +149,7 @@ class TextEditorComponent {
|
||||
if (this.pendingAutoscroll) this.autoscrollVertically()
|
||||
this.populateVisibleRowRange()
|
||||
this.queryScreenLinesToRender()
|
||||
this.queryLineNumbersToRender()
|
||||
this.queryGuttersToRender()
|
||||
this.queryDecorationsToRender()
|
||||
this.shouldRenderDummyScrollbars = !this.refreshedScrollbarStyle
|
||||
@@ -150,9 +160,9 @@ class TextEditorComponent {
|
||||
measureContentDuringUpdateSync () {
|
||||
this.measureHorizontalPositions()
|
||||
this.updateAbsolutePositionedDecorations()
|
||||
if (this.remeasureGutterContainer) {
|
||||
if (this.remeasureGutterDimensions) {
|
||||
this.measureGutterDimensions()
|
||||
this.remeasureGutterContainer = false
|
||||
this.remeasureGutterDimensions = false
|
||||
}
|
||||
const wasHorizontalScrollbarVisible = this.isHorizontalScrollbarVisible()
|
||||
this.measureLongestLineWidth()
|
||||
@@ -243,25 +253,10 @@ class TextEditorComponent {
|
||||
display: 'flex'
|
||||
}
|
||||
|
||||
let gutterNodes
|
||||
let scrollHeight
|
||||
if (this.measurements) {
|
||||
innerStyle.transform = `translateY(${-this.getScrollTop()}px)`
|
||||
gutterNodes = this.guttersToRender.map((gutter) => {
|
||||
if (gutter.name === 'line-number') {
|
||||
return this.renderLineNumberGutter(gutter)
|
||||
} else {
|
||||
return $(CustomGutterComponent, {
|
||||
key: gutter,
|
||||
element: gutter.getElement(),
|
||||
name: gutter.name,
|
||||
visible: gutter.isVisible(),
|
||||
height: this.getScrollHeight(),
|
||||
decorations: this.decorationsToRender.customGutter.get(gutter.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
gutterNodes = this.renderLineNumberGutter()
|
||||
scrollHeight = this.getScrollHeight()
|
||||
}
|
||||
|
||||
return $.div(
|
||||
@@ -274,68 +269,52 @@ class TextEditorComponent {
|
||||
backgroundColor: 'inherit'
|
||||
}
|
||||
},
|
||||
$.div({style: innerStyle}, gutterNodes)
|
||||
$.div({style: innerStyle},
|
||||
this.guttersToRender.map((gutter) => {
|
||||
if (gutter.name === 'line-number') {
|
||||
return this.renderLineNumberGutter(gutter)
|
||||
} else {
|
||||
return $(CustomGutterComponent, {
|
||||
key: gutter,
|
||||
element: gutter.getElement(),
|
||||
name: gutter.name,
|
||||
visible: gutter.isVisible(),
|
||||
height: scrollHeight,
|
||||
decorations: this.decorationsToRender.customGutter.get(gutter.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
renderLineNumberGutter (gutter) {
|
||||
const {model} = this.props
|
||||
|
||||
if (!model.isLineNumberGutterVisible()) return null
|
||||
|
||||
if (this.currentFrameLineNumberGutterProps) {
|
||||
return $(LineNumberGutterComponent, this.currentFrameLineNumberGutterProps)
|
||||
}
|
||||
|
||||
const maxLineNumberDigits = Math.max(2, model.getLineCount().toString().length)
|
||||
if (!this.props.model.isLineNumberGutterVisible()) return null
|
||||
|
||||
if (this.measurements) {
|
||||
const startRow = this.getRenderedStartRow()
|
||||
const endRow = this.getRenderedEndRow()
|
||||
const renderedRowCount = this.getRenderedRowCount()
|
||||
const bufferRows = new Array(renderedRowCount)
|
||||
const foldableFlags = new Array(renderedRowCount)
|
||||
const softWrappedFlags = new Array(renderedRowCount)
|
||||
const lineNumberDecorations = new Array(renderedRowCount)
|
||||
|
||||
let previousBufferRow = (startRow > 0) ? model.bufferRowForScreenRow(startRow - 1) : -1
|
||||
for (let row = startRow; row < endRow; row++) {
|
||||
const i = row - startRow
|
||||
const bufferRow = model.bufferRowForScreenRow(row)
|
||||
bufferRows[i] = bufferRow
|
||||
softWrappedFlags[i] = bufferRow === previousBufferRow
|
||||
foldableFlags[i] = model.isFoldableAtBufferRow(bufferRow)
|
||||
lineNumberDecorations[i] = this.decorationsToRender.lineNumbers.get(row)
|
||||
previousBufferRow = bufferRow
|
||||
}
|
||||
|
||||
const rowsPerTile = this.getRowsPerTile()
|
||||
|
||||
this.currentFrameLineNumberGutterProps = {
|
||||
const {maxDigits, keys, numbers, foldableFlags} = this.lineNumbersToRender
|
||||
return $(LineNumberGutterComponent, {
|
||||
ref: 'lineNumberGutter',
|
||||
element: gutter.getElement(),
|
||||
parentComponent: this,
|
||||
startRow: this.getRenderedStartRow(),
|
||||
endRow: this.getRenderedEndRow(),
|
||||
rowsPerTile: this.getRowsPerTile(),
|
||||
maxDigits: maxDigits,
|
||||
keys: keys,
|
||||
numbers: numbers,
|
||||
foldableFlags: foldableFlags,
|
||||
decorations: this.decorationsToRender.lineNumbers,
|
||||
height: this.getScrollHeight(),
|
||||
width: this.getLineNumberGutterWidth(),
|
||||
lineHeight: this.getLineHeight(),
|
||||
startRow, endRow, rowsPerTile, maxLineNumberDigits,
|
||||
bufferRows, lineNumberDecorations, softWrappedFlags,
|
||||
foldableFlags
|
||||
}
|
||||
|
||||
return $(LineNumberGutterComponent, this.currentFrameLineNumberGutterProps)
|
||||
})
|
||||
} else {
|
||||
return $.div(
|
||||
{
|
||||
ref: 'lineNumberGutter',
|
||||
className: 'gutter line-numbers',
|
||||
attributes: {'gutter-name': 'line-number'}
|
||||
},
|
||||
$.div({className: 'line-number'},
|
||||
'0'.repeat(maxLineNumberDigits),
|
||||
$.div({className: 'icon-right'})
|
||||
)
|
||||
)
|
||||
return $(LineNumberGutterComponent, {
|
||||
ref: 'lineNumberGutter',
|
||||
element: gutter.getElement(),
|
||||
maxDigits: this.lineNumbersToRender.maxDigits
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,6 +618,51 @@ class TextEditorComponent {
|
||||
}
|
||||
}
|
||||
|
||||
queryLineNumbersToRender () {
|
||||
const {model} = this.props
|
||||
if (!model.isLineNumberGutterVisible()) return
|
||||
|
||||
this.queryMaxLineNumberDigits()
|
||||
|
||||
const startRow = this.getRenderedStartRow()
|
||||
const endRow = this.getRenderedEndRow()
|
||||
const renderedRowCount = this.getRenderedRowCount()
|
||||
|
||||
const {numbers, keys, foldableFlags} = this.lineNumbersToRender
|
||||
numbers.length = renderedRowCount
|
||||
keys.length = renderedRowCount
|
||||
foldableFlags.length = renderedRowCount
|
||||
|
||||
let previousBufferRow = (startRow > 0) ? model.bufferRowForScreenRow(startRow - 1) : -1
|
||||
let softWrapCount = 0
|
||||
for (let row = startRow; row < endRow; row++) {
|
||||
const i = row - startRow
|
||||
const bufferRow = model.bufferRowForScreenRow(row)
|
||||
if (bufferRow === previousBufferRow) {
|
||||
numbers[i] = -1
|
||||
keys[i] = bufferRow + 1 + '-' + softWrapCount++
|
||||
foldableFlags[i] = false
|
||||
} else {
|
||||
softWrapCount = 0
|
||||
numbers[i] = bufferRow + 1
|
||||
keys[i] = bufferRow + 1
|
||||
foldableFlags[i] = model.isFoldableAtBufferRow(bufferRow)
|
||||
}
|
||||
previousBufferRow = bufferRow
|
||||
}
|
||||
}
|
||||
|
||||
queryMaxLineNumberDigits () {
|
||||
const {model} = this.props
|
||||
if (model.isLineNumberGutterVisible()) {
|
||||
const maxDigits = Math.max(2, model.getLineCount().toString().length)
|
||||
if (maxDigits !== this.lineNumbersToRender.maxDigits) {
|
||||
this.remeasureGutterDimensions = true
|
||||
this.lineNumbersToRender.maxDigits = maxDigits
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderedScreenLineForRow (row) {
|
||||
return this.renderedScreenLines[row - this.getRenderedStartRow()]
|
||||
}
|
||||
@@ -648,11 +672,11 @@ class TextEditorComponent {
|
||||
this.guttersToRender = this.props.model.getGutters()
|
||||
|
||||
if (!oldGuttersToRender || oldGuttersToRender.length !== this.guttersToRender.length) {
|
||||
this.remeasureGutterContainer = true
|
||||
this.remeasureGutterDimensions = true
|
||||
} else {
|
||||
for (let i = 0, length = this.guttersToRender.length; i < length; i++) {
|
||||
if (this.guttersToRender[i] !== oldGuttersToRender[i]) {
|
||||
this.remeasureGutterContainer = true
|
||||
this.remeasureGutterDimensions = true
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -1027,7 +1051,6 @@ class TextEditorComponent {
|
||||
}
|
||||
|
||||
didResizeGutterContainer () {
|
||||
console.log('didResizeGutterContainer');
|
||||
if (this.measureGutterDimensions()) {
|
||||
this.scheduleUpdate()
|
||||
}
|
||||
@@ -1476,10 +1499,10 @@ class TextEditorComponent {
|
||||
}
|
||||
|
||||
if (this.refs.lineNumberGutter) {
|
||||
const lineNumberGutterWidth = this.refs.lineNumberGutter.offsetWidth
|
||||
const lineNumberGutterWidth = this.refs.lineNumberGutter.element.offsetWidth
|
||||
if (lineNumberGutterWidth !== this.measurements.lineNumberGutterWidth) {
|
||||
dimensionsChanged = true
|
||||
this.measurements.lineNumberGutterWidth = this.refs.lineNumberGutter.offsetWidth
|
||||
this.measurements.lineNumberGutterWidth = lineNumberGutterWidth
|
||||
}
|
||||
} else {
|
||||
this.measurements.lineNumberGutterWidth = 0
|
||||
@@ -2068,85 +2091,81 @@ class LineNumberGutterComponent {
|
||||
render () {
|
||||
const {
|
||||
parentComponent, height, width, lineHeight, startRow, endRow, rowsPerTile,
|
||||
maxLineNumberDigits, bufferRows, softWrappedFlags, foldableFlags,
|
||||
lineNumberDecorations
|
||||
maxDigits, keys, numbers, foldableFlags, decorations
|
||||
} = this.props
|
||||
|
||||
const renderedTileCount = parentComponent.getRenderedTileCount()
|
||||
const children = new Array(renderedTileCount)
|
||||
const tileHeight = rowsPerTile * lineHeight + 'px'
|
||||
const tileWidth = width + 'px'
|
||||
let children = null
|
||||
|
||||
let softWrapCount = 0
|
||||
for (let tileStartRow = startRow; tileStartRow < endRow; tileStartRow += rowsPerTile) {
|
||||
const tileEndRow = Math.min(endRow, tileStartRow + rowsPerTile)
|
||||
const tileChildren = new Array(tileEndRow - tileStartRow)
|
||||
for (let row = tileStartRow; row < tileEndRow; row++) {
|
||||
const i = row - startRow
|
||||
const bufferRow = bufferRows[i]
|
||||
const softWrapped = softWrappedFlags[i]
|
||||
const foldable = foldableFlags[i]
|
||||
let key, lineNumber
|
||||
let className = 'line-number'
|
||||
if (softWrapped) {
|
||||
softWrapCount++
|
||||
key = `${bufferRow}-${softWrapCount}`
|
||||
lineNumber = '•'
|
||||
} else {
|
||||
softWrapCount = 0
|
||||
key = bufferRow
|
||||
lineNumber = (bufferRow + 1).toString()
|
||||
if (numbers) {
|
||||
const renderedTileCount = parentComponent.getRenderedTileCount()
|
||||
children = new Array(renderedTileCount)
|
||||
const tileHeight = rowsPerTile * lineHeight + 'px'
|
||||
const tileWidth = width + 'px'
|
||||
|
||||
let softWrapCount = 0
|
||||
for (let tileStartRow = startRow; tileStartRow < endRow; tileStartRow += rowsPerTile) {
|
||||
const tileEndRow = Math.min(endRow, tileStartRow + rowsPerTile)
|
||||
const tileChildren = new Array(tileEndRow - tileStartRow)
|
||||
for (let row = tileStartRow; row < tileEndRow; row++) {
|
||||
const i = row - startRow
|
||||
const key = keys[i]
|
||||
const foldable = foldableFlags[i]
|
||||
let number = numbers[i]
|
||||
|
||||
let className = 'line-number'
|
||||
if (foldable) className += ' foldable'
|
||||
|
||||
const decorationsForRow = decorations.get(row)
|
||||
if (decorationsForRow) className += ' ' + decorationsForRow
|
||||
|
||||
if (number === -1) number = '•'
|
||||
number = NBSP_CHARACTER.repeat(maxDigits - number.length) + number
|
||||
|
||||
tileChildren[row - tileStartRow] = $.div({key, className},
|
||||
number,
|
||||
$.div({className: 'icon-right'})
|
||||
)
|
||||
}
|
||||
|
||||
const lineNumberDecoration = lineNumberDecorations[i]
|
||||
if (lineNumberDecoration != null) className += ' ' + lineNumberDecoration
|
||||
const tileIndex = parentComponent.tileIndexForTileStartRow(tileStartRow)
|
||||
const top = tileStartRow * lineHeight
|
||||
|
||||
lineNumber = NBSP_CHARACTER.repeat(maxLineNumberDigits - lineNumber.length) + lineNumber
|
||||
|
||||
tileChildren[row - tileStartRow] = $.div({key, className},
|
||||
lineNumber,
|
||||
$.div({className: 'icon-right'})
|
||||
)
|
||||
children[tileIndex] = $.div({
|
||||
key: tileIndex,
|
||||
style: {
|
||||
contain: 'strict',
|
||||
overflow: 'hidden',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
height: tileHeight,
|
||||
width: tileWidth,
|
||||
willChange: 'transform',
|
||||
transform: `translateY(${top}px)`,
|
||||
backgroundColor: 'inherit'
|
||||
}
|
||||
}, ...tileChildren)
|
||||
}
|
||||
|
||||
const tileIndex = parentComponent.tileIndexForTileStartRow(tileStartRow)
|
||||
const top = tileStartRow * lineHeight
|
||||
|
||||
children[tileIndex] = $.div({
|
||||
key: tileIndex,
|
||||
on: {
|
||||
mousedown: this.didMouseDown
|
||||
},
|
||||
style: {
|
||||
contain: 'strict',
|
||||
overflow: 'hidden',
|
||||
position: 'absolute',
|
||||
height: tileHeight,
|
||||
width: tileWidth,
|
||||
willChange: 'transform',
|
||||
transform: `translateY(${top}px)`,
|
||||
backgroundColor: 'inherit'
|
||||
}
|
||||
}, ...tileChildren)
|
||||
}
|
||||
|
||||
return $.div(
|
||||
{
|
||||
className: 'gutter line-numbers',
|
||||
attributes: {'gutter-name': 'line-number'},
|
||||
style: {
|
||||
contain: 'strict',
|
||||
overflow: 'hidden',
|
||||
height: height + 'px',
|
||||
width: tileWidth
|
||||
}
|
||||
style: {position: 'relative'},
|
||||
on: {
|
||||
mousedown: this.didMouseDown
|
||||
},
|
||||
},
|
||||
...children
|
||||
$.div({key: 'placeholder', className: 'line-number', style: {visibility: 'hidden'}},
|
||||
'0'.repeat(maxDigits),
|
||||
$.div({className: 'icon-right'})
|
||||
),
|
||||
children
|
||||
)
|
||||
}
|
||||
|
||||
shouldUpdate (newProps) {
|
||||
return true
|
||||
const oldProps = this.props
|
||||
|
||||
if (oldProps.height !== newProps.height) return true
|
||||
@@ -2155,11 +2174,11 @@ class LineNumberGutterComponent {
|
||||
if (oldProps.startRow !== newProps.startRow) return true
|
||||
if (oldProps.endRow !== newProps.endRow) return true
|
||||
if (oldProps.rowsPerTile !== newProps.rowsPerTile) return true
|
||||
if (oldProps.maxLineNumberDigits !== newProps.maxLineNumberDigits) return true
|
||||
if (!arraysEqual(oldProps.bufferRows, newProps.bufferRows)) return true
|
||||
if (!arraysEqual(oldProps.softWrappedFlags, newProps.softWrappedFlags)) return true
|
||||
if (oldProps.maxDigits !== newProps.maxDigits) return true
|
||||
if (!arraysEqual(oldProps.keys, newProps.keys)) return true
|
||||
if (!arraysEqual(oldProps.numbers, newProps.numbers)) return true
|
||||
if (!arraysEqual(oldProps.foldableFlags, newProps.foldableFlags)) return true
|
||||
if (!arraysEqual(oldProps.lineNumberDecorations, newProps.lineNumberDecorations)) return true
|
||||
if (!arraysEqual(oldProps.decorations, newProps.decorations)) return true
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -2671,7 +2671,6 @@ class TextEditor extends Model
|
||||
_.last(@selections)
|
||||
|
||||
getSelectionAtScreenPosition: (position) ->
|
||||
debugger if global.debug
|
||||
markers = @selectionsMarkerLayer.findMarkers(containsScreenPosition: position)
|
||||
if markers.length > 0
|
||||
@cursorsByMarkerId.get(markers[0].id).selection
|
||||
@@ -3405,6 +3404,9 @@ class TextEditor extends Model
|
||||
getGutters: ->
|
||||
@gutterContainer.getGutters()
|
||||
|
||||
getLineNumberGutter: ->
|
||||
@lineNumberGutter
|
||||
|
||||
# Essential: Get the gutter with the given name.
|
||||
#
|
||||
# Returns a {Gutter}, or `null` if no gutter exists for the given name.
|
||||
|
||||
Reference in New Issue
Block a user