diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 11f46ed8e..e9c68d638 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -1098,6 +1098,19 @@ describe "Editor", -> expect(editor.getSelection().isEmpty()).toBeTruthy() expect(cursorView).toBeVisible() + describe "when the editor is using a variable-width font", -> + beforeEach -> + editor.setFontFamily('sans-serif') + + afterEach -> + editor.clearFontFamily() + + it "correctly positions the cursor", -> + editor.setCursorBufferPosition([3, 30]) + expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 178} + editor.setCursorBufferPosition([3, Infinity]) + expect(editor.getCursorView().position()).toEqual {top: 3 * editor.lineHeight, left: 353} + describe "autoscrolling", -> it "only autoscrolls when the last cursor is moved", -> editor.setCursorBufferPosition([11,0]) diff --git a/src/app/editor.coffee b/src/app/editor.coffee index e6412359b..48690aab6 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -1184,8 +1184,31 @@ class Editor extends View @pixelPositionForScreenPosition(@screenPositionForBufferPosition(position)) pixelPositionForScreenPosition: (position) -> - position = Point.fromObject(position) - { top: position.row * @lineHeight, left: position.column * @charWidth } + {row, column} = Point.fromObject(position) + [lineElement] = @buildLineElementsForScreenRows(row, row) + @renderedLines.append(lineElement) + left = @positionLeftForLineAndColumn(lineElement, column) + @renderedLines[0].removeChild(lineElement) + { top: row * @lineHeight, left: left } + + positionLeftForLineAndColumn: (lineElement, column) -> + return 0 if column is 0 + + delta = 0 + iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, acceptNode: -> NodeFilter.FILTER_ACCEPT) + while textNode = iterator.nextNode() + nextDelta = delta + textNode.textContent.length + if nextDelta >= column + offset = column - delta + break + delta = nextDelta + + range = document.createRange() + range.setEnd(textNode, offset) + range.collapse() + leftPixels = range.getClientRects()[0].left - @scrollView.offset().left + @scrollView.scrollLeft() + range.detach() + leftPixels pixelOffsetForScreenPosition: (position) -> {top, left} = @pixelPositionForScreenPosition(position)