diff --git a/spec/app/buffer-spec.coffee b/spec/app/buffer-spec.coffee index 47eec56ff..ca7dd8681 100644 --- a/spec/app/buffer-spec.coffee +++ b/spec/app/buffer-spec.coffee @@ -707,15 +707,26 @@ describe 'Buffer', -> describe "marker observation", -> describe ".observeMarkerHeadPosition(marker, callback)", -> + observeHandler = null + + beforeEach -> + observeHandler = jasmine.createSpy("observeHandler") + it "calls the given callback whenever the marker's head position changes", -> marker = buffer.markRange([[4, 20], [4, 23]]) - observeHandler = jasmine.createSpy("observeHandler") buffer.observeMarkerHeadPosition(marker, observeHandler) buffer.setMarkerHeadPosition(marker, [6, 2]) expect(observeHandler).toHaveBeenCalled() expect(observeHandler.argsForCall[0][0]).toEqual [6, 2] + it "allows the observation subscription to be cancelled", -> + marker = buffer.markRange([[4, 20], [4, 23]]) + subscription = buffer.observeMarkerHeadPosition(marker, observeHandler) + subscription.cancel() + buffer.setMarkerHeadPosition(marker, [6, 2]) + expect(observeHandler).not.toHaveBeenCalled() + describe "marker updates due to buffer changes", -> [marker1, marker2] = [] diff --git a/spec/app/display-buffer-spec.coffee b/spec/app/display-buffer-spec.coffee index c9f24b72c..054978315 100644 --- a/spec/app/display-buffer-spec.coffee +++ b/spec/app/display-buffer-spec.coffee @@ -604,10 +604,14 @@ describe "DisplayBuffer", -> expect(displayBuffer.getMarkerBufferRange(marker)).toEqual [[5, 4], [8, 4]] describe "observation", -> + observeHandler = null + + beforeEach -> + observeHandler = jasmine.createSpy("observeHandler") + describe ".observeMarkerHeadScreenPosition(marker, callback)", -> it "calls the callback whenever the markers head's screen position changes", -> marker = displayBuffer.markScreenRange([[5, 4], [5, 10]]) - observeHandler = jasmine.createSpy("observeHandler") displayBuffer.observeMarkerHeadScreenPosition(marker, observeHandler) displayBuffer.setMarkerHeadScreenPosition(marker, [8, 20]) expect(observeHandler).toHaveBeenCalled() @@ -630,7 +634,6 @@ describe "DisplayBuffer", -> it "does not call the callback for screen changes that don't change the position of the marker", -> marker = displayBuffer.markScreenPosition([3, 4]) - observeHandler = jasmine.createSpy("observeHandler") displayBuffer.observeMarkerHeadScreenPosition(marker, observeHandler) buffer.insert([3, 0], '...') @@ -649,3 +652,13 @@ describe "DisplayBuffer", -> fold.destroy() expect(observeHandler).toHaveBeenCalled() expect(observeHandler.argsForCall[0][0]).toEqual [3, 7] + + it "allows observation subscriptions to be cancelled", -> + marker = displayBuffer.markScreenRange([[5, 4], [5, 10]]) + subscription = displayBuffer.observeMarkerHeadScreenPosition(marker, observeHandler) + subscription.cancel() + buffer.insert([11, 0], '...') + expect(observeHandler).not.toHaveBeenCalled() + + displayBuffer.unfoldBufferRow(4) + expect(observeHandler).not.toHaveBeenCalled() diff --git a/src/app/buffer-marker.coffee b/src/app/buffer-marker.coffee index 84b91bc5a..61485dba6 100644 --- a/src/app/buffer-marker.coffee +++ b/src/app/buffer-marker.coffee @@ -53,6 +53,8 @@ class BufferMarker observeHeadPosition: (callback) -> @headPositionObservers.push(callback) + cancel: => + _.remove(@headPositionObservers, callback) tryToInvalidate: (oldRange) -> containsStart = oldRange.containsPoint(@getStartPosition(), exclusive: true) diff --git a/src/app/display-buffer.coffee b/src/app/display-buffer.coffee index 125c8647c..87c0aa87a 100644 --- a/src/app/display-buffer.coffee +++ b/src/app/display-buffer.coffee @@ -355,10 +355,18 @@ class DisplayBuffer @markerScreenPositionObservers[id] ?= { head: [], tail: [] } @cacheMarkerScreenPositions(id) unless @markerScreenPositions[id] @markerScreenPositionObservers[id].head.push(callback) - @buffer.observeMarkerHeadPosition id, (bufferPosition) => + subscription = @buffer.observeMarkerHeadPosition id, (bufferPosition) => @cacheMarkerScreenPositions(id) callback(@screenPositionForBufferPosition(bufferPosition)) + cancel: => + subscription.cancel() + { head, tail } = @markerScreenPositionObservers[id] + _.remove(head, callback) + unless head.length + tail.length + delete @markerScreenPositionObservers[id] + delete @markerScreenPositions[id] + cacheMarkerScreenPositions: (id) -> @markerScreenPositions[id] = { head: @getMarkerHeadScreenPosition(id), tail: @getMarkerTailScreenPosition }