mirror of
https://github.com/atom/atom.git
synced 2026-01-24 06:18:03 -05:00
Fix cursor positioning around fold markers
This commit is contained in:
@@ -331,6 +331,20 @@ describe('TextEditorComponent', () => {
|
||||
expect(element.querySelector('.cursor').offsetWidth).toBe(Math.round(component.getBaseCharacterWidth()))
|
||||
})
|
||||
|
||||
it('positions and sizes cursors correctly when they are located next to a fold marker', async () => {
|
||||
const {component, element, editor} = buildComponent()
|
||||
editor.foldBufferRange([[0, 3], [0, 6]])
|
||||
|
||||
editor.setCursorScreenPosition([0, 3])
|
||||
await component.getNextUpdatePromise()
|
||||
const cursor = element.querySelector('.cursor')
|
||||
verifyCursorPosition(component, element.querySelector('.cursor'), 0, 3)
|
||||
|
||||
editor.setCursorScreenPosition([0, 4])
|
||||
await component.getNextUpdatePromise()
|
||||
verifyCursorPosition(component, element.querySelector('.cursor'), 0, 4)
|
||||
})
|
||||
|
||||
it('places the hidden input element at the location of the last cursor if it is visible', async () => {
|
||||
const {component, element, editor} = buildComponent({height: 60, width: 120, rowsPerTile: 2})
|
||||
const {hiddenInput} = component.refs
|
||||
@@ -2893,7 +2907,7 @@ async function setEditorWidthInCharacters (component, widthInCharacters) {
|
||||
function verifyCursorPosition (component, cursorNode, row, column) {
|
||||
const rect = cursorNode.getBoundingClientRect()
|
||||
expect(Math.round(rect.top)).toBe(clientTopForLine(component, row))
|
||||
expect(Math.round(rect.left)).toBe(clientLeftForCharacter(component, row, column))
|
||||
expect(Math.round(rect.left)).toBe(Math.round(clientLeftForCharacter(component, row, column)))
|
||||
}
|
||||
|
||||
function clientTopForLine (component, row) {
|
||||
@@ -2905,7 +2919,7 @@ function clientLeftForCharacter (component, row, column) {
|
||||
let textNodeStartColumn = 0
|
||||
for (const textNode of textNodes) {
|
||||
const textNodeEndColumn = textNodeStartColumn + textNode.textContent.length
|
||||
if (column <= textNodeEndColumn) {
|
||||
if (column < textNodeEndColumn) {
|
||||
const range = document.createRange()
|
||||
range.setStart(textNode, column - textNodeStartColumn)
|
||||
range.setEnd(textNode, column - textNodeStartColumn)
|
||||
@@ -2913,6 +2927,12 @@ function clientLeftForCharacter (component, row, column) {
|
||||
}
|
||||
textNodeStartColumn = textNodeEndColumn
|
||||
}
|
||||
|
||||
const lastTextNode = textNodes[textNodes.length - 1]
|
||||
const range = document.createRange()
|
||||
range.setStart(lastTextNode, 0)
|
||||
range.setEnd(lastTextNode, lastTextNode.textContent.length)
|
||||
return range.getBoundingClientRect().right
|
||||
}
|
||||
|
||||
function clientPositionForCharacter (component, row, column) {
|
||||
|
||||
@@ -1981,30 +1981,33 @@ class TextEditorComponent {
|
||||
let lineNodeClientLeft = -1
|
||||
let textNodeStartColumn = 0
|
||||
let textNodesIndex = 0
|
||||
let lastTextNodeRight = null
|
||||
|
||||
columnLoop: // eslint-disable-line no-labels
|
||||
for (let columnsIndex = 0; columnsIndex < columnsToMeasure.length; columnsIndex++) {
|
||||
const nextColumnToMeasure = columnsToMeasure[columnsIndex]
|
||||
while (textNodesIndex < textNodes.length) {
|
||||
const nextColumnToMeasure = columnsToMeasure[columnsIndex]
|
||||
if (nextColumnToMeasure === 0) {
|
||||
positions.set(0, 0)
|
||||
continue columnLoop // eslint-disable-line no-labels
|
||||
}
|
||||
if (nextColumnToMeasure >= lineNode.textContent.length) {
|
||||
|
||||
}
|
||||
if (positions.has(nextColumnToMeasure)) continue columnLoop // eslint-disable-line no-labels
|
||||
const textNode = textNodes[textNodesIndex]
|
||||
const textNodeEndColumn = textNodeStartColumn + textNode.textContent.length
|
||||
|
||||
if (nextColumnToMeasure <= textNodeEndColumn) {
|
||||
if (nextColumnToMeasure < textNodeEndColumn) {
|
||||
let clientPixelPosition
|
||||
if (nextColumnToMeasure === textNodeStartColumn) {
|
||||
clientPixelPosition = clientRectForRange(textNode, 0, 1).left
|
||||
} else {
|
||||
clientPixelPosition = clientRectForRange(textNode, 0, nextColumnToMeasure - textNodeStartColumn).right
|
||||
}
|
||||
if (lineNodeClientLeft === -1) lineNodeClientLeft = lineNode.getBoundingClientRect().left
|
||||
|
||||
if (lineNodeClientLeft === -1) {
|
||||
lineNodeClientLeft = lineNode.getBoundingClientRect().left
|
||||
}
|
||||
|
||||
positions.set(nextColumnToMeasure, Math.round(clientPixelPosition - lineNodeClientLeft))
|
||||
continue columnLoop // eslint-disable-line no-labels
|
||||
} else {
|
||||
@@ -2012,6 +2015,17 @@ class TextEditorComponent {
|
||||
textNodeStartColumn = textNodeEndColumn
|
||||
}
|
||||
}
|
||||
|
||||
if (lastTextNodeRight == null) {
|
||||
const lastTextNode = textNodes[textNodes.length - 1]
|
||||
lastTextNodeRight = clientRectForRange(lastTextNode, 0, lastTextNode.textContent.length).right
|
||||
}
|
||||
|
||||
if (lineNodeClientLeft === -1) {
|
||||
lineNodeClientLeft = lineNode.getBoundingClientRect().left
|
||||
}
|
||||
|
||||
positions.set(nextColumnToMeasure, lastTextNodeRight - lineNodeClientLeft)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user