mirror of
https://github.com/atom/atom.git
synced 2026-02-14 08:35:11 -05:00
Merge branch 'master' into as-tiled-gutter
Conflicts: src/text-editor-presenter.coffee
This commit is contained in:
@@ -153,6 +153,8 @@ class Decoration
|
||||
oldProperties = @properties
|
||||
@properties = translateDecorationParamsOldToNew(newProperties)
|
||||
@properties.id = @id
|
||||
if newProperties.type?
|
||||
@displayBuffer.decorationDidChangeType(this)
|
||||
@emit 'updated', {oldParams: oldProperties, newParams: newProperties} if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-change-properties', {oldProperties, newProperties}
|
||||
|
||||
|
||||
@@ -37,9 +37,11 @@ class DisplayBuffer extends Model
|
||||
@foldsByMarkerId = {}
|
||||
@decorationsById = {}
|
||||
@decorationsByMarkerId = {}
|
||||
@overlayDecorationsById = {}
|
||||
@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()
|
||||
@@ -918,7 +920,16 @@ class DisplayBuffer extends Model
|
||||
@getDecorations(propertyFilter).filter (decoration) -> decoration.isType('highlight')
|
||||
|
||||
getOverlayDecorations: (propertyFilter) ->
|
||||
@getDecorations(propertyFilter).filter (decoration) -> decoration.isType('overlay')
|
||||
result = []
|
||||
for id, decoration of @overlayDecorationsById
|
||||
result.push(decoration)
|
||||
if propertyFilter?
|
||||
result.filter (decoration) ->
|
||||
for key, value of propertyFilter
|
||||
return false unless decoration.properties[key] is value
|
||||
true
|
||||
else
|
||||
result
|
||||
|
||||
decorationsForScreenRowRange: (startScreenRow, endScreenRow) ->
|
||||
decorationsByMarkerId = {}
|
||||
@@ -933,6 +944,7 @@ class DisplayBuffer extends Model
|
||||
@disposables.add decoration.onDidDestroy => @removeDecoration(decoration)
|
||||
@decorationsByMarkerId[marker.id] ?= []
|
||||
@decorationsByMarkerId[marker.id].push(decoration)
|
||||
@overlayDecorationsById[decoration.id] = decoration if decoration.isType('overlay')
|
||||
@decorationsById[decoration.id] = decoration
|
||||
@emit 'decoration-added', decoration if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-add-decoration', decoration
|
||||
@@ -949,6 +961,10 @@ class DisplayBuffer extends Model
|
||||
@emit 'decoration-removed', decoration if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-remove-decoration', decoration
|
||||
delete @decorationsByMarkerId[marker.id] if decorations.length is 0
|
||||
delete @overlayDecorationsById[decoration.id]
|
||||
|
||||
decorationsForMarkerId: (markerId) ->
|
||||
@decorationsByMarkerId[markerId]
|
||||
|
||||
# Retrieves a {Marker} based on its id.
|
||||
#
|
||||
@@ -1242,6 +1258,12 @@ class DisplayBuffer extends Model
|
||||
foldForMarker: (marker) ->
|
||||
@foldsByMarkerId[marker.id]
|
||||
|
||||
decorationDidChangeType: (decoration) ->
|
||||
if decoration.isType('overlay')
|
||||
@overlayDecorationsById[decoration.id] = decoration
|
||||
else
|
||||
delete @overlayDecorationsById[decoration.id]
|
||||
|
||||
if Grim.includeDeprecatedAPIs
|
||||
DisplayBuffer.properties
|
||||
softWrapped: null
|
||||
|
||||
12
src/marker-observation-window.coffee
Normal file
12
src/marker-observation-window.coffee
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports =
|
||||
class MarkerObservationWindow
|
||||
constructor: (@displayBuffer, @bufferWindow) ->
|
||||
|
||||
setScreenRange: (range) ->
|
||||
@bufferWindow.setRange(@displayBuffer.bufferRangeForScreenRange(range))
|
||||
|
||||
setBufferRange: (range) ->
|
||||
@bufferWindow.setRange(range)
|
||||
|
||||
destroy: ->
|
||||
@bufferWindow.destroy()
|
||||
@@ -48,6 +48,7 @@ class Marker
|
||||
oldTailBufferPosition: null
|
||||
oldTailScreenPosition: null
|
||||
wasValid: true
|
||||
hasChangeObservers: false
|
||||
|
||||
###
|
||||
Section: Construction and Destruction
|
||||
@@ -57,14 +58,8 @@ class Marker
|
||||
@emitter = new Emitter
|
||||
@disposables = new CompositeDisposable
|
||||
@id = @bufferMarker.id
|
||||
@oldHeadBufferPosition = @getHeadBufferPosition()
|
||||
@oldHeadScreenPosition = @getHeadScreenPosition()
|
||||
@oldTailBufferPosition = @getTailBufferPosition()
|
||||
@oldTailScreenPosition = @getTailScreenPosition()
|
||||
@wasValid = @isValid()
|
||||
|
||||
@disposables.add @bufferMarker.onDidDestroy => @destroyed()
|
||||
@disposables.add @bufferMarker.onDidChange (event) => @notifyObservers(event)
|
||||
|
||||
# Essential: Destroys the marker, causing it to emit the 'destroyed' event. Once
|
||||
# destroyed, a marker cannot be restored by undo/redo operations.
|
||||
@@ -102,6 +97,14 @@ class Marker
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidChange: (callback) ->
|
||||
unless @hasChangeObservers
|
||||
@oldHeadBufferPosition = @getHeadBufferPosition()
|
||||
@oldHeadScreenPosition = @getHeadScreenPosition()
|
||||
@oldTailBufferPosition = @getTailBufferPosition()
|
||||
@oldTailScreenPosition = @getTailScreenPosition()
|
||||
@wasValid = @isValid()
|
||||
@disposables.add @bufferMarker.onDidChange (event) => @notifyObservers(event)
|
||||
@hasChangeObservers = true
|
||||
@emitter.on 'did-change', callback
|
||||
|
||||
# Essential: Invoke the given callback when the marker is destroyed.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{CompositeDisposable, Emitter} = require 'event-kit'
|
||||
{CompositeDisposable, Disposable, Emitter} = require 'event-kit'
|
||||
{Point, Range} = require 'text-buffer'
|
||||
_ = require 'underscore-plus'
|
||||
Decoration = require './decoration'
|
||||
@@ -25,6 +25,10 @@ class TextEditorPresenter
|
||||
@disposables = new CompositeDisposable
|
||||
@emitter = new Emitter
|
||||
@characterWidthsByScope = {}
|
||||
@rangesByDecorationId = {}
|
||||
@lineDecorationsByScreenRow = {}
|
||||
@lineNumberDecorationsByScreenRow = {}
|
||||
@customGutterDecorationsByGutterNameAndScreenRow = {}
|
||||
@transferMeasurementsToModel()
|
||||
@observeModel()
|
||||
@observeConfig()
|
||||
@@ -120,13 +124,21 @@ class TextEditorPresenter
|
||||
@shouldUpdateLineNumbersState = true
|
||||
@shouldUpdateGutterOrderState = true
|
||||
@shouldUpdateCustomGutterDecorationState = true
|
||||
|
||||
@emitDidUpdateState()
|
||||
|
||||
@model.onDidUpdateMarkers =>
|
||||
@shouldUpdateLinesState = 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
|
||||
@@ -138,14 +150,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))
|
||||
@@ -1089,58 +1101,22 @@ class TextEditorPresenter
|
||||
|
||||
observeDecoration: (decoration) ->
|
||||
decorationDisposables = new CompositeDisposable
|
||||
decorationDisposables.add decoration.getMarker().onDidChange(@decorationMarkerDidChange.bind(this, decoration))
|
||||
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)
|
||||
|
||||
decorationMarkerDidChange: (decoration, change) ->
|
||||
decorationPropertiesDidChange: (decoration, {oldProperties}) ->
|
||||
@shouldUpdateDecorations = true
|
||||
if decoration.isType('line') or decoration.isType('gutter')
|
||||
return if change.textChanged
|
||||
|
||||
intersectsVisibleRowRange = false
|
||||
oldRange = new Range(change.oldTailScreenPosition, change.oldHeadScreenPosition)
|
||||
newRange = new Range(change.newTailScreenPosition, change.newHeadScreenPosition)
|
||||
|
||||
if oldRange.intersectsRowRange(@startRow, @endRow - 1)
|
||||
@removeFromLineDecorationCaches(decoration, oldRange)
|
||||
intersectsVisibleRowRange = true
|
||||
|
||||
if newRange.intersectsRowRange(@startRow, @endRow - 1)
|
||||
@addToLineDecorationCaches(decoration, newRange)
|
||||
intersectsVisibleRowRange = true
|
||||
|
||||
if intersectsVisibleRowRange
|
||||
if decoration.isType('line')
|
||||
@shouldUpdateLinesState = true
|
||||
if decoration.isType('line-number')
|
||||
@shouldUpdateLineNumbersState = true
|
||||
else if decoration.isType('gutter')
|
||||
@shouldUpdateCustomGutterDecorationState = true
|
||||
|
||||
if decoration.isType('highlight')
|
||||
return if change.textChanged
|
||||
|
||||
@updateHighlightState(decoration)
|
||||
|
||||
if decoration.isType('overlay')
|
||||
@shouldUpdateOverlaysState = true
|
||||
|
||||
@emitDidUpdateState()
|
||||
|
||||
decorationPropertiesDidChange: (decoration, event) ->
|
||||
{oldProperties} = event
|
||||
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')
|
||||
@shouldUpdateLinesState = true
|
||||
if decoration.isType('line-number') or Decoration.isType(oldProperties, 'line-number')
|
||||
@@ -1150,16 +1126,12 @@ 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())
|
||||
if decoration.isType('line')
|
||||
@shouldUpdateLinesState = true
|
||||
@shouldUpdateLinesState = true if decoration.isType('line')
|
||||
if decoration.isType('line-number')
|
||||
@shouldUpdateLineNumbersState = true
|
||||
else if decoration.isType('gutter')
|
||||
@@ -1171,14 +1143,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)
|
||||
|
||||
@@ -1198,10 +1162,10 @@ class TextEditorPresenter
|
||||
@emitDidUpdateState()
|
||||
|
||||
updateDecorations: ->
|
||||
@rangesByDecorationId = {}
|
||||
@lineDecorationsByScreenRow = {}
|
||||
@lineNumberDecorationsByScreenRow = {}
|
||||
@customGutterDecorationsByGutterNameAndScreenRow = {}
|
||||
@highlightDecorationsById = {}
|
||||
|
||||
visibleHighlights = {}
|
||||
return unless 0 <= @startRow <= @endRow <= Infinity
|
||||
@@ -1220,16 +1184,19 @@ class TextEditorPresenter
|
||||
|
||||
return
|
||||
|
||||
removeFromLineDecorationCaches: (decoration, range) ->
|
||||
@removePropertiesFromLineDecorationCaches(decoration.id, decoration.getProperties(), range)
|
||||
removeFromLineDecorationCaches: (decoration) ->
|
||||
@removePropertiesFromLineDecorationCaches(decoration.id, decoration.getProperties())
|
||||
|
||||
removePropertiesFromLineDecorationCaches: (decorationId, decorationProperties, range) ->
|
||||
gutterName = decorationProperties.gutterName
|
||||
for row in [range.start.row..range.end.row] by 1
|
||||
delete @lineDecorationsByScreenRow[row]?[decorationId]
|
||||
delete @lineNumberDecorationsByScreenRow[row]?[decorationId]
|
||||
delete @customGutterDecorationsByGutterNameAndScreenRow[gutterName]?[row]?[decorationId] if gutterName
|
||||
return
|
||||
removePropertiesFromLineDecorationCaches: (decorationId, decorationProperties) ->
|
||||
if range = @rangesByDecorationId[decorationId]
|
||||
delete @rangesByDecorationId[decorationId]
|
||||
|
||||
gutterName = decorationProperties.gutterName
|
||||
for row in [range.start.row..range.end.row] by 1
|
||||
delete @lineDecorationsByScreenRow[row]?[decorationId]
|
||||
delete @lineNumberDecorationsByScreenRow[row]?[decorationId]
|
||||
delete @customGutterDecorationsByGutterNameAndScreenRow[gutterName]?[row]?[decorationId] if gutterName
|
||||
return
|
||||
|
||||
addToLineDecorationCaches: (decoration, range) ->
|
||||
marker = decoration.getMarker()
|
||||
@@ -1243,6 +1210,8 @@ class TextEditorPresenter
|
||||
return if properties.onlyEmpty
|
||||
omitLastRow = range.end.column is 0
|
||||
|
||||
@rangesByDecorationId[decoration.id] = range
|
||||
|
||||
for row in [range.start.row..range.end.row] by 1
|
||||
continue if properties.onlyHead and row isnt marker.getHeadScreenPosition().row
|
||||
continue if omitLastRow and row is range.end.row
|
||||
@@ -1291,6 +1260,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1386,6 +1389,9 @@ class TextEditor extends Model
|
||||
decorationForId: (id) ->
|
||||
@displayBuffer.decorationForId(id)
|
||||
|
||||
decorationsForMarkerId: (id) ->
|
||||
@displayBuffer.decorationsForMarkerId(id)
|
||||
|
||||
###
|
||||
Section: Markers
|
||||
###
|
||||
@@ -1488,6 +1494,25 @@ class TextEditor extends Model
|
||||
findMarkers: (properties) ->
|
||||
@displayBuffer.findMarkers(properties)
|
||||
|
||||
# Extended: Observe changes in the set of markers that intersect a particular
|
||||
# region of the editor.
|
||||
#
|
||||
# * `callback` A {Function} to call whenever one or more {Marker}s appears,
|
||||
# disappears, or moves within the given region.
|
||||
# * `event` An {Object} with the following keys:
|
||||
# * `insert` A {Set} containing the ids of all markers that appeared
|
||||
# in the range.
|
||||
# * `update` A {Set} containing the ids of all markers that moved within
|
||||
# the region.
|
||||
# * `remove` A {Set} containing the ids of all markers that disappeared
|
||||
# from the region.
|
||||
#
|
||||
# Returns a {MarkerObservationWindow}, which allows you to specify the region
|
||||
# of interest by calling {MarkerObservationWindow::setBufferRange} or
|
||||
# {MarkerObservationWindow::setScreenRange}.
|
||||
observeMarkers: (callback) ->
|
||||
@displayBuffer.observeMarkers(callback)
|
||||
|
||||
# Extended: Get the {Marker} for the given marker id.
|
||||
#
|
||||
# * `id` {Number} id of the marker
|
||||
|
||||
@@ -126,6 +126,7 @@ atom.commands.add 'atom-workspace',
|
||||
'application:about': -> ipc.send('command', 'application:about')
|
||||
'application:run-all-specs': -> ipc.send('command', 'application:run-all-specs')
|
||||
'application:run-benchmarks': -> ipc.send('command', 'application:run-benchmarks')
|
||||
'application:show-preferences': -> ipc.send('command', 'application:show-settings')
|
||||
'application:show-settings': -> ipc.send('command', 'application:show-settings')
|
||||
'application:quit': -> ipc.send('command', 'application:quit')
|
||||
'application:hide': -> ipc.send('command', 'application:hide')
|
||||
|
||||
Reference in New Issue
Block a user