From f1276f59ded8ae5356dd0dff2bed5b1dc808e3c3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 1 Sep 2015 10:43:45 -0600 Subject: [PATCH] Autoscroll when mouse gets close to the edge of the editor scroll view Previously, we required the cursor to exceed the bounds of the editor, but that makes it impossible to scroll when the window is maximized. --- spec/text-editor-component-spec.coffee | 19 ++++++++++--------- src/text-editor-component.coffee | 22 +++++++++++++--------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 3feb70da7..7e1b2fd64 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -1850,7 +1850,7 @@ describe "TextEditorComponent", -> nextAnimationFrame() expect(editor.getSelectedScreenRange()).toEqual [[2, 4], [10, 0]] - it "autoscrolls when the cursor exceeds the boundaries of the editor", -> + it "autoscrolls when the cursor approaches the boundaries of the editor", -> wrapperNode.style.height = '100px' wrapperNode.style.width = '100px' component.measureDimensions() @@ -1860,26 +1860,26 @@ describe "TextEditorComponent", -> expect(editor.getScrollLeft()).toBe(0) linesNode.dispatchEvent(buildMouseEvent('mousedown', {clientX: 0, clientY: 0}, which: 1)) - linesNode.dispatchEvent(buildMouseEvent('mousemove', {clientX: 150, clientY: 50}, which: 1)) + linesNode.dispatchEvent(buildMouseEvent('mousemove', {clientX: 100, clientY: 50}, which: 1)) nextAnimationFrame() expect(editor.getScrollTop()).toBe(0) expect(editor.getScrollLeft()).toBeGreaterThan(0) - linesNode.dispatchEvent(buildMouseEvent('mousemove', {clientX: 150, clientY: 150}, which: 1)) + linesNode.dispatchEvent(buildMouseEvent('mousemove', {clientX: 100, clientY: 100}, which: 1)) nextAnimationFrame() expect(editor.getScrollTop()).toBeGreaterThan(0) previousScrollTop = editor.getScrollTop() previousScrollLeft = editor.getScrollLeft() - linesNode.dispatchEvent(buildMouseEvent('mousemove', {clientX: -20, clientY: 50}, which: 1)) + linesNode.dispatchEvent(buildMouseEvent('mousemove', {clientX: 10, clientY: 50}, which: 1)) nextAnimationFrame() expect(editor.getScrollTop()).toBe(previousScrollTop) expect(editor.getScrollLeft()).toBeLessThan(previousScrollLeft) - linesNode.dispatchEvent(buildMouseEvent('mousemove', {clientX: -20, clientY: -20}, which: 1)) + linesNode.dispatchEvent(buildMouseEvent('mousemove', {clientX: 10, clientY: 10}, which: 1)) nextAnimationFrame() expect(editor.getScrollTop()).toBeLessThan(previousScrollTop) @@ -1995,7 +1995,7 @@ describe "TextEditorComponent", -> linesNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenPosition([8, 4]), which: 1)) nextAnimationFrame() - expect(editor.getSelectedScreenRange()).toEqual [[5, 0], [9, 0]] + expect(editor.getSelectedScreenRange()).toEqual [[5, 0], [8, 0]] expect(editor.getScrollTop()).toBe maximalScrollTop # does not autoscroll upward (regression) linesNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenPosition([9, 3]), which: 1)) @@ -2086,7 +2086,7 @@ describe "TextEditorComponent", -> nextAnimationFrame() expect(editor.getLastSelection().isReversed()).toBe false - it "autoscrolls when the cursor exceeds the top or bottom of the editor", -> + it "autoscrolls when the cursor approaches the top or bottom of the editor", -> wrapperNode.style.height = 6 * lineHeightInPixels + 'px' component.measureDimensions() nextAnimationFrame() @@ -2100,11 +2100,12 @@ describe "TextEditorComponent", -> expect(editor.getScrollTop()).toBeGreaterThan 0 maxScrollTop = editor.getScrollTop() - gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(5))) + + gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(10))) nextAnimationFrame() expect(editor.getScrollTop()).toBe maxScrollTop - gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(2))) + gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(7))) nextAnimationFrame() expect(editor.getScrollTop()).toBeLessThan maxScrollTop diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index fce46f35c..8ff7a0d77 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -545,20 +545,24 @@ class TextEditorComponent disposables.dispose() autoscroll = (mouseClientPosition) => - editorClientRect = @domNode.getBoundingClientRect() + {top, bottom, left, right} = @scrollViewNode.getBoundingClientRect() + top += 30 + bottom -= 30 + left += 30 + right -= 30 - if mouseClientPosition.clientY < editorClientRect.top - mouseYDelta = editorClientRect.top - mouseClientPosition.clientY + if mouseClientPosition.clientY < top + mouseYDelta = top - mouseClientPosition.clientY yDirection = -1 - else if mouseClientPosition.clientY > editorClientRect.bottom - mouseYDelta = mouseClientPosition.clientY - editorClientRect.bottom + else if mouseClientPosition.clientY > bottom + mouseYDelta = mouseClientPosition.clientY - bottom yDirection = 1 - if mouseClientPosition.clientX < editorClientRect.left - mouseXDelta = editorClientRect.left - mouseClientPosition.clientX + if mouseClientPosition.clientX < left + mouseXDelta = left - mouseClientPosition.clientX xDirection = -1 - else if mouseClientPosition.clientX > editorClientRect.right - mouseXDelta = mouseClientPosition.clientX - editorClientRect.right + else if mouseClientPosition.clientX > right + mouseXDelta = mouseClientPosition.clientX - right xDirection = 1 if mouseYDelta?