diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index 31db65760..d832ab606 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -2830,6 +2830,43 @@ describe('TextEditorComponent', () => { }) }) + describe('screenPositionForPixelPositionSync', () => { + it('returns the screen position for the given pixel position, regardless of whether or not it is currently on screen', async () => { + const {component, element, editor} = buildComponent({rowsPerTile: 2, autoHeight: false}) + await setEditorHeightInLines(component, 3) + await setScrollTop(component, 3 * component.getLineHeight()) + const {component: referenceComponent} = buildComponent() + + { + const pixelPosition = referenceComponent.pixelPositionForScreenPositionSync({row: 0, column: 0}) + pixelPosition.top += component.getLineHeight() / 3 + pixelPosition.left += component.getBaseCharacterWidth() / 3 + expect(component.screenPositionForPixelPositionSync(pixelPosition)).toEqual([0, 0]) + } + + { + const pixelPosition = referenceComponent.pixelPositionForScreenPositionSync({row: 0, column: 5}) + pixelPosition.top += component.getLineHeight() / 3 + pixelPosition.left += component.getBaseCharacterWidth() / 3 + expect(component.screenPositionForPixelPositionSync(pixelPosition)).toEqual([0, 5]) + } + + { + const pixelPosition = referenceComponent.pixelPositionForScreenPositionSync({row: 5, column: 7}) + pixelPosition.top += component.getLineHeight() / 3 + pixelPosition.left += component.getBaseCharacterWidth() / 3 + expect(component.screenPositionForPixelPositionSync(pixelPosition)).toEqual([5, 7]) + } + + { + const pixelPosition = referenceComponent.pixelPositionForScreenPositionSync({row: 12, column: 1}) + pixelPosition.top += component.getLineHeight() / 3 + pixelPosition.left += component.getBaseCharacterWidth() / 3 + expect(component.screenPositionForPixelPositionSync(pixelPosition)).toEqual([12, 1]) + } + }) + }) + describe('model methods that delegate to the component / element', () => { it('delegates setHeight and getHeight to the component', async () => { const {component, element, editor} = buildComponent({autoHeight: false}) diff --git a/src/text-editor-component.js b/src/text-editor-component.js index 46eb9b164..6bed15a52 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -152,6 +152,22 @@ class TextEditorComponent { return {top, left} } + screenPositionForPixelPositionSync (pixelPosition) { + const {model} = this.props + + const row = Math.max(0, Math.min( + this.rowForPixelPosition(pixelPosition.top), + model.getApproximateScreenLineCount() - 1 + )) + + if (!this.renderedScreenLineForRow(row)) { + this.requestExtraLineToMeasure(row, model.screenLineForScreenRow(row)) + this.updateSyncBeforeMeasuringContent() + this.measureContentDuringUpdateSync() + } + return this.screenPositionForPixelPosition(pixelPosition) + } + scheduleUpdate (nextUpdateOnlyBlinksCursors = false) { if (!this.visible) return diff --git a/src/text-editor-element.js b/src/text-editor-element.js index f87ca0845..428c44ee5 100644 --- a/src/text-editor-element.js +++ b/src/text-editor-element.js @@ -201,6 +201,10 @@ class TextEditorElement extends HTMLElement { return this.getComponent().pixelPositionForScreenPositionSync(screenPosition) } + screenPositionForPixelPosition (pixelPosition) { + return this.getComponent().screenPositionForPixelPositionSync(pixelPosition) + } + getComponent () { if (!this.component) { this.component = new TextEditorComponent({