mirror of
https://github.com/atom/atom.git
synced 2026-01-24 14:28:14 -05:00
Add overlay decorations to TextEditorPresenter::state
This commit is contained in:
@@ -877,6 +877,68 @@ describe "TextEditorPresenter", ->
|
||||
flashCount: 2
|
||||
}
|
||||
|
||||
describe ".overlays", ->
|
||||
stateForOverlay = (presenter, decoration) ->
|
||||
presenter.state.content.overlays[decoration.id]
|
||||
|
||||
it "contains state for overlay decorations both initially and when their markers move", ->
|
||||
item = {}
|
||||
marker = editor.markBufferPosition([2, 13], invalidate: 'touch')
|
||||
decoration = editor.decorateMarker(marker, {type: 'overlay', item})
|
||||
presenter = new TextEditorPresenter(model: editor, clientHeight: 30, scrollTop: 20, lineHeight: 10, lineOverdrawMargin: 0, baseCharacterWidth: 10)
|
||||
|
||||
# Initial state
|
||||
expectValues stateForOverlay(presenter, decoration), {
|
||||
item: item
|
||||
pixelPosition: {top: 2 * 10, left: 13 * 10}
|
||||
}
|
||||
|
||||
# Change range
|
||||
expectStateUpdate presenter, -> marker.setBufferRange([[2, 13], [4, 6]])
|
||||
expectValues stateForOverlay(presenter, decoration), {
|
||||
item: item
|
||||
pixelPosition: {top: 4 * 10, left: 6 * 10}
|
||||
}
|
||||
|
||||
# Valid -> invalid
|
||||
expectStateUpdate presenter, -> editor.getBuffer().insert([2, 14], 'x')
|
||||
expect(stateForOverlay(presenter, decoration)).toBeUndefined()
|
||||
|
||||
# Invalid -> valid
|
||||
expectStateUpdate presenter, -> editor.undo()
|
||||
expectValues stateForOverlay(presenter, decoration), {
|
||||
item: item
|
||||
pixelPosition: {top: 4 * 10, left: 6 * 10}
|
||||
}
|
||||
|
||||
# Reverse direction
|
||||
expectStateUpdate presenter, -> marker.setBufferRange([[2, 13], [4, 6]], reversed: true)
|
||||
expectValues stateForOverlay(presenter, decoration), {
|
||||
item: item
|
||||
pixelPosition: {top: 2 * 10, left: 13 * 10}
|
||||
}
|
||||
|
||||
# Destroy
|
||||
decoration.destroy()
|
||||
expect(stateForOverlay(presenter, decoration)).toBeUndefined()
|
||||
|
||||
# Add
|
||||
decoration2 = editor.decorateMarker(marker, {type: 'overlay', item})
|
||||
expectValues stateForOverlay(presenter, decoration2), {
|
||||
item: item
|
||||
pixelPosition: {top: 2 * 10, left: 13 * 10}
|
||||
}
|
||||
|
||||
it "honors the 'position' option on overlay decorations", ->
|
||||
item = {}
|
||||
marker = editor.markBufferRange([[2, 13], [4, 14]], invalidate: 'touch')
|
||||
decoration = editor.decorateMarker(marker, {type: 'overlay', position: 'tail', item})
|
||||
presenter = new TextEditorPresenter(model: editor, clientHeight: 30, scrollTop: 20, lineHeight: 10, lineOverdrawMargin: 0, baseCharacterWidth: 10)
|
||||
expectValues stateForOverlay(presenter, decoration), {
|
||||
item: item
|
||||
pixelPosition: {top: 2 * 10, left: 13 * 10}
|
||||
}
|
||||
|
||||
describe ".gutter", ->
|
||||
describe ".lineNumbers", ->
|
||||
lineNumberStateForScreenRow = (presenter, screenRow) ->
|
||||
|
||||
@@ -34,6 +34,7 @@ class TextEditorPresenter
|
||||
@observeLineDecoration(decoration) for decoration in @model.getLineDecorations()
|
||||
@observeLineNumberDecoration(decoration) for decoration in @model.getLineNumberDecorations()
|
||||
@observeHighlightDecoration(decoration) for decoration in @model.getHighlightDecorations()
|
||||
@observeOverlayDecoration(decoration) for decoration in @model.getOverlayDecorations()
|
||||
@observeCursor(cursor) for cursor in @model.getCursors()
|
||||
|
||||
observeConfig: ->
|
||||
@@ -42,9 +43,12 @@ class TextEditorPresenter
|
||||
buildState: ->
|
||||
@state =
|
||||
content:
|
||||
lines: {}
|
||||
blinkCursorsOff: false
|
||||
gutter: {}
|
||||
lines: {}
|
||||
highlights: {}
|
||||
overlays: {}
|
||||
gutter:
|
||||
lineNumbers: {}
|
||||
@updateState()
|
||||
|
||||
updateState: ->
|
||||
@@ -53,6 +57,7 @@ class TextEditorPresenter
|
||||
@updateLinesState()
|
||||
@updateCursorsState()
|
||||
@updateHighlightsState()
|
||||
@updateOverlaysState()
|
||||
@updateLineNumbersState()
|
||||
|
||||
updateVerticalScrollState: ->
|
||||
@@ -118,8 +123,6 @@ class TextEditorPresenter
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateHighlightsState: ->
|
||||
@state.content.highlights ?= {}
|
||||
|
||||
startRow = @getStartRow()
|
||||
endRow = @getEndRow()
|
||||
visibleHighlights = {}
|
||||
@@ -154,12 +157,33 @@ class TextEditorPresenter
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateOverlaysState: ->
|
||||
visibleDecorationIds = {}
|
||||
|
||||
for decoration in @model.getOverlayDecorations()
|
||||
continue unless decoration.getMarker().isValid()
|
||||
|
||||
{item, position} = decoration.getProperties()
|
||||
if position is 'tail'
|
||||
screenPosition = decoration.getMarker().getTailScreenPosition()
|
||||
else
|
||||
screenPosition = decoration.getMarker().getHeadScreenPosition()
|
||||
|
||||
@state.content.overlays[decoration.id] ?= {item}
|
||||
@state.content.overlays[decoration.id].pixelPosition = @pixelPositionForScreenPosition(screenPosition)
|
||||
visibleDecorationIds[decoration.id] = true
|
||||
|
||||
for id of @state.content.overlays
|
||||
delete @state.content.overlays[id] unless visibleDecorationIds[id]
|
||||
|
||||
@emitter.emit "did-update-state"
|
||||
|
||||
updateLineNumbersState: ->
|
||||
@state.gutter.lineNumbers = {}
|
||||
startRow = @getStartRow()
|
||||
endRow = @getEndRow()
|
||||
lastBufferRow = null
|
||||
wrapCount = 0
|
||||
visibleLineNumberIds = {}
|
||||
|
||||
for bufferRow, i in @model.bufferRowsForScreenRows(startRow, endRow - 1)
|
||||
screenRow = startRow + i
|
||||
@@ -167,16 +191,20 @@ class TextEditorPresenter
|
||||
if bufferRow is lastBufferRow
|
||||
wrapCount++
|
||||
softWrapped = true
|
||||
key = bufferRow + '-' + wrapCount
|
||||
id = bufferRow + '-' + wrapCount
|
||||
else
|
||||
wrapCount = 0
|
||||
softWrapped = false
|
||||
lastBufferRow = bufferRow
|
||||
key = bufferRow
|
||||
id = bufferRow
|
||||
decorationClasses = @lineNumberDecorationClassesForRow(screenRow)
|
||||
foldable = @model.isFoldableAtScreenRow(screenRow)
|
||||
|
||||
@state.gutter.lineNumbers[key] = {screenRow, bufferRow, softWrapped, top, decorationClasses, foldable}
|
||||
@state.gutter.lineNumbers[id] = {screenRow, bufferRow, softWrapped, top, decorationClasses, foldable}
|
||||
visibleLineNumberIds[id] = true
|
||||
|
||||
for id of @state.gutter.lineNumbers
|
||||
delete @state.gutter.lineNumbers[id] unless visibleLineNumberIds[id]
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
@@ -444,6 +472,15 @@ class TextEditorPresenter
|
||||
decorationState.flashDuration = flash.duration
|
||||
@emitter.emit "did-update-state"
|
||||
|
||||
observeOverlayDecoration: (decoration) ->
|
||||
decorationDisposables = new CompositeDisposable
|
||||
decorationDisposables.add decoration.getMarker().onDidChange(@updateOverlaysState.bind(this))
|
||||
decorationDisposables.add decoration.onDidChangeProperties(@updateOverlaysState.bind(this))
|
||||
decorationDisposables.add decoration.onDidDestroy =>
|
||||
@disposables.remove(decorationDisposables)
|
||||
@updateOverlaysState()
|
||||
@disposables.add(decorationDisposables)
|
||||
|
||||
didAddDecoration: (decoration) ->
|
||||
if decoration.isType('line')
|
||||
@observeLineDecoration(decoration)
|
||||
@@ -454,6 +491,9 @@ class TextEditorPresenter
|
||||
else if decoration.isType('highlight')
|
||||
@observeHighlightDecoration(decoration)
|
||||
@updateHighlightsState()
|
||||
else if decoration.isType('overlay')
|
||||
@observeOverlayDecoration(decoration)
|
||||
@updateOverlaysState()
|
||||
|
||||
observeCursor: (cursor) ->
|
||||
didChangePositionDisposable = cursor.onDidChangePosition =>
|
||||
|
||||
Reference in New Issue
Block a user