Reduce observation to single observeMarker method on display buffer

It will call the observer callbacks with the buffer and screen positions
of the head and tell each time any of these values is changed.
This commit is contained in:
Nathan Sobo
2013-02-04 21:24:06 -07:00
parent 58450d6a65
commit afe0a6570a
7 changed files with 167 additions and 142 deletions

View File

@@ -12,7 +12,7 @@ class Cursor
needsAutoscroll: null
constructor: ({@editSession, @marker}) ->
@editSession.observeMarkerHeadPosition @marker, (e) =>
@editSession.observeMarker @marker, (e) =>
@needsAutoscroll ?= @isLastCursor() and !e.bufferChanged
@trigger 'moved', e
@editSession.trigger 'cursor-moved', e

View File

@@ -1,7 +1,13 @@
Range = require 'range'
_ = require 'underscore'
module.exports =
class DisplayBufferMarker
observers: null
bufferMarkerSubscription: null
previousHeadScreenPosition: null
previousTailScreenPosition: null
constructor: ({@id, @displayBuffer}) ->
@buffer = @displayBuffer.buffer
@@ -18,7 +24,7 @@ class DisplayBufferMarker
@buffer.setMarkerRange(@id, bufferRange, options)
getHeadScreenPosition: ->
@headScreenPosition ?= @displayBuffer.screenPositionForBufferPosition(@getHeadBufferPosition(), wrapAtSoftNewlines: true)
@displayBuffer.screenPositionForBufferPosition(@getHeadBufferPosition(), wrapAtSoftNewlines: true)
setHeadScreenPosition: (screenPosition, options) ->
screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options)
@@ -31,7 +37,8 @@ class DisplayBufferMarker
@buffer.setMarkerHeadPosition(@id, bufferPosition)
getTailScreenPosition: ->
@getMarker(@id).getTailScreenPosition()
if tailBufferPosition = @getTailBufferPosition()
@displayBuffer.screenPositionForBufferPosition(tailBufferPosition, wrapAtSoftNewlines: true)
setTailScreenPosition: (screenPosition, options) ->
screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options)
@@ -49,44 +56,60 @@ class DisplayBufferMarker
clearTail: ->
@buffer.clearMarkerTail(@id)
observeHeadPosition: (callback) ->
unless @headObservers
@observeBufferMarkerHeadPosition()
@displayBuffer.markers[@id] = this
@headObservers = []
@headObservers.push(callback)
cancel: => @unobserveHeadPosition(callback)
observe: (callback) ->
@observeBufferMarkerIfNeeded()
@observers.push(callback)
cancel: => @unobserve(callback)
unobserveHeadPosition: (callback) ->
_.remove(@headObservers, callback)
@unsubscribe() unless @headObservers.length
unobserve: (callback) ->
_.remove(@observers, callback)
@unobserveBufferMarkerIfNeeded()
observeBufferMarkerHeadPosition: ->
@getHeadScreenPosition()
@bufferMarkerHeadSubscription =
@buffer.observeMarkerHeadPosition @id, (e) =>
bufferChanged = e.bufferChanged
oldBufferPosition = e.oldPosition
newBufferPosition = e.newPosition
@refreshHeadScreenPosition({bufferChanged, oldBufferPosition, newBufferPosition})
observeBufferMarkerIfNeeded: ->
return if @observers
@observers = []
@previousHeadScreenPosition = @getHeadScreenPosition()
@previousTailScreenPosition = @getTailScreenPosition()
@bufferMarkerSubscription =
@buffer.observeMarker @id, ({oldHeadPosition, newHeadPosition, oldTailPosition, newTailPosition, bufferChanged}) =>
@notifyObservers
oldHeadBufferPosition: oldHeadPosition
newHeadBufferPosition: newHeadPosition
oldTailBufferPosition: oldTailPosition
newTailBufferPosition: newTailPosition
bufferChanged: bufferChanged
@displayBuffer.markers[@id] = this
refreshHeadScreenPosition: ({bufferChanged, oldBufferPosition, newBufferPosition}={}) ->
unless bufferChanged
oldBufferPosition ?= @getHeadBufferPosition()
newBufferPosition ?= oldBufferPosition
oldScreenPosition = @getHeadScreenPosition()
@headScreenPosition = null
newScreenPosition = @getHeadScreenPosition()
unless newScreenPosition.isEqual(oldScreenPosition)
@notifyHeadObservers({ oldBufferPosition, newBufferPosition, oldScreenPosition, newScreenPosition, bufferChanged })
notifyHeadObservers: (event) ->
observer(event) for observer in @getHeadObservers()
getHeadObservers: ->
new Array(@headObservers...)
unsubscribe: ->
@bufferMarkerHeadSubscription.cancel()
unobserveBufferMarkerIfNeeded: ->
return if @observers.length
@observers = null
@bufferMarkerSubscription.cancel()
delete @displayBuffer.markers[@id]
notifyObservers: ({oldHeadBufferPosition, oldTailBufferPosition, bufferChanged}) ->
oldHeadScreenPosition = @previousHeadScreenPosition
newHeadScreenPosition = @getHeadScreenPosition()
@previousHeadScreenPosition = newHeadScreenPosition
oldTailScreenPosition = @previousTailScreenPosition
newTailScreenPosition = @getTailScreenPosition()
@previousTailScreenPosition = newTailScreenPosition
return if _.isEqual(newHeadScreenPosition, oldHeadScreenPosition) and _.isEqual(newTailScreenPosition, oldTailScreenPosition)
oldHeadBufferPosition ?= @getHeadBufferPosition()
newHeadBufferPosition = @getHeadBufferPosition()
oldTailBufferPosition ?= @getTailBufferPosition()
newTailBufferPosition = @getTailBufferPosition()
for observer in @getObservers()
observer({
oldHeadScreenPosition, newHeadScreenPosition,
oldTailScreenPosition, newTailScreenPosition,
oldHeadBufferPosition, newHeadBufferPosition,
oldTailBufferPosition, newTailBufferPosition,
bufferChanged
})
getObservers: ->
new Array(@observers...)

View File

@@ -369,12 +369,12 @@ class DisplayBuffer
isMarkerReversed: (id) ->
@buffer.isMarkerReversed(id)
observeMarkerHeadPosition: (id, callback) ->
@getMarker(id).observeHeadPosition(callback)
observeMarker: (id, callback) ->
@getMarker(id).observe(callback)
refreshMarkerScreenPositions: ->
for marker in @getMarkers()
marker.refreshHeadScreenPosition(bufferChanged: false)
marker.notifyObservers(bufferChanged: false)
destroy: ->
@tokenizedBuffer.destroy()

View File

@@ -489,8 +489,8 @@ class EditSession
setMarkerTailBufferPosition: (args...) ->
@displayBuffer.setMarkerTailBufferPosition(args...)
observeMarkerHeadPosition: (args...) ->
@displayBuffer.observeMarkerHeadPosition(args...)
observeMarker: (args...) ->
@displayBuffer.observeMarker(args...)
placeMarkerTail: (args...) ->
@displayBuffer.placeMarkerTail(args...)

View File

@@ -10,10 +10,7 @@ class Selection
constructor: ({@cursor, @marker, @editSession}) ->
@cursor.selection = this
@cursor.on 'moved.selection', ({bufferChange}) =>
@screenRangeChanged() unless bufferChange
@editSession.observeMarker @marker, => @screenRangeChanged()
@cursor.on 'destroyed.selection', =>
@cursor = null
@destroy()
@@ -78,7 +75,6 @@ class Selection
clear: ->
@editSession.clearMarkerTail(@marker)
@screenRangeChanged()
selectWord: ->
options = {}