WIP: Make selections remember if they are wordwise/linewise

Also always expand from the initial selection after a double/triple click in either direction until directionality of the selection is established.
This commit is contained in:
Corey Johnson & Nathan Sobo
2012-10-30 13:56:35 -06:00
parent 5b7e96067a
commit c55332a3a4
4 changed files with 82 additions and 49 deletions

View File

@@ -9,7 +9,7 @@ $ = require 'jquery'
_ = require 'underscore'
fs = require 'fs'
describe "Editor", ->
fdescribe "Editor", ->
[rootView, project, buffer, editor, cachedLineHeight] = []
getLineHeight = ->
@@ -536,7 +536,20 @@ describe "Editor", ->
expect(editor.getCursorBufferPosition()).toEqual(row: 3, column: 50)
describe "double-click", ->
it "selects the word under the cursor", ->
it "selects the word under the cursor, and expands the selection in either direction on a subsequent shift-click", ->
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 24], originalEvent: {detail: 1})
editor.renderedLines.trigger 'mouseup'
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 24], originalEvent: {detail: 2})
editor.renderedLines.trigger 'mouseup'
expect(editor.getSelectedText()).toBe "concat"
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [8, 7], shiftKey: true)
editor.renderedLines.trigger 'mouseup'
expect(editor.getSelectedText()).toBe "return sort(left).concat"
it "stops selecting by word when the selection is emptied", ->
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 1})
editor.renderedLines.trigger 'mouseup'
@@ -544,6 +557,12 @@ describe "Editor", ->
editor.renderedLines.trigger 'mouseup'
expect(editor.getSelectedText()).toBe "quicksort"
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 10])
editor.renderedLines.trigger 'mouseup'
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 12], originalEvent: {detail: 1}, shiftKey: true)
expect(editor.getSelectedBufferRange()).toEqual [[3, 10], [3, 12]]
describe "triple/quardruple/etc-click", ->
it "selects the line under the cursor", ->
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
@@ -640,65 +659,55 @@ describe "Editor", ->
expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27)
describe "double-click and drag", ->
it "creates a selection from the word underneath an initial double click to mouse's new location ", ->
it "selects the word under the cursor, then continues to select by word in either direction as the mouse is dragged", ->
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 1})
editor.renderedLines.trigger 'mouseup'
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [0, 8], originalEvent: {detail: 2})
expect(editor.getSelectedText()).toBe "quicksort"
editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [1, 8])
expect(editor.getSelectedBufferRange()).toEqual [[0, 4], [1, 10]]
expect(editor.getCursorBufferPosition()).toEqual [1, 10]
editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [0, 1])
expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]]
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
editor.renderedLines.trigger 'mouseup'
expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]]
# shift-clicking still selects by word, but does not preserve the initial range
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [5, 25], originalEvent: {detail: 1}, shiftKey: true)
editor.renderedLines.trigger 'mouseup'
editor.logScreenLines(5, 5)
expect(editor.getSelectedBufferRange()).toEqual [[0, 13], [5, 27]]
describe "triple-click and drag", ->
ffit "expands the initial selection linewise in either direction", ->
editor.attachToDom()
editor.css(position: 'absolute', top: 10, left: 10)
# double click
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 1})
$(document).trigger 'mouseup'
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 2})
# moving changes selection
editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [5, 27])
range = editor.getSelection().getScreenRange()
expect(range.start).toEqual({row: 4, column: 4})
expect(range.end).toEqual({row: 5, column: 27})
expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27)
# mouse up may occur outside of editor, but still need to halt selection
$(document).trigger 'mouseup'
# moving after mouse up should not change selection
editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [8, 8])
range = editor.getSelection().getScreenRange()
expect(range.start).toEqual({row: 4, column: 4})
expect(range.end).toEqual({row: 5, column: 27})
expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27)
describe "trip-click and drag", ->
it "creates a selection from the line underneath an initial triple click to mouse's new location ", ->
editor.attachToDom()
editor.css(position: 'absolute', top: 10, left: 10)
# double click
# triple click
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 1})
$(document).trigger 'mouseup'
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 2})
$(document).trigger 'mouseup'
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 7], originalEvent: {detail: 3})
expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [5, 0]]
# moving changes selection
# moving changes selection linewise
editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [5, 27])
expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [6, 0]]
expect(editor.getCursorBufferPosition()).toEqual [6, 0]
range = editor.getSelection().getScreenRange()
expect(range.start).toEqual({row: 4, column: 0})
expect(range.end).toEqual({row: 5, column: 27})
expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27)
# moving changes selection linewise
editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [2, 27])
expect(editor.getSelectedBufferRange()).toEqual [[2, 0], [5, 0]]
expect(editor.getCursorBufferPosition()).toEqual [2, 0]
# mouse up may occur outside of editor, but still need to halt selection
$(document).trigger 'mouseup'
# moving after mouse up should not change selection
editor.renderedLines.trigger mousemoveEvent(editor: editor, point: [8, 8])
range = editor.getSelection().getScreenRange()
expect(range.start).toEqual({row: 4, column: 0})
expect(range.end).toEqual({row: 5, column: 27})
expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27)
describe "meta-click and drag", ->
it "adds an additional selection", ->
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [4, 10])

View File

@@ -566,6 +566,9 @@ class EditSession
fn(selection) for selection in @getSelections()
@mergeIntersectingSelections(reverse: true)
finalizeSelections: ->
selection.finalize() for selection in @getSelections()
mergeIntersectingSelections: (options) ->
for selection in @getSelections()
otherSelections = @getSelections()

View File

@@ -360,6 +360,7 @@ class Editor extends View
@off 'mousemove', moveHandler
reverse = @activeEditSession.getLastSelection().isReversed()
@activeEditSession.mergeIntersectingSelections({reverse})
@activeEditSession.finalizeSelections()
@syncCursorAnimations()
afterAttach: (onDom) ->

View File

@@ -6,6 +6,8 @@ _ = require 'underscore'
module.exports =
class Selection
anchor: null
wordwise: false
initialScreenRange: null
constructor: ({@cursor, @editSession}) ->
@cursor.selection = this
@@ -25,6 +27,10 @@ class Selection
@editSession.removeSelection(this)
@trigger 'destroy'
finalize: ->
@initialScreenRange = null unless @initialScreenRange?.isEqual(@getScreenRange())
@wordwise = false if @isEmpty()
isEmpty: ->
@getBufferRange().isEmpty()
@@ -53,7 +59,7 @@ class Selection
setBufferRange: (bufferRange, options={}) ->
bufferRange = Range.fromObject(bufferRange)
{ start, end } = bufferRange
[start, end] = [end, start] if options.reverse
[start, end] = [end, start] if options.reverse ? @isReversed()
@editSession.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds
@placeAnchor() unless @anchor
@@ -89,6 +95,8 @@ class Selection
selectWord: ->
@setBufferRange(@cursor.getCurrentWordBufferRange())
@wordwise = true
@initialScreenRange = @getScreenRange()
expandOverWord: ->
@setBufferRange(@getBufferRange().union(@cursor.getCurrentWordBufferRange()))
@@ -105,7 +113,19 @@ class Selection
@setBufferRange(@getBufferRange().union(@cursor.getCurrentLineBufferRange()))
selectToScreenPosition: (position) ->
@modifySelection => @cursor.setScreenPosition(position)
@modifySelection =>
if @initialScreenRange
if position.isLessThan(@initialScreenRange.start)
@anchor.setScreenPosition(@initialScreenRange.end)
@cursor.setScreenPosition(position)
else
@anchor.setScreenPosition(@initialScreenRange.start)
@cursor.setScreenPosition(position)
else
@cursor.setScreenPosition(position)
if @wordwise
@expandOverWord()
selectToBufferPosition: (position) ->
@modifySelection => @cursor.setBufferPosition(position)