Re-render when a marker changes

fixes #2705
This commit is contained in:
Ben Ogle 2014-06-23 16:00:36 -07:00
parent 7139fd9f98
commit f381abcbad
4 changed files with 52 additions and 16 deletions

View File

@ -995,18 +995,6 @@ describe "EditorComponent", ->
nextTick()
expect(node.querySelectorAll('.test-highlight').length).toBe 0
it "moves rendered highlights when the marker moves", ->
regionStyle = node.querySelector('.test-highlight .region').style
originalTop = parseInt(regionStyle.top)
editor.getBuffer().insert([0, 0], '\n')
nextTick()
regionStyle = node.querySelector('.test-highlight .region').style
newTop = parseInt(regionStyle.top)
expect(newTop).toBe originalTop + lineHeightInPixels
it "removes highlights when a decoration's marker is destroyed", ->
marker.destroy()
nextTick()
@ -1028,6 +1016,29 @@ describe "EditorComponent", ->
regions = node.querySelectorAll('.test-highlight .region')
expect(regions.length).toBe 2
describe "when a decoration's marker moves", ->
it "moves rendered highlights when the buffer is changed", ->
regionStyle = node.querySelector('.test-highlight .region').style
originalTop = parseInt(regionStyle.top)
editor.getBuffer().insert([0, 0], '\n')
nextTick()
regionStyle = node.querySelector('.test-highlight .region').style
newTop = parseInt(regionStyle.top)
expect(newTop).toBe originalTop + lineHeightInPixels
it "moves rendered highlights when the marker is manually moved", ->
regionStyle = node.querySelector('.test-highlight .region').style
expect(parseInt(regionStyle.top)).toBe 2 * lineHeightInPixels
marker.setBufferRange([[5, 8], [5, 13]])
nextTick()
regionStyle = node.querySelector('.test-highlight .region').style
expect(parseInt(regionStyle.top)).toBe 5 * lineHeightInPixels
describe "hidden input field", ->
it "renders the hidden input field at the position of the last cursor if the cursor is on screen and the editor is focused", ->
editor.setVerticalScrollMargin(0)

View File

@ -45,7 +45,8 @@ class DisplayBuffer extends Model
@markers = {}
@foldsByMarkerId = {}
@decorationsByMarkerId = {}
@decorationMarkerSubscriptions = {}
@decorationMarkerChangedSubscriptions = {}
@decorationMarkerDestroyedSubscriptions = {}
@updateAllScreenLines()
@createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes())
@subscribe @tokenizedBuffer, 'grammar-changed', (grammar) => @emit 'grammar-changed', grammar
@ -755,7 +756,11 @@ class DisplayBuffer extends Model
return
marker = @getMarker(marker.id)
@decorationMarkerSubscriptions[marker.id] ?= @subscribe marker, 'destroyed', => @removeAllDecorationsForMarker(marker)
@decorationMarkerDestroyedSubscriptions[marker.id] ?= @subscribe marker, 'destroyed', => @removeAllDecorationsForMarker(marker)
subscription = @subscribe marker, 'changed', (event) => @emit('decoration-changed', marker, decoration, event)
@decorationMarkerChangedSubscriptions[marker.id] ?= []
@decorationMarkerChangedSubscriptions[marker.id].push {decoration, subscription}
@decorationsByMarkerId[marker.id] ?= []
@decorationsByMarkerId[marker.id].push(decoration)
@ -772,6 +777,7 @@ class DisplayBuffer extends Model
for i in [decorations.length - 1..0]
decoration = decorations[i]
if @decorationMatchesPattern(decoration, decorationPattern)
@unsubscribeDecorationFromMarker(marker, decoration)
decorations.splice(i, 1)
@emit 'decoration-removed', marker, decoration
@ -784,9 +790,26 @@ class DisplayBuffer extends Model
@removedAllMarkerDecorations(marker)
removedAllMarkerDecorations: (marker) ->
@decorationMarkerSubscriptions[marker.id].off()
@decorationMarkerDestroyedSubscriptions[marker.id].off()
for subscriptionObject in @decorationMarkerChangedSubscriptions[marker.id]
subscriptionObject.subscription.off()
delete @decorationsByMarkerId[marker.id]
delete @decorationMarkerSubscriptions[marker.id]
delete @decorationMarkerChangedSubscriptions[marker.id]
delete @decorationMarkerDestroyedSubscriptions[marker.id]
unsubscribeDecorationFromMarker: (marker, decoration) ->
subscriptionObjects = @decorationMarkerChangedSubscriptions[marker.id]
return unless @decorationMarkerChangedSubscriptions[marker.id]
for i in [subscriptionObjects.length - 1..0]
subscriptionObject = subscriptionObjects[i]
if subscriptionObject.decoration == decoration
subscriptionObject.subscription.off()
subscriptionObjects.splice(i, 1)
delete @decorationMarkerChangedSubscriptions[marker.id] if subscriptionObjects.length == 0
# Retrieves a {DisplayBufferMarker} based on its id.
#

View File

@ -291,6 +291,7 @@ EditorComponent = React.createClass
@subscribe editor, 'selection-added', @onSelectionAdded
@subscribe editor, 'decoration-added', @onDecorationChanged
@subscribe editor, 'decoration-removed', @onDecorationChanged
@subscribe editor, 'decoration-changed', @onDecorationChanged
@subscribe editor, 'character-widths-changed', @onCharacterWidthsChanged
@subscribe editor.$scrollTop.changes, @onScrollTopChanged
@subscribe editor.$scrollLeft.changes, @requestUpdate

View File

@ -217,6 +217,7 @@ class Editor extends Model
@subscribe @displayBuffer, 'soft-wrap-changed', (args...) => @emit 'soft-wrap-changed', args...
@subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args...
@subscribe @displayBuffer, "decoration-removed", (args...) => @emit 'decoration-removed', args...
@subscribe @displayBuffer, "decoration-changed", (args...) => @emit 'decoration-changed', args...
@subscribe @displayBuffer, "character-widths-changed", (changeCount) => @emit 'character-widths-changed', changeCount
getViewClass: ->