From 3a433f734caaff8224611d9d9b0ce402fee3f7d7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sun, 6 Apr 2014 13:34:50 -0600 Subject: [PATCH] Move the cursor on single click --- spec/editor-component-spec.coffee | 16 ++++++++++++++++ src/display-buffer.coffee | 19 +++++++++++++++++++ src/editor-component.coffee | 13 ++++++++++++- src/editor.coffee | 5 ++--- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 7e59739d3..6c034448e 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -162,6 +162,22 @@ describe "EditorComponent", -> expect(region3Rect.left).toBe 0 expect(region3Rect.width).toBe 10 * charWidth + describe "mouse interactions", -> + clientCoordinatesForScreenPosition = (screenPosition) -> + positionOffset = editor.pixelPositionForScreenPosition(screenPosition) + editorClientRect = node.getBoundingClientRect() + clientX = editorClientRect.left + positionOffset.left + clientY = editorClientRect.top + positionOffset.top - editor.getScrollTop() + {clientX, clientY} + + describe "when a non-folded line is single-clicked", -> + it "moves the cursor to the nearest row and column", -> + node.style.height = 4.5 * lineHeightInPixels + 'px' + component.updateAllDimensions() + editor.setScrollTop(3.5 * lineHeightInPixels) + component.onMouseDown(clientCoordinatesForScreenPosition([4, 8])) + expect(editor.getCursorScreenPosition()).toEqual [4, 8] + it "transfers focus to the hidden input", -> expect(document.activeElement).toBe document.body node.focus() diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index cc1d2c362..8da7af7f0 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -383,6 +383,25 @@ class DisplayBuffer extends Model column++ {top, left} + screenPositionForPixelPosition: (pixelPosition) -> + targetTop = pixelPosition.top + targetLeft = pixelPosition.left + row = Math.floor(targetTop / @getLineHeight()) + row = Math.min(row, @getLastRow()) + row = Math.max(0, row) + + left = 0 + column = 0 + for token in @lineForRow(row).tokens + charWidths = @getScopedCharWidths(token.scopes) + for char in token.value + charWidth = charWidths[char] ? defaultCharWidth + break if targetLeft <= left + (charWidth / 2) + left += charWidth + column++ + + new Point(row, column) + # Gets the number of screen lines. # # Returns a {Number}. diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 2f411e78d..80acec657 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -38,7 +38,7 @@ EditorCompont = React.createClass height = editor.getScrollHeight() WebkitTransform = "translateY(#{-editor.getScrollTop()}px)" - div className: 'scrollable-content', style: {height, WebkitTransform}, + div className: 'scrollable-content', style: {height, WebkitTransform}, onMouseDown: @onMouseDown, @renderCursors() @renderVisibleLines() @renderUnderlayer() @@ -267,6 +267,17 @@ EditorCompont = React.createClass @refs.verticalScrollbar.getDOMNode().scrollTop -= event.wheelDeltaY event.preventDefault() + onMouseDown: (event) -> + {editor} = @props + {clientX, clientY} = event + editorClientRect = @refs.scrollView.getDOMNode().getBoundingClientRect() + + pixelPosition = + top: clientY - editorClientRect.top + editor.getScrollTop() + left: clientX - editorClientRect.left + screenPosition = editor.screenPositionForPixelPosition(pixelPosition) + editor.setCursorScreenPosition(screenPosition) + clearVisibleRowOverrides: -> @visibleRowOverrides = null @forceUpdate() diff --git a/src/editor.coffee b/src/editor.coffee index e4dfeaa62..c841c4952 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -153,7 +153,8 @@ class Editor extends Model @delegatesMethods 'setLineHeight', 'getLineHeight', 'setDefaultCharWidth', 'setHeight', 'getHeight', 'setWidth', 'getWidth', 'setScrollTop', 'getScrollTop', 'getScrollBottom', 'setScrollBottom', 'setScrollLeft', 'getScrollLeft', 'getScrollHeight', 'getVisibleRowRange', - 'intersectsVisibleRowRange', 'selectionIntersectsVisibleRowRange', toProperty: 'displayBuffer' + 'intersectsVisibleRowRange', 'selectionIntersectsVisibleRowRange', 'pixelPositionForScreenPosition', + 'screenPositionForPixelPosition', toProperty: 'displayBuffer' @delegatesProperties '$lineHeight', '$defaultCharWidth', '$height', '$width', '$scrollTop', '$scrollLeft', toProperty: 'displayBuffer' @@ -512,8 +513,6 @@ class Editor extends Model # this editor. shouldPromptToSave: -> @isModified() and not @buffer.hasMultipleEditors() - pixelPositionForScreenPosition: (screenPosition) -> @displayBuffer.pixelPositionForScreenPosition(screenPosition) - # Public: Convert a position in buffer-coordinates to screen-coordinates. # # The position is clipped via {::clipBufferPosition} prior to the conversion.