Autoscroll vertically when click-dragging the line number gutter

This commit is contained in:
Nathan Sobo 2017-03-14 15:10:01 -06:00 committed by Antonio Scandurra
parent 6e9a9ef43c
commit cf19d0efd5
2 changed files with 62 additions and 2 deletions

View File

@ -1144,6 +1144,65 @@ describe('TextEditorComponent', () => {
[[2, 0], [4, 4]] [[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)
})
}) })
}) })
}) })

View File

@ -849,6 +849,7 @@ class TextEditorComponent {
const initialScreenRange = model.screenRangeForBufferRange(initialBufferRange) const initialScreenRange = model.screenRangeForBufferRange(initialBufferRange)
this.handleMouseDragUntilMouseUp({ this.handleMouseDragUntilMouseUp({
didDrag: (event) => { didDrag: (event) => {
this.autoscrollOnMouseDrag(event, true)
const dragRow = this.screenPositionForMouseEvent(event).row const dragRow = this.screenPositionForMouseEvent(event).row
const draggedLineScreenRange = Range(Point(dragRow, 0), Point(dragRow + 1, 0)) const draggedLineScreenRange = Range(Point(dragRow, 0), Point(dragRow + 1, 0))
model.getLastSelection().setScreenRange(draggedLineScreenRange.union(initialScreenRange), { model.getLastSelection().setScreenRange(draggedLineScreenRange.union(initialScreenRange), {
@ -899,7 +900,7 @@ class TextEditorComponent {
window.addEventListener('mouseup', didMouseUp) window.addEventListener('mouseup', didMouseUp)
} }
autoscrollOnMouseDrag ({clientX, clientY}) { autoscrollOnMouseDrag ({clientX, clientY}, verticalOnly = false) {
let {top, bottom, left, right} = this.refs.scroller.getBoundingClientRect() let {top, bottom, left, right} = this.refs.scroller.getBoundingClientRect()
top += MOUSE_DRAG_AUTOSCROLL_MARGIN top += MOUSE_DRAG_AUTOSCROLL_MARGIN
bottom -= 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 scaledDelta = scaleMouseDragAutoscrollDelta(xDelta) * xDirection
const newScrollLeft = this.constrainScrollLeft(this.measurements.scrollLeft + scaledDelta) const newScrollLeft = this.constrainScrollLeft(this.measurements.scrollLeft + scaledDelta)
if (newScrollLeft !== this.measurements.scrollLeft) { if (newScrollLeft !== this.measurements.scrollLeft) {