presenter: use 'markers-updated' event for state updates

Signed-off-by: Nathan Sobo <nathan@github.com>
This commit is contained in:
Max Brunsfeld
2015-06-03 17:58:44 -07:00
committed by Nathan Sobo
parent 76c696f1a2
commit f5895d8b0b
5 changed files with 41 additions and 120 deletions

View File

@@ -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 ->

View File

@@ -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'

View File

@@ -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

View File

@@ -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)

View File

@@ -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