Tell marker head observers if a move was caused by a buffer change

This is used by cursor to only autoscroll when the marker head is
explicitly moved, so that passive movements caused by buffer insertions
don't trigger autoscrolling.
This commit is contained in:
Nathan Sobo
2013-02-02 16:17:14 -07:00
parent bd1a100d17
commit e53403718a
5 changed files with 19 additions and 15 deletions

View File

@@ -720,13 +720,17 @@ describe 'Buffer', ->
beforeEach ->
observeHandler = jasmine.createSpy("observeHandler")
it "calls the given callback whenever the marker's head position changes", ->
it "calls the given callback whenever the marker's head position changes with the position and whether or not the move was caused by a buffer change", ->
marker = buffer.markRange([[4, 20], [4, 23]])
buffer.observeMarkerHeadPosition(marker, observeHandler)
buffer.setMarkerHeadPosition(marker, [6, 2])
expect(observeHandler).toHaveBeenCalled()
expect(observeHandler.argsForCall[0][0]).toEqual [6, 2]
expect(observeHandler.argsForCall[0]).toEqual [[6, 2], false]
observeHandler.reset()
buffer.insert([6, 0], '...')
expect(observeHandler.argsForCall[0]).toEqual [[6, 5], true]
it "allows the observation subscription to be cancelled", ->
marker = buffer.markRange([[4, 20], [4, 23]])

View File

@@ -620,27 +620,27 @@ fdescribe "DisplayBuffer", ->
observeHandler = jasmine.createSpy("observeHandler")
describe ".observeMarkerHeadScreenPosition(marker, callback)", ->
it "calls the callback whenever the markers head's screen position changes", ->
it "calls the callback whenever the markers head's screen position changes with the new position and whether it was precipitated by a buffer change", ->
marker = displayBuffer.markScreenRange([[5, 4], [5, 10]])
displayBuffer.observeMarkerHeadScreenPosition(marker, observeHandler)
displayBuffer.setMarkerHeadScreenPosition(marker, [8, 20])
expect(observeHandler).toHaveBeenCalled()
expect(observeHandler.argsForCall[0][0]).toEqual [8, 20]
expect(observeHandler.argsForCall[0]).toEqual [[8, 20], false]
observeHandler.reset()
buffer.insert([11, 0], '...')
expect(observeHandler).toHaveBeenCalled()
expect(observeHandler.argsForCall[0][0]).toEqual [8, 23]
expect(observeHandler.argsForCall[0]).toEqual [[8, 23], true]
observeHandler.reset()
displayBuffer.unfoldBufferRow(4)
expect(observeHandler).toHaveBeenCalled()
expect(observeHandler.argsForCall[0][0]).toEqual [11, 23]
expect(observeHandler.argsForCall[0]).toEqual [[11, 23], false]
observeHandler.reset()
displayBuffer.foldBufferRow(4)
expect(observeHandler).toHaveBeenCalled()
expect(observeHandler.argsForCall[0][0]).toEqual [8, 23]
expect(observeHandler.argsForCall[0]).toEqual [[8, 23], false]
it "does not call the callback for screen changes that don't change the position of the marker", ->
marker = displayBuffer.markScreenPosition([3, 4])

View File

@@ -38,7 +38,7 @@ class BufferMarker
setHeadPosition: (headPosition, options={}) ->
@headPosition = Point.fromObject(headPosition)
@headPosition = @buffer.clipPosition(@headPosition) if options.clip ? true
observer(@headPosition) for observer in @headPositionObservers
observer(@headPosition, !!options.bufferChanged) for observer in @headPositionObservers
@headPosition
setTailPosition: (tailPosition, options={}) ->
@@ -81,8 +81,8 @@ class BufferMarker
[@id]
handleBufferChange: (bufferChange) ->
@setHeadPosition(@updatePosition(@headPosition, bufferChange, false), clip: false)
@setTailPosition(@updatePosition(@tailPosition, bufferChange, true), clip: false) if @tailPosition
@setHeadPosition(@updatePosition(@headPosition, bufferChange, false), clip: false, bufferChanged: true)
@setTailPosition(@updatePosition(@tailPosition, bufferChange, true), clip: false, bufferChanged: true) if @tailPosition
updatePosition: (position, bufferChange, isFirstPoint) ->
{ oldRange, newRange } = bufferChange

View File

@@ -12,8 +12,8 @@ class Cursor
needsAutoscroll: null
constructor: ({@editSession, @marker}) ->
@editSession.observeMarkerHeadScreenPosition @marker, (screenPosition) =>
@needsAutoscroll ?= @isLastCursor()
@editSession.observeMarkerHeadScreenPosition @marker, (screenPosition, bufferChanged) =>
@needsAutoscroll ?= @isLastCursor() and !bufferChanged
@trigger 'moved', screenPosition
@editSession.trigger 'cursor-moved', screenPosition
@needsAutoscroll = true

View File

@@ -372,9 +372,9 @@ class DisplayBuffer
@markerScreenPositionObservers[id] ?= { head: [], tail: [] }
@cacheMarkerScreenPositions(id) unless @markerScreenPositions[id]
@markerScreenPositionObservers[id].head.push(callback)
subscription = @buffer.observeMarkerHeadPosition id, (bufferPosition) =>
subscription = @buffer.observeMarkerHeadPosition id, (bufferPosition, bufferChanged) =>
@cacheMarkerScreenPositions(id)
callback(@getMarkerHeadScreenPosition(id))
callback(@getMarkerHeadScreenPosition(id), bufferChanged)
cancel: =>
subscription.cancel()
@@ -392,7 +392,7 @@ class DisplayBuffer
currentHeadPosition = @getMarkerHeadScreenPosition(id)
unless currentHeadPosition.isEqual(head)
@cacheMarkerScreenPositions(id)
observer(currentHeadPosition) for observer in @markerScreenPositionObservers[id].head
observer(currentHeadPosition, false) for observer in @markerScreenPositionObservers[id].head
destroy: ->
@tokenizedBuffer.destroy()