Base the screen range of the selection view on the selection model

This commit is contained in:
Nathan Sobo
2012-06-08 11:21:37 -06:00
parent eed9af4c45
commit f3144fe0d8
5 changed files with 83 additions and 27 deletions

View File

@@ -17,8 +17,8 @@ describe "Selection", ->
it "places the anchor at the start of the range and the cursor at the end", ->
range = new Range({row: 2, column: 7}, {row: 3, column: 18})
selection.setBufferRange(range)
expect(selection.anchor.getScreenPosition()).toEqual range.start
expect(selection.cursor.getScreenPosition()).toEqual range.end
expect(selection.selection.anchor.getScreenPosition()).toEqual range.start
expect(selection.selection.cursor.getScreenPosition()).toEqual range.end
describe ".deleteSelectedText()", ->
describe "when nothing is selected", ->

View File

@@ -14,7 +14,6 @@ class CursorView extends View
hidden: false
initialize: (@cursor, @editor) ->
@cursor.on 'change-screen-position', (position, options) =>
@updateAppearance()
unless options.bufferChange

View File

@@ -32,7 +32,8 @@ class EditSession
@addCursorAtScreenPosition([0, 0])
@buffer.on "change.edit-session-#{@id}", (e) =>
@moveCursors (cursor) -> cursor.handleBufferChange(e)
for selection in @getSelections()
selection.handleBufferChange(e)
@renderer.on "change.edit-session-#{@id}", (e) =>
@trigger 'screen-lines-change', e
@@ -107,7 +108,7 @@ class EditSession
cursor
addSelectionForCursor: (cursor) ->
selection = new Selection(cursor)
selection = new Selection(editSession: this, cursor: cursor)
@selections.push(selection)
@trigger 'add-selection', selection
selection

View File

@@ -16,6 +16,9 @@ class SelectionView extends View
initialize: ({@editor, @selection} = {}) ->
@cursor = @selection.cursor
@regions = []
@selection.view = this
@selection.on 'change-screen-range', =>
@updateAppearance()
handleBufferChange: (e) ->
return unless @anchor
@@ -28,17 +31,16 @@ class SelectionView extends View
@anchor.setScreenPosition @cursor.getScreenPosition()
isEmpty: ->
@getBufferRange().isEmpty()
@selection.isEmpty()
isReversed: ->
not @isEmpty() and @cursor.getBufferPosition().isLessThan(@anchor.getBufferPosition())
@selection.isReversed()
intersectsWith: (otherSelection) ->
@getScreenRange().intersectsWith(otherSelection.getScreenRange())
clearSelection: ->
@anchor = null
@updateAppearance()
@selection.clear()
updateAppearance: ->
return unless @cursor
@@ -60,7 +62,6 @@ class SelectionView extends View
@appendRegion(rowSpan - 1, { row: range.start.row + 1, column: 0}, null)
@appendRegion(1, { row: range.end.row, column: 0 }, range.end)
appendRegion: (rows, start, end) ->
{ lineHeight, charWidth } = @editor
css = @editor.pixelPositionForScreenPosition(start)
@@ -79,21 +80,13 @@ class SelectionView extends View
@regions = []
getScreenRange: ->
if @anchor
new Range(@anchor.getScreenPosition(), @cursor.getScreenPosition())
else
new Range(@cursor.getScreenPosition(), @cursor.getScreenPosition())
@selection.getScreenRange()
setScreenRange: (range, {reverse}={}) ->
range = Range.fromObject(range)
{ start, end } = range
[start, end] = [end, start] if reverse
@cursor.setScreenPosition(start)
@modifySelection => @cursor.setScreenPosition(end)
setScreenRange: (range, options)->
@selection.setScreenRange(range, options)
getBufferRange: ->
@editor.bufferRangeForScreenRange(@getScreenRange())
@selection.getBufferRange()
setBufferRange: (bufferRange, options) ->
@setScreenRange(@editor.screenRangeForBufferRange(bufferRange), options)
@@ -182,10 +175,7 @@ class SelectionView extends View
super
modifySelection: (fn) ->
@placeAnchor()
@retainSelection = true
fn()
@retainSelection = false
@selection.modifySelection(fn)
selectWord: ->
@setBufferRange(@cursor.getCurrentWordBufferRange())

View File

@@ -1,3 +1,69 @@
Range = require 'range'
Anchor = require 'new-anchor'
EventEmitter = require 'event-emitter'
_ = require 'underscore'
module.exports =
class Selection
constructor: (@cursor) ->
anchor: null
constructor: ({@cursor, @editSession}) ->
@cursor.on 'change-screen-position', (e) =>
@trigger 'change-screen-range', @getScreenRange() unless e.bufferChanged
getScreenRange: ->
if @anchor
new Range(@anchor.getScreenPosition(), @cursor.getScreenPosition())
else
new Range(@cursor.getScreenPosition(), @cursor.getScreenPosition())
setScreenRange: (screenRange, options={})->
screenRange = Range.fromObject(screenRange)
{ start, end } = screenRange
[start, end] = [end, start] if options.reverse
@modifyScreenRange =>
@placeAnchor() unless @anchor
@modifySelection =>
@anchor.setScreenPosition(start)
@cursor.setScreenPosition(end)
getBufferRange: ->
if @anchor
new Range(@anchor.getBufferPosition(), @cursor.getBufferPosition())
else
new Range(@cursor.getBufferPosition(), @cursor.getBufferPosition())
clear: ->
@modifyScreenRange => @anchor = null
isEmpty: ->
@getBufferRange().isEmpty()
isReversed: ->
not @isEmpty() and @cursor.getBufferPosition().isLessThan(@anchor.getBufferPosition())
handleBufferChange: (e) ->
@modifyScreenRange =>
@anchor?.handleBufferChange(e)
@cursor.handleBufferChange(e)
modifySelection: (fn) ->
@retainSelection = true
@view?.retainSelection = true
@placeAnchor() unless @anchor
fn()
@retainSelection = false
@view?.retainSelection = false
modifyScreenRange: (fn) ->
oldScreenRange = @getScreenRange()
fn()
newScreenRange = @getScreenRange()
@trigger 'change-screen-range', newScreenRange unless oldScreenRange.isEqual(newScreenRange)
placeAnchor: ->
@anchor = new Anchor(@editSession)
@anchor.setScreenPosition(@cursor.getScreenPosition())
_.extend Selection.prototype, EventEmitter