From cf19d0efd537757a1bd8706e349f119dff7061b3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Mar 2017 15:10:01 -0600 Subject: [PATCH] Autoscroll vertically when click-dragging the line number gutter --- spec/text-editor-component-spec.js | 59 ++++++++++++++++++++++++++++++ src/text-editor-component.js | 5 ++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index df5a2287f..c532c1518 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -1144,6 +1144,65 @@ describe('TextEditorComponent', () => { [[2, 0], [4, 4]] ]) }) + + it('autoscrolls the content when dragging near the edge of the screen', async () => { + const {component, editor} = buildComponent({width: 200, height: 200}) + const {scroller} = component.refs + spyOn(component, 'handleMouseDragUntilMouseUp') + + let previousScrollTop = 0 + let previousScrollLeft = 0 + function assertScrolledDown () { + expect(scroller.scrollTop).toBeGreaterThan(previousScrollTop) + previousScrollTop = scroller.scrollTop + expect(scroller.scrollLeft).toBe(previousScrollLeft) + previousScrollLeft = scroller.scrollLeft + } + + function assertScrolledUp () { + expect(scroller.scrollTop).toBeLessThan(previousScrollTop) + previousScrollTop = scroller.scrollTop + expect(scroller.scrollLeft).toBe(previousScrollLeft) + previousScrollLeft = scroller.scrollLeft + } + + component.didMouseDownOnLineNumberGutter({detail: 1, button: 0, clientX: 0, clientY: 100}) + const {didDrag, didStopDragging} = component.handleMouseDragUntilMouseUp.argsForCall[0][0] + didDrag({clientX: 199, clientY: 199}) + assertScrolledDown() + didDrag({clientX: 199, clientY: 199}) + assertScrolledDown() + didDrag({clientX: 199, clientY: 199}) + assertScrolledDown() + didDrag({clientX: component.getGutterContainerWidth() + 1, clientY: 1}) + assertScrolledUp() + didDrag({clientX: component.getGutterContainerWidth() + 1, clientY: 1}) + assertScrolledUp() + didDrag({clientX: component.getGutterContainerWidth() + 1, clientY: 1}) + assertScrolledUp() + + // Don't artificially update scroll measurements beyond the minimum or + // maximum possible scroll positions + expect(scroller.scrollTop).toBe(0) + expect(scroller.scrollLeft).toBe(0) + didDrag({clientX: component.getGutterContainerWidth() + 1, clientY: 1}) + expect(component.measurements.scrollTop).toBe(0) + expect(scroller.scrollTop).toBe(0) + expect(component.measurements.scrollLeft).toBe(0) + expect(scroller.scrollLeft).toBe(0) + + const maxScrollTop = scroller.scrollHeight - scroller.clientHeight + const maxScrollLeft = scroller.scrollWidth - scroller.clientWidth + scroller.scrollTop = maxScrollTop + scroller.scrollLeft = maxScrollLeft + await component.getNextUpdatePromise() + + didDrag({clientX: 199, clientY: 199}) + didDrag({clientX: 199, clientY: 199}) + didDrag({clientX: 199, clientY: 199}) + expect(component.measurements.scrollTop).toBe(maxScrollTop) + expect(component.measurements.scrollLeft).toBe(maxScrollLeft) + }) }) }) }) diff --git a/src/text-editor-component.js b/src/text-editor-component.js index 0a8cf4125..aef4b9b54 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -849,6 +849,7 @@ class TextEditorComponent { const initialScreenRange = model.screenRangeForBufferRange(initialBufferRange) this.handleMouseDragUntilMouseUp({ didDrag: (event) => { + this.autoscrollOnMouseDrag(event, true) const dragRow = this.screenPositionForMouseEvent(event).row const draggedLineScreenRange = Range(Point(dragRow, 0), Point(dragRow + 1, 0)) model.getLastSelection().setScreenRange(draggedLineScreenRange.union(initialScreenRange), { @@ -899,7 +900,7 @@ class TextEditorComponent { window.addEventListener('mouseup', didMouseUp) } - autoscrollOnMouseDrag ({clientX, clientY}) { + autoscrollOnMouseDrag ({clientX, clientY}, verticalOnly = false) { let {top, bottom, left, right} = this.refs.scroller.getBoundingClientRect() top += MOUSE_DRAG_AUTOSCROLL_MARGIN bottom -= MOUSE_DRAG_AUTOSCROLL_MARGIN @@ -935,7 +936,7 @@ class TextEditorComponent { } } - if (xDelta != null) { + if (!verticalOnly && xDelta != null) { const scaledDelta = scaleMouseDragAutoscrollDelta(xDelta) * xDirection const newScrollLeft = this.constrainScrollLeft(this.measurements.scrollLeft + scaledDelta) if (newScrollLeft !== this.measurements.scrollLeft) {