From f5895d8b0b09e68391d034fd458007e9913f09d7 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 3 Jun 2015 17:58:44 -0700 Subject: [PATCH] presenter: use 'markers-updated' event for state updates Signed-off-by: Nathan Sobo --- spec/display-buffer-spec.coffee | 44 ------------- spec/text-editor-presenter-spec.coffee | 16 +++-- src/display-buffer.coffee | 5 +- src/text-editor-presenter.coffee | 91 +++++++------------------- src/text-editor.coffee | 5 +- 5 files changed, 41 insertions(+), 120 deletions(-) diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 4c48607a5..140ca2f9e 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -1207,50 +1207,6 @@ describe "DisplayBuffer", -> expect(markerCreated1).toHaveBeenCalled() expect(markerCreated2).not.toHaveBeenCalled() - describe "::observeMarkers(callback)", -> - [observationWindow, events] = [] - - beforeEach -> - events = [] - observationWindow = displayBuffer.observeMarkers (event) -> events.push(event) - displayBuffer.unfoldBufferRow(4, 7) - - it "calls the callback when markers enter, leave, or move within the screen range", -> - expect(events).toHaveLength 0 - - observationWindow.setScreenRange([[0, 0], [4, 0]]) - expect(events).toHaveLength 0 - - marker1 = displayBuffer.markScreenPosition([4, 2]) - expect(events).toHaveLength 0 - - observationWindow.setScreenRange([[0, 0], [5, 0]]) - expect(events).toHaveLength 1 - expect(events[0]).toEqual { - insert: new Set([marker1.id]) - update: new Set - remove: new Set - } - - marker2 = displayBuffer.markScreenPosition([5, 2]) - expect(events).toHaveLength 1 - - observationWindow.setBufferRange([[1, 0], [6, 0]]) - expect(events).toHaveLength 2 - expect(events[1]).toEqual { - insert: new Set([marker2.id]) - update: new Set([marker1.id]) - remove: new Set - } - - marker1.destroy() - expect(events).toHaveLength 3 - expect(events[2]).toEqual { - insert: new Set - update: new Set - remove: new Set([marker1.id]) - } - describe "decorations", -> [marker, decoration, decorationProperties] = [] beforeEach -> diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 142026913..fc52c4828 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -1532,21 +1532,27 @@ describe "TextEditorPresenter", -> expect(stateForHighlight(presenter, destroyedSelection.decoration)).toBeUndefined() it "updates when highlight decorations' properties are updated", -> - marker = editor.markBufferRange([[2, 2], [2, 4]]) + marker = editor.markBufferPosition([2, 2]) highlight = editor.decorateMarker(marker, type: 'highlight', class: 'a') presenter = buildPresenter(explicitHeight: 30, scrollTop: 20) - expectValues stateForHighlight(presenter, highlight), {class: 'a'} - expectStateUpdate presenter, -> highlight.setProperties(class: 'b', type: 'highlight') + expect(stateForHighlight(presenter, highlight)).toBeUndefined() + + expectStateUpdate presenter, -> + marker.setBufferRange([[2, 2], [2, 4]]) + highlight.setProperties(class: 'b', type: 'highlight') + expectValues stateForHighlight(presenter, highlight), {class: 'b'} it "increments the .flashCount and sets the .flashClass and .flashDuration when the highlight model flashes", -> presenter = buildPresenter(explicitHeight: 30, scrollTop: 20) - marker = editor.markBufferRange([[2, 2], [2, 4]]) + marker = editor.markBufferPosition([2, 2]) highlight = editor.decorateMarker(marker, type: 'highlight', class: 'a') - expectStateUpdate presenter, -> highlight.flash('b', 500) + expectStateUpdate presenter, -> + marker.setBufferRange([[2, 2], [2, 4]]) + highlight.flash('b', 500) expectValues stateForHighlight(presenter, highlight), { flashClass: 'b' diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index b361e416b..aa6abb7b7 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -10,7 +10,6 @@ Model = require './model' Token = require './token' Decoration = require './decoration' Marker = require './marker' -MarkerObservationWindow = require './marker-observation-window' class BufferToScreenConversionError extends Error constructor: (@message, @metadata) -> @@ -41,6 +40,7 @@ class DisplayBuffer extends Model @disposables.add @tokenizedBuffer.observeGrammar @subscribeToScopedConfigSettings @disposables.add @tokenizedBuffer.onDidChange @handleTokenizedBufferChange @disposables.add @buffer.onDidCreateMarker @handleBufferMarkerCreated + @disposables.add @buffer.onDidUpdateMarkers => @emitter.emit 'did-update-markers' @foldMarkerAttributes = Object.freeze({class: 'fold', displayBufferId: @id}) folds = (new Fold(this, marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes())) @updateAllScreenLines() @@ -1049,9 +1049,6 @@ class DisplayBuffer extends Model params = @translateToBufferMarkerParams(params) @buffer.findMarkers(params).map (stringMarker) => @getMarker(stringMarker.id) - observeMarkers: (callback) -> - new MarkerObservationWindow(this, @buffer.observeMarkers(callback)) - translateToBufferMarkerParams: (params) -> bufferMarkerParams = {} for key, value of params diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index c2a1d88a5..03cfd5a21 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -29,7 +29,6 @@ class TextEditorPresenter @lineDecorationsByScreenRow = {} @lineNumberDecorationsByScreenRow = {} @customGutterDecorationsByGutterNameAndScreenRow = {} - @highlightDecorationsById = {} @transferMeasurementsToModel() @observeModel() @observeConfig() @@ -126,17 +125,21 @@ class TextEditorPresenter @shouldUpdateLineNumbersState = true @shouldUpdateGutterOrderState = true @shouldUpdateCustomGutterDecorationState = true - @emitDidUpdateState() - @markerObservationWindow = @model.observeMarkers(@markersInRangeDidChange.bind(this)) - @disposables.add new Disposable => @markerObservationWindow.destroy() + @model.onDidUpdateMarkers => + @shouldUpdateTilesState = true + @shouldUpdateLineNumbersState = true + @shouldUpdateDecorations = true + @shouldUpdateOverlaysState = true + @shouldUpdateCustomGutterDecorationState = true + @emitDidUpdateState() @disposables.add @model.onDidChangeGrammar(@didChangeGrammar.bind(this)) @disposables.add @model.onDidChangePlaceholderText => @shouldUpdateContentState = true - @emitDidUpdateState() + @disposables.add @model.onDidChangeMini => @shouldUpdateScrollbarsState = true @shouldUpdateContentState = true @@ -148,14 +151,14 @@ class TextEditorPresenter @shouldUpdateCustomGutterDecorationState = true @updateScrollbarDimensions() @updateCommonGutterState() - @emitDidUpdateState() + @disposables.add @model.onDidChangeLineNumberGutterVisible => @shouldUpdateLineNumberGutterState = true @shouldUpdateGutterOrderState = true @updateCommonGutterState() - @emitDidUpdateState() + @disposables.add @model.onDidAddDecoration(@didAddDecoration.bind(this)) @disposables.add @model.onDidAddCursor(@didAddCursor.bind(this)) @disposables.add @model.onDidChangeScrollTop(@setScrollTop.bind(this)) @@ -614,7 +617,6 @@ class TextEditorPresenter visibleLinesCount = Math.ceil(@height / @lineHeight) + 1 endRow = startRow + visibleLinesCount @endRow = Math.min(@model.getScreenLineCount(), endRow) - @markerObservationWindow.setScreenRange(Range(Point(@startRow, 0), Point(@endRow, 0))) updateScrollWidth: -> return unless @contentWidth? and @clientWidth? @@ -1098,58 +1100,21 @@ class TextEditorPresenter observeDecoration: (decoration) -> decorationDisposables = new CompositeDisposable if decoration.isType('highlight') - decorationDisposables.add decoration.onDidFlash(@highlightDidFlash.bind(this, decoration)) - decorationDisposables.add decoration.onDidChangeProperties(@decorationPropertiesDidChange.bind(this, decoration)) + decorationDisposables.add decoration.onDidFlash => + @shouldUpdateDecorations = true + @emitDidUpdateState() + + decorationDisposables.add decoration.onDidChangeProperties (event) => + @decorationPropertiesDidChange(decoration, event) decorationDisposables.add decoration.onDidDestroy => @disposables.remove(decorationDisposables) decorationDisposables.dispose() @didDestroyDecoration(decoration) @disposables.add(decorationDisposables) - markersInRangeDidChange: (event) -> - event.insert.forEach (markerId) => - range = @model.getMarker(markerId).getScreenRange() - if decorations = @model.decorationsForMarkerId(markerId) - for decoration in decorations - @decorationMarkerDidChange(decoration) - if decoration.isType('line') or decoration.isType('gutter') - @addToLineDecorationCaches(decoration, range) - event.update.forEach (markerId) => - range = @model.getMarker(markerId).getScreenRange() - if decorations = @model.decorationsForMarkerId(markerId) - for decoration in decorations - @decorationMarkerDidChange(decoration) - if decoration.isType('line') or decoration.isType('gutter') - @removeFromLineDecorationCaches(decoration) - @addToLineDecorationCaches(decoration, range) - event.remove.forEach (markerId) => - if decorations = @model.decorationsForMarkerId(markerId) - for decoration in decorations - @decorationMarkerDidChange(decoration) - if decoration.isType('line') or decoration.isType('gutter') - @removeFromLineDecorationCaches(decoration) - @emitDidUpdateState() - - decorationMarkerDidChange: (decoration) -> - if decoration.isType('highlight') - @updateHighlightState(decoration) - if decoration.isType('overlay') - @shouldUpdateOverlaysState = true - if decoration.isType('line') - @shouldUpdateTilesState = true - if decoration.isType('line-number') - @shouldUpdateLineNumbersState = true - else if decoration.isType('gutter') - @shouldUpdateCustomGutterDecorationState = true - - decorationPropertiesDidChange: (decoration, event) -> - {oldProperties} = event + decorationPropertiesDidChange: (decoration, {oldProperties}) -> + @shouldUpdateDecorations = true if decoration.isType('line') or decoration.isType('gutter') - @removePropertiesFromLineDecorationCaches( - decoration.id, - oldProperties, - decoration.getMarker().getScreenRange()) - @addToLineDecorationCaches(decoration, decoration.getMarker().getScreenRange()) if decoration.isType('line') or Decoration.isType(oldProperties, 'line') @shouldUpdateTilesState = true if decoration.isType('line-number') or Decoration.isType(oldProperties, 'line-number') @@ -1159,14 +1124,11 @@ class TextEditorPresenter @shouldUpdateCustomGutterDecorationState = true else if decoration.isType('overlay') @shouldUpdateOverlaysState = true - else if decoration.isType('highlight') - @updateHighlightState(decoration, event) - @emitDidUpdateState() didDestroyDecoration: (decoration) -> + @shouldUpdateDecorations = true if decoration.isType('line') or decoration.isType('gutter') - @removeFromLineDecorationCaches(decoration, decoration.getMarker().getScreenRange()) @shouldUpdateTilesState = true if decoration.isType('line') if decoration.isType('line-number') @shouldUpdateLineNumbersState = true @@ -1179,14 +1141,6 @@ class TextEditorPresenter @emitDidUpdateState() - highlightDidFlash: (decoration) -> - flash = decoration.consumeNextFlash() - if decorationState = @state.content.highlights[decoration.id] - decorationState.flashCount++ - decorationState.flashClass = flash.class - decorationState.flashDuration = flash.duration - @emitDidUpdateState() - didAddDecoration: (decoration) -> @observeDecoration(decoration) @@ -1209,7 +1163,6 @@ class TextEditorPresenter @lineDecorationsByScreenRow = {} @lineNumberDecorationsByScreenRow = {} @customGutterDecorationsByGutterNameAndScreenRow = {} - @highlightDecorationsById = {} visibleHighlights = {} return unless 0 <= @startRow <= @endRow <= Infinity @@ -1304,6 +1257,12 @@ class TextEditorPresenter flashDuration: null flashClass: null } + + if flash = decoration.consumeNextFlash() + highlightState.flashCount++ + highlightState.flashClass = flash.class + highlightState.flashDuration = flash.duration + highlightState.class = properties.class highlightState.deprecatedRegionClass = properties.deprecatedRegionClass highlightState.regions = @buildHighlightRegions(range) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index f2d8445aa..4aacb3dfa 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -163,10 +163,10 @@ class TextEditor extends Model subscribeToDisplayBuffer: -> @disposables.add @displayBuffer.onDidCreateMarker @handleMarkerCreated - @disposables.add @displayBuffer.onDidUpdateMarkers => @mergeIntersectingSelections() @disposables.add @displayBuffer.onDidChangeGrammar => @handleGrammarChange() @disposables.add @displayBuffer.onDidTokenize => @handleTokenization() @disposables.add @displayBuffer.onDidChange (e) => + @mergeIntersectingSelections() @emit 'screen-lines-changed', e if includeDeprecatedAPIs @emitter.emit 'did-change', e @@ -461,6 +461,9 @@ class TextEditor extends Model onDidChangeIcon: (callback) -> @emitter.on 'did-change-icon', callback + onDidUpdateMarkers: (callback) -> + @displayBuffer.onDidUpdateMarkers(callback) + # Public: Retrieves the current {TextBuffer}. getBuffer: -> @buffer