Expand selections on mouse drag

This commit is contained in:
Nathan Sobo 2017-03-10 14:31:54 -07:00 committed by Antonio Scandurra
parent 6bfe08e9b0
commit 5594c9d82f
2 changed files with 129 additions and 0 deletions

View File

@ -819,6 +819,88 @@ describe('TextEditorComponent', () => {
}, clientPositionForCharacter(component, 3, 11)))
expect(editor.getSelectedScreenRange()).toEqual([[2, 0], [4, 0]])
})
it('expands the last selection on drag', () => {
const {component, editor} = buildComponent()
spyOn(component, 'handleMouseDragUntilMouseUp')
component.didMouseDownOnContent(Object.assign({
detail: 1,
}, clientPositionForCharacter(component, 1, 4)))
{
const [didDrag, didStopDragging] = component.handleMouseDragUntilMouseUp.argsForCall[0]
didDrag(clientPositionForCharacter(component, 8, 8))
expect(editor.getSelectedScreenRange()).toEqual([[1, 4], [8, 8]])
didDrag(clientPositionForCharacter(component, 4, 8))
expect(editor.getSelectedScreenRange()).toEqual([[1, 4], [4, 8]])
didStopDragging()
expect(editor.getSelectedScreenRange()).toEqual([[1, 4], [4, 8]])
}
// Click-drag a second selection... selections are not merged until the
// drag stops.
component.didMouseDownOnContent(Object.assign({
detail: 1,
metaKey: 1,
}, clientPositionForCharacter(component, 8, 8)))
{
const [didDrag, didStopDragging] = component.handleMouseDragUntilMouseUp.argsForCall[1]
didDrag(clientPositionForCharacter(component, 2, 8))
expect(editor.getSelectedScreenRanges()).toEqual([
[[1, 4], [4, 8]],
[[2, 8], [8, 8]]
])
didDrag(clientPositionForCharacter(component, 6, 8))
expect(editor.getSelectedScreenRanges()).toEqual([
[[1, 4], [4, 8]],
[[6, 8], [8, 8]]
])
didDrag(clientPositionForCharacter(component, 2, 8))
expect(editor.getSelectedScreenRanges()).toEqual([
[[1, 4], [4, 8]],
[[2, 8], [8, 8]]
])
didStopDragging()
expect(editor.getSelectedScreenRanges()).toEqual([
[[1, 4], [8, 8]]
])
}
})
it('expands the selection word-wise on double-click-drag', () => {
const {component, editor} = buildComponent()
spyOn(component, 'handleMouseDragUntilMouseUp')
component.didMouseDownOnContent(Object.assign({
detail: 1,
}, clientPositionForCharacter(component, 1, 4)))
component.didMouseDownOnContent(Object.assign({
detail: 2,
}, clientPositionForCharacter(component, 1, 4)))
const [didDrag, didStopDragging] = component.handleMouseDragUntilMouseUp.argsForCall[1]
didDrag(clientPositionForCharacter(component, 0, 8))
expect(editor.getSelectedScreenRange()).toEqual([[0, 4], [1, 5]])
didDrag(clientPositionForCharacter(component, 2, 10))
expect(editor.getSelectedScreenRange()).toEqual([[1, 2], [2, 13]])
})
it('expands the selection line-wise on triple-click-drag', () => {
const {component, editor} = buildComponent()
spyOn(component, 'handleMouseDragUntilMouseUp')
const tripleClickPosition = clientPositionForCharacter(component, 2, 8)
component.didMouseDownOnContent(Object.assign({detail: 1}, tripleClickPosition))
component.didMouseDownOnContent(Object.assign({detail: 2}, tripleClickPosition))
component.didMouseDownOnContent(Object.assign({detail: 3}, tripleClickPosition))
const [didDrag, didStopDragging] = component.handleMouseDragUntilMouseUp.argsForCall[2]
didDrag(clientPositionForCharacter(component, 1, 8))
expect(editor.getSelectedScreenRange()).toEqual([[1, 0], [3, 0]])
didDrag(clientPositionForCharacter(component, 4, 10))
expect(editor.getSelectedScreenRange()).toEqual([[2, 0], [5, 0]])
})
})
})

View File

@ -786,6 +786,53 @@ class TextEditorComponent {
model.getLastSelection().selectLine(null, {autoscroll: false})
break
}
this.handleMouseDragUntilMouseUp(
(event) => {
const screenPosition = this.screenPositionForMouseEvent(event)
model.selectToScreenPosition(screenPosition, {suppressSelectionMerge: true, autoscroll: false})
this.updateSync()
},
() => {
model.finalizeSelections()
model.mergeIntersectingSelections()
this.updateSync()
}
)
}
handleMouseDragUntilMouseUp (didDragCallback, didStopDragging) {
let dragging = false
let lastMousemoveEvent
const animationFrameLoop = () => {
window.requestAnimationFrame(() => {
if (dragging && this.visible) {
didDragCallback(lastMousemoveEvent)
animationFrameLoop()
}
})
}
function didMouseMove (event) {
lastMousemoveEvent = event
if (!dragging) {
dragging = true
animationFrameLoop()
}
}
function didMouseUp () {
window.removeEventListener('mousemove', didMouseMove)
window.removeEventListener('mouseup', didMouseUp)
if (dragging) {
dragging = false
didStopDragging()
}
}
window.addEventListener('mousemove', didMouseMove)
window.addEventListener('mouseup', didMouseUp)
}
screenPositionForMouseEvent ({clientX, clientY}) {