diff --git a/lib/mixins/canvas-drawer.coffee b/lib/mixins/canvas-drawer.coffee index bc65db4a..90d36026 100644 --- a/lib/mixins/canvas-drawer.coffee +++ b/lib/mixins/canvas-drawer.coffee @@ -146,7 +146,7 @@ class CanvasDrawer extends Mixin charWidth = @minimap.getCharWidth() * devicePixelRatio canvasWidth = @canvas.width displayCodeHighlights = @displayCodeHighlights - decorations = @minimap.decorationsForScreenRowRangeByTypeThenRows(firstRow, lastRow) + decorations = @minimap.decorationsByTypeThenRows(firstRow, lastRow) line = lines[0] diff --git a/lib/mixins/decoration-management.coffee b/lib/mixins/decoration-management.coffee index c9513090..a2685426 100644 --- a/lib/mixins/decoration-management.coffee +++ b/lib/mixins/decoration-management.coffee @@ -117,22 +117,26 @@ class DecorationManagement extends Mixin # endScreenRow - The ending row index. # # Returns an {Object}. - decorationsForScreenRowRangeByTypeThenRows: (startScreenRow, endScreenRow) -> - decorationsByMarkerType = {} - for marker in @findMarkers(intersectsScreenRowRange: [startScreenRow, endScreenRow]) - if decorations = @decorationsByMarkerId[marker.id] - range = marker.getScreenRange() - rows = [range.start.row..range.end.row] + decorationsByTypeThenRows: (startScreenRow, endScreenRow) -> + return @decorationsByTypeThenRowsCache if @decorationsByTypeThenRowsCache? - for decoration in decorations - {type} = decoration.getProperties() - decorationsByMarkerType[type] ?= {} + cache = {} + + for id, decoration of @decorationsById + range = decoration.marker.getScreenRange() + rows = [range.start.row..range.end.row] + + {type} = decoration.getProperties() + cache[type] ?= {} + + for row in rows + cache[type][row] ?= [] + cache[type][row].push(decoration) - for row in rows - decorationsByMarkerType[type][row] ?= [] - decorationsByMarkerType[type][row].push(decoration) + @decorationsByTypeThenRowsCache = cache - decorationsByMarkerType + invalidateDecorationForScreenRowsCache: -> + @decorationsByTypeThenRowsCache = null # Public: Adds a decoration that tracks a `Marker`. When the marker moves, # is invalidated, or is destroyed, the decoration will be updated to reflect @@ -186,6 +190,7 @@ class DecorationManagement extends Mixin @decorationMarkerChangedSubscriptions[marker.id] ?= marker.onDidChange (event) => decorations = @decorationsByMarkerId[marker.id] + @invalidateDecorationForScreenRowsCache() # Why check existence? Markers may get destroyed or decorations removed # in the change handler. Bookmarks does this. @@ -241,6 +246,7 @@ class DecorationManagement extends Mixin # decoration - The `Decoration` to register changes for. emitDecorationChanges: (decoration) -> return if decoration.marker.displayBuffer.isDestroyed() + @invalidateDecorationForScreenRowsCache() range = decoration.marker.getScreenRange() return unless range? @@ -269,21 +275,21 @@ class DecorationManagement extends Mixin removeDecoration: (decoration) -> return unless decoration? {marker} = decoration - return unless decorations = @decorationsByMarkerId[marker.id] - - @emitDecorationChanges(decoration) + delete @decorationsById[decoration.id] - @decorationUpdatedSubscriptions[decoration.id].dispose() - @decorationDestroyedSubscriptions[decoration.id].dispose() + @decorationUpdatedSubscriptions[decoration.id]?.dispose() + @decorationDestroyedSubscriptions[decoration.id]?.dispose() delete @decorationUpdatedSubscriptions[decoration.id] delete @decorationDestroyedSubscriptions[decoration.id] + return unless decorations = @decorationsByMarkerId[marker.id] + + @emitDecorationChanges(decoration) index = decorations.indexOf(decoration) if index > -1 decorations.splice(index, 1) - delete @decorationsById[decoration.id] @emitter.emit 'did-remove-decoration', {marker, decoration} @removedAllMarkerDecorations(marker) if decorations.length is 0 diff --git a/spec/minimap-spec.coffee b/spec/minimap-spec.coffee index 1fa672c0..8b67c285 100644 --- a/spec/minimap-spec.coffee +++ b/spec/minimap-spec.coffee @@ -296,7 +296,7 @@ describe 'Minimap', -> expect(decoration).toBeUndefined() - describe '::decorationsForScreenRowRangeByTypeThenRows', -> + describe '::decorationsByTypeThenRows', -> [decorations] = [] beforeEach -> @@ -313,7 +313,7 @@ describe 'Minimap', -> createDecoration 'line', [[12,0], [12,0]] createDecoration 'highlight-under', [[0,0], [10,1]] - decorations = minimap.decorationsForScreenRowRangeByTypeThenRows(0, 12) + decorations = minimap.decorationsByTypeThenRows(0, 12) it 'returns an object whose keys are the decorations types', -> expect(Object.keys(decorations).sort()).toEqual(['highlight-over', 'highlight-under', 'line'])