mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Merge branch 'batch-updates'
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -2,14 +2,13 @@ module.exports =
|
||||
class CursorsComponent
|
||||
oldState: null
|
||||
|
||||
constructor: (@presenter) ->
|
||||
constructor: ->
|
||||
@cursorNodesById = {}
|
||||
@domNode = document.createElement('div')
|
||||
@domNode.classList.add('cursors')
|
||||
@updateSync()
|
||||
|
||||
updateSync: ->
|
||||
newState = @presenter.state.content
|
||||
updateSync: (state) ->
|
||||
newState = state.content
|
||||
@oldState ?= {cursors: {}}
|
||||
|
||||
# update blink class
|
||||
|
||||
@@ -18,10 +18,8 @@ class GutterComponent
|
||||
@domNode.addEventListener 'click', @onClick
|
||||
@domNode.addEventListener 'mousedown', @onMouseDown
|
||||
|
||||
@updateSync()
|
||||
|
||||
updateSync: ->
|
||||
@newState = @presenter.state.gutter
|
||||
updateSync: (state) ->
|
||||
@newState = state.gutter
|
||||
@oldState ?= {lineNumbers: {}}
|
||||
|
||||
@appendDummyLineNumber() unless @dummyLineNumberNode?
|
||||
|
||||
@@ -5,7 +5,7 @@ module.exports =
|
||||
class HighlightsComponent
|
||||
oldState: null
|
||||
|
||||
constructor: (@presenter) ->
|
||||
constructor: ->
|
||||
@highlightNodesById = {}
|
||||
@regionNodesByHighlightId = {}
|
||||
|
||||
@@ -17,8 +17,8 @@ class HighlightsComponent
|
||||
insertionPoint.setAttribute('select', '.underlayer')
|
||||
@domNode.appendChild(insertionPoint)
|
||||
|
||||
updateSync: ->
|
||||
newState = @presenter.state.content.highlights
|
||||
updateSync: (state) ->
|
||||
newState = state.content.highlights
|
||||
@oldState ?= {}
|
||||
|
||||
# remove highlights
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
module.exports =
|
||||
class InputComponent
|
||||
constructor: (@presenter) ->
|
||||
constructor: ->
|
||||
@domNode = document.createElement('input')
|
||||
@domNode.classList.add('hidden-input')
|
||||
@domNode.setAttribute('data-react-skip-selection-restoration', true)
|
||||
@domNode.style['-webkit-transform'] = 'translateZ(0)'
|
||||
@domNode.addEventListener 'paste', (event) -> event.preventDefault()
|
||||
@updateSync()
|
||||
|
||||
updateSync: ->
|
||||
updateSync: (state) ->
|
||||
@oldState ?= {}
|
||||
newState = @presenter.state.hiddenInput
|
||||
newState = state.hiddenInput
|
||||
|
||||
if newState.top isnt @oldState.top
|
||||
@domNode.style.top = newState.top + 'px'
|
||||
|
||||
@@ -42,15 +42,13 @@ class LinesComponent
|
||||
|
||||
insertionPoint = document.createElement('content')
|
||||
insertionPoint.setAttribute('select', 'atom-overlay')
|
||||
@overlayManager = new OverlayManager(@hostElement)
|
||||
@overlayManager = new OverlayManager(@presenter, @hostElement)
|
||||
@domNode.appendChild(insertionPoint)
|
||||
else
|
||||
@overlayManager = new OverlayManager(@domNode)
|
||||
@overlayManager = new OverlayManager(@presenter, @domNode)
|
||||
|
||||
@updateSync(visible)
|
||||
|
||||
updateSync: ->
|
||||
@newState = @presenter.state.content
|
||||
updateSync: (state) ->
|
||||
@newState = state.content
|
||||
@oldState ?= {lines: {}}
|
||||
|
||||
if @newState.scrollHeight isnt @oldState.scrollHeight
|
||||
@@ -81,10 +79,10 @@ class LinesComponent
|
||||
@domNode.style.width = @newState.scrollWidth + 'px'
|
||||
@oldState.scrollWidth = @newState.scrollWidth
|
||||
|
||||
@cursorsComponent.updateSync()
|
||||
@highlightsComponent.updateSync()
|
||||
@cursorsComponent.updateSync(state)
|
||||
@highlightsComponent.updateSync(state)
|
||||
|
||||
@overlayManager?.render(@presenter)
|
||||
@overlayManager?.render(state)
|
||||
|
||||
@oldState.indentGuidesVisible = @newState.indentGuidesVisible
|
||||
@oldState.scrollWidth = @newState.scrollWidth
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
module.exports =
|
||||
class OverlayManager
|
||||
constructor: (@container) ->
|
||||
constructor: (@presenter, @container) ->
|
||||
@overlayNodesById = {}
|
||||
|
||||
render: (presenter) ->
|
||||
for decorationId, {pixelPosition, item} of presenter.state.content.overlays
|
||||
@renderOverlay(presenter, decorationId, item, pixelPosition)
|
||||
render: (state) ->
|
||||
for decorationId, {pixelPosition, item} of state.content.overlays
|
||||
@renderOverlay(state, decorationId, item, pixelPosition)
|
||||
|
||||
for id, overlayNode of @overlayNodesById
|
||||
unless presenter.state.content.overlays.hasOwnProperty(id)
|
||||
unless state.content.overlays.hasOwnProperty(id)
|
||||
delete @overlayNodesById[id]
|
||||
overlayNode.remove()
|
||||
|
||||
return
|
||||
|
||||
renderOverlay: (presenter, decorationId, item, pixelPosition) ->
|
||||
renderOverlay: (state, decorationId, item, pixelPosition) ->
|
||||
item = atom.views.getView(item)
|
||||
unless overlayNode = @overlayNodesById[decorationId]
|
||||
overlayNode = @overlayNodesById[decorationId] = document.createElement('atom-overlay')
|
||||
@@ -25,15 +25,15 @@ class OverlayManager
|
||||
itemHeight = item.offsetHeight
|
||||
|
||||
|
||||
{scrollTop, scrollLeft} = presenter.state.content
|
||||
{scrollTop, scrollLeft} = state.content
|
||||
|
||||
left = pixelPosition.left
|
||||
if left + itemWidth - scrollLeft > presenter.contentFrameWidth and left - itemWidth >= scrollLeft
|
||||
if left + itemWidth - scrollLeft > @presenter.contentFrameWidth and left - itemWidth >= scrollLeft
|
||||
left -= itemWidth
|
||||
|
||||
top = pixelPosition.top + presenter.lineHeight
|
||||
if top + itemHeight - scrollTop > presenter.height and top - itemHeight - presenter.lineHeight >= scrollTop
|
||||
top -= itemHeight + presenter.lineHeight
|
||||
top = pixelPosition.top + @presenter.lineHeight
|
||||
if top + itemHeight - scrollTop > @presenter.height and top - itemHeight - @presenter.lineHeight >= scrollTop
|
||||
top -= itemHeight + @presenter.lineHeight
|
||||
|
||||
overlayNode.style.top = top + 'px'
|
||||
overlayNode.style.left = left + 'px'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports =
|
||||
class ScrollbarComponent
|
||||
constructor: ({@presenter, @orientation, @onScroll}) ->
|
||||
constructor: ({@orientation, @onScroll}) ->
|
||||
@domNode = document.createElement('div')
|
||||
@domNode.classList.add "#{@orientation}-scrollbar"
|
||||
@domNode.style['-webkit-transform'] = 'translateZ(0)' # See atom/atom#3559
|
||||
@@ -12,16 +12,14 @@ class ScrollbarComponent
|
||||
|
||||
@domNode.addEventListener 'scroll', @onScrollCallback
|
||||
|
||||
@updateSync()
|
||||
|
||||
updateSync: ->
|
||||
updateSync: (state) ->
|
||||
@oldState ?= {}
|
||||
switch @orientation
|
||||
when 'vertical'
|
||||
@newState = @presenter.state.verticalScrollbar
|
||||
@newState = state.verticalScrollbar
|
||||
@updateVertical()
|
||||
when 'horizontal'
|
||||
@newState = @presenter.state.horizontalScrollbar
|
||||
@newState = state.horizontalScrollbar
|
||||
@updateHorizontal()
|
||||
|
||||
if @newState.visible isnt @oldState.visible
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
module.exports =
|
||||
class ScrollbarCornerComponent
|
||||
constructor: (@presenter) ->
|
||||
constructor: () ->
|
||||
@domNode = document.createElement('div')
|
||||
@domNode.classList.add('scrollbar-corner')
|
||||
|
||||
@contentNode = document.createElement('div')
|
||||
@domNode.appendChild(@contentNode)
|
||||
|
||||
@updateSync()
|
||||
|
||||
updateSync: ->
|
||||
updateSync: (state) ->
|
||||
@oldState ?= {}
|
||||
@newState ?= {}
|
||||
|
||||
newHorizontalState = @presenter.state.horizontalScrollbar
|
||||
newVerticalState = @presenter.state.verticalScrollbar
|
||||
newHorizontalState = state.horizontalScrollbar
|
||||
newVerticalState = state.verticalScrollbar
|
||||
@newState.visible = newHorizontalState.visible and newVerticalState.visible
|
||||
@newState.height = newHorizontalState.height
|
||||
@newState.width = newVerticalState.width
|
||||
|
||||
@@ -64,21 +64,21 @@ class TextEditorComponent
|
||||
@scrollViewNode.classList.add('scroll-view')
|
||||
@domNode.appendChild(@scrollViewNode)
|
||||
|
||||
@mountGutterComponent() if @presenter.state.gutter.visible
|
||||
@mountGutterComponent() if @presenter.getState().gutter.visible
|
||||
|
||||
@hiddenInputComponent = new InputComponent(@presenter)
|
||||
@hiddenInputComponent = new InputComponent
|
||||
@scrollViewNode.appendChild(@hiddenInputComponent.domNode)
|
||||
|
||||
@linesComponent = new LinesComponent({@presenter, @hostElement, @useShadowDOM})
|
||||
@scrollViewNode.appendChild(@linesComponent.domNode)
|
||||
|
||||
@horizontalScrollbarComponent = new ScrollbarComponent({@presenter, orientation: 'horizontal', onScroll: @onHorizontalScroll})
|
||||
@horizontalScrollbarComponent = new ScrollbarComponent({orientation: 'horizontal', onScroll: @onHorizontalScroll})
|
||||
@scrollViewNode.appendChild(@horizontalScrollbarComponent.domNode)
|
||||
|
||||
@verticalScrollbarComponent = new ScrollbarComponent({@presenter, orientation: 'vertical', onScroll: @onVerticalScroll})
|
||||
@verticalScrollbarComponent = new ScrollbarComponent({orientation: 'vertical', onScroll: @onVerticalScroll})
|
||||
@domNode.appendChild(@verticalScrollbarComponent.domNode)
|
||||
|
||||
@scrollbarCornerComponent = new ScrollbarCornerComponent(@presenter)
|
||||
@scrollbarCornerComponent = new ScrollbarCornerComponent
|
||||
@domNode.appendChild(@scrollbarCornerComponent.domNode)
|
||||
|
||||
@observeEditor()
|
||||
@@ -104,7 +104,7 @@ class TextEditorComponent
|
||||
|
||||
updateSync: ->
|
||||
@oldState ?= {}
|
||||
@newState = @presenter.state
|
||||
@newState = @presenter.getState()
|
||||
|
||||
cursorMoved = @cursorMoved
|
||||
selectionChanged = @selectionChanged
|
||||
@@ -128,18 +128,18 @@ class TextEditorComponent
|
||||
else
|
||||
@domNode.style.height = ''
|
||||
|
||||
if @presenter.state.gutter.visible
|
||||
if @newState.gutter.visible
|
||||
@mountGutterComponent() unless @gutterComponent?
|
||||
@gutterComponent.updateSync()
|
||||
@gutterComponent.updateSync(@newState)
|
||||
else
|
||||
@gutterComponent?.domNode?.remove()
|
||||
@gutterComponent = null
|
||||
|
||||
@hiddenInputComponent.updateSync()
|
||||
@linesComponent.updateSync()
|
||||
@horizontalScrollbarComponent.updateSync()
|
||||
@verticalScrollbarComponent.updateSync()
|
||||
@scrollbarCornerComponent.updateSync()
|
||||
@hiddenInputComponent.updateSync(@newState)
|
||||
@linesComponent.updateSync(@newState)
|
||||
@horizontalScrollbarComponent.updateSync(@newState)
|
||||
@verticalScrollbarComponent.updateSync(@newState)
|
||||
@scrollbarCornerComponent.updateSync(@newState)
|
||||
|
||||
if @editor.isAlive()
|
||||
@updateParentViewFocusedClassIfNeeded()
|
||||
@@ -152,7 +152,7 @@ class TextEditorComponent
|
||||
@linesComponent.measureCharactersInNewLines() if @isVisible() and not @newState.content.scrollingVertically
|
||||
|
||||
mountGutterComponent: ->
|
||||
@gutterComponent = new GutterComponent({@presenter, @editor, onMouseDown: @onGutterMouseDown})
|
||||
@gutterComponent = new GutterComponent({@editor, onMouseDown: @onGutterMouseDown})
|
||||
@domNode.insertBefore(@gutterComponent.domNode, @domNode.firstChild)
|
||||
|
||||
becameVisible: ->
|
||||
|
||||
@@ -26,13 +26,18 @@ class TextEditorPresenter
|
||||
@observeConfig()
|
||||
@buildState()
|
||||
@startBlinkingCursors() if @focused
|
||||
@updating = false
|
||||
|
||||
destroy: ->
|
||||
@disposables.dispose()
|
||||
|
||||
# Calls your `callback` when some changes in the model occurred and the current state has been updated.
|
||||
onDidUpdateState: (callback) ->
|
||||
@emitter.on 'did-update-state', callback
|
||||
|
||||
emitDidUpdateState: ->
|
||||
@emitter.emit "did-update-state" if @isBatching()
|
||||
|
||||
transferMeasurementsToModel: ->
|
||||
@model.setHeight(@explicitHeight) if @explicitHeight?
|
||||
@model.setWidth(@contentFrameWidth) if @contentFrameWidth?
|
||||
@@ -43,6 +48,59 @@ class TextEditorPresenter
|
||||
@model.setVerticalScrollbarWidth(@measuredVerticalScrollbarWidth) if @measuredVerticalScrollbarWidth?
|
||||
@model.setHorizontalScrollbarHeight(@measuredHorizontalScrollbarHeight) if @measuredHorizontalScrollbarHeight?
|
||||
|
||||
# Private: Determines whether {TextEditorPresenter} is currently batching changes.
|
||||
# Returns a {Boolean}, `true` if is collecting changes, `false` if is applying them.
|
||||
isBatching: ->
|
||||
@updating is false
|
||||
|
||||
# Private: Executes `fn` if `isBatching()` is false, otherwise sets `@[flagName]` to `true` for later processing. In either cases, it calls `emitDidUpdateState`.
|
||||
# * `flagName` {String} name of a property of this presenter
|
||||
# * `fn` {Function} to call when not batching.
|
||||
batch: (flagName, fn) ->
|
||||
if @isBatching()
|
||||
@[flagName] = true
|
||||
else
|
||||
fn.apply(this)
|
||||
|
||||
@emitDidUpdateState()
|
||||
|
||||
# Public: Gets this presenter's state, updating it just in time before returning from this function.
|
||||
# Returns a state {Object}, useful for rendering to screen.
|
||||
getState: ->
|
||||
@updating = true
|
||||
|
||||
@updateFocusedState() if @shouldUpdateFocusedState
|
||||
@updateHeightState() if @shouldUpdateHeightState
|
||||
@updateVerticalScrollState() if @shouldUpdateVerticalScrollState
|
||||
@updateHorizontalScrollState() if @shouldUpdateHorizontalScrollState
|
||||
@updateScrollbarsState() if @shouldUpdateScrollbarsState
|
||||
@updateHiddenInputState() if @shouldUpdateHiddenInputState
|
||||
@updateContentState() if @shouldUpdateContentState
|
||||
@updateDecorations() if @shouldUpdateDecorations
|
||||
@updateLinesState() if @shouldUpdateLinesState
|
||||
@updateCursorsState() if @shouldUpdateCursorsState
|
||||
@updateOverlaysState() if @shouldUpdateOverlaysState
|
||||
@updateGutterState() if @shouldUpdateGutterState
|
||||
@updateLineNumbersState() if @shouldUpdateLineNumbersState
|
||||
|
||||
@shouldUpdateFocusedState = false
|
||||
@shouldUpdateHeightState = false
|
||||
@shouldUpdateVerticalScrollState = false
|
||||
@shouldUpdateHorizontalScrollState = false
|
||||
@shouldUpdateScrollbarsState = false
|
||||
@shouldUpdateHiddenInputState = false
|
||||
@shouldUpdateContentState = false
|
||||
@shouldUpdateDecorations = false
|
||||
@shouldUpdateLinesState = false
|
||||
@shouldUpdateCursorsState = false
|
||||
@shouldUpdateOverlaysState = false
|
||||
@shouldUpdateGutterState = false
|
||||
@shouldUpdateLineNumbersState = false
|
||||
|
||||
@updating = false
|
||||
|
||||
@state
|
||||
|
||||
observeModel: ->
|
||||
@disposables.add @model.onDidChange =>
|
||||
@updateContentDimensions()
|
||||
@@ -141,18 +199,16 @@ class TextEditorPresenter
|
||||
@updateGutterState()
|
||||
@updateLineNumbersState()
|
||||
|
||||
updateFocusedState: ->
|
||||
updateFocusedState: -> @batch "shouldUpdateFocusedState", ->
|
||||
@state.focused = @focused
|
||||
|
||||
updateHeightState: ->
|
||||
updateHeightState: -> @batch "shouldUpdateHeightState", ->
|
||||
if @autoHeight
|
||||
@state.height = @contentHeight
|
||||
else
|
||||
@state.height = null
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateVerticalScrollState: ->
|
||||
updateVerticalScrollState: -> @batch "shouldUpdateVerticalScrollState", ->
|
||||
@state.content.scrollHeight = @scrollHeight
|
||||
@state.gutter.scrollHeight = @scrollHeight
|
||||
@state.verticalScrollbar.scrollHeight = @scrollHeight
|
||||
@@ -161,18 +217,14 @@ class TextEditorPresenter
|
||||
@state.gutter.scrollTop = @scrollTop
|
||||
@state.verticalScrollbar.scrollTop = @scrollTop
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateHorizontalScrollState: ->
|
||||
updateHorizontalScrollState: -> @batch "shouldUpdateHorizontalScrollState", ->
|
||||
@state.content.scrollWidth = @scrollWidth
|
||||
@state.horizontalScrollbar.scrollWidth = @scrollWidth
|
||||
|
||||
@state.content.scrollLeft = @scrollLeft
|
||||
@state.horizontalScrollbar.scrollLeft = @scrollLeft
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateScrollbarsState: ->
|
||||
updateScrollbarsState: -> @batch "shouldUpdateScrollbarsState", ->
|
||||
@state.horizontalScrollbar.visible = @horizontalScrollbarHeight > 0
|
||||
@state.horizontalScrollbar.height = @measuredHorizontalScrollbarHeight
|
||||
@state.horizontalScrollbar.right = @verticalScrollbarWidth
|
||||
@@ -181,9 +233,7 @@ class TextEditorPresenter
|
||||
@state.verticalScrollbar.width = @measuredVerticalScrollbarWidth
|
||||
@state.verticalScrollbar.bottom = @horizontalScrollbarHeight
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateHiddenInputState: ->
|
||||
updateHiddenInputState: -> @batch "shouldUpdateHiddenInputState", ->
|
||||
return unless lastCursor = @model.getLastCursor()
|
||||
|
||||
{top, left, height, width} = @pixelRectForScreenRange(lastCursor.getScreenRange())
|
||||
@@ -200,17 +250,14 @@ class TextEditorPresenter
|
||||
@state.hiddenInput.height = height
|
||||
@state.hiddenInput.width = Math.max(width, 2)
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateContentState: ->
|
||||
updateContentState: -> @batch "shouldUpdateContentState", ->
|
||||
@state.content.scrollWidth = @scrollWidth
|
||||
@state.content.scrollLeft = @scrollLeft
|
||||
@state.content.indentGuidesVisible = not @model.isMini() and @showIndentGuide
|
||||
@state.content.backgroundColor = if @model.isMini() then null else @backgroundColor
|
||||
@state.content.placeholderText = if @model.isEmpty() then @model.getPlaceholderText() else null
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateLinesState: ->
|
||||
updateLinesState: -> @batch "shouldUpdateLinesState", ->
|
||||
return unless @startRow? and @endRow? and @lineHeight?
|
||||
|
||||
visibleLineIds = {}
|
||||
@@ -235,8 +282,6 @@ class TextEditorPresenter
|
||||
unless visibleLineIds.hasOwnProperty(id)
|
||||
delete @state.content.lines[id]
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateLineState: (row, line) ->
|
||||
lineState = @state.content.lines[line.id]
|
||||
lineState.screenRow = row
|
||||
@@ -256,14 +301,10 @@ class TextEditorPresenter
|
||||
top: row * @lineHeight
|
||||
decorationClasses: @lineDecorationClassesForRow(row)
|
||||
|
||||
updateCursorsState: ->
|
||||
updateCursorsState: -> @batch "shouldUpdateCursorsState", ->
|
||||
@state.content.cursors = {}
|
||||
|
||||
@updateCursorState(cursor) for cursor in @model.cursors # using property directly to avoid allocation
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
|
||||
updateCursorState: (cursor, destroyOnly = false) ->
|
||||
delete @state.content.cursors[cursor.id]
|
||||
|
||||
@@ -275,7 +316,9 @@ class TextEditorPresenter
|
||||
pixelRect.width = @baseCharacterWidth if pixelRect.width is 0
|
||||
@state.content.cursors[cursor.id] = pixelRect
|
||||
|
||||
updateOverlaysState: ->
|
||||
@emitDidUpdateState()
|
||||
|
||||
updateOverlaysState: -> @batch "shouldUpdateOverlaysState", ->
|
||||
return unless @hasPixelRectRequirements()
|
||||
|
||||
visibleDecorationIds = {}
|
||||
@@ -296,18 +339,15 @@ class TextEditorPresenter
|
||||
for id of @state.content.overlays
|
||||
delete @state.content.overlays[id] unless visibleDecorationIds[id]
|
||||
|
||||
@emitter.emit "did-update-state"
|
||||
|
||||
updateGutterState: ->
|
||||
updateGutterState: -> @batch "shouldUpdateGutterState", ->
|
||||
@state.gutter.visible = not @model.isMini() and (@model.isGutterVisible() ? true) and @showLineNumbers
|
||||
@state.gutter.maxLineNumberDigits = @model.getLineCount().toString().length
|
||||
@state.gutter.backgroundColor = if @gutterBackgroundColor isnt "rgba(0, 0, 0, 0)"
|
||||
@gutterBackgroundColor
|
||||
else
|
||||
@backgroundColor
|
||||
@emitter.emit "did-update-state"
|
||||
|
||||
updateLineNumbersState: ->
|
||||
updateLineNumbersState: -> @batch "shouldUpdateLineNumbersState", ->
|
||||
return unless @startRow? and @endRow? and @lineHeight?
|
||||
|
||||
visibleLineNumberIds = {}
|
||||
@@ -350,8 +390,6 @@ class TextEditorPresenter
|
||||
for id of @state.gutter.lineNumbers
|
||||
delete @state.gutter.lineNumbers[id] unless visibleLineNumberIds[id]
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateStartRow: ->
|
||||
return unless @scrollTop? and @lineHeight?
|
||||
|
||||
@@ -536,7 +574,7 @@ class TextEditorPresenter
|
||||
@stoppedScrollingTimeoutId = null
|
||||
@stoppedScrollingTimeoutId = setTimeout(@didStopScrolling.bind(this), @stoppedScrollingDelay)
|
||||
@state.content.scrollingVertically = true
|
||||
@emitter.emit 'did-update-state'
|
||||
@emitDidUpdateState()
|
||||
|
||||
didStopScrolling: ->
|
||||
@state.content.scrollingVertically = false
|
||||
@@ -545,7 +583,7 @@ class TextEditorPresenter
|
||||
@updateLinesState()
|
||||
@updateLineNumbersState()
|
||||
else
|
||||
@emitter.emit 'did-update-state'
|
||||
@emitDidUpdateState()
|
||||
|
||||
setScrollLeft: (scrollLeft) ->
|
||||
scrollLeft = @constrainScrollLeft(scrollLeft)
|
||||
@@ -809,7 +847,7 @@ class TextEditorPresenter
|
||||
decorationState.flashCount++
|
||||
decorationState.flashClass = flash.class
|
||||
decorationState.flashDuration = flash.duration
|
||||
@emitter.emit "did-update-state"
|
||||
@emitDidUpdateState()
|
||||
|
||||
didAddDecoration: (decoration) ->
|
||||
@observeDecoration(decoration)
|
||||
@@ -823,7 +861,7 @@ class TextEditorPresenter
|
||||
else if decoration.isType('overlay')
|
||||
@updateOverlaysState()
|
||||
|
||||
updateDecorations: ->
|
||||
updateDecorations: -> @batch "shouldUpdateDecorations", ->
|
||||
@lineDecorationsByScreenRow = {}
|
||||
@lineNumberDecorationsByScreenRow = {}
|
||||
@highlightDecorationsById = {}
|
||||
@@ -843,7 +881,6 @@ class TextEditorPresenter
|
||||
unless visibleHighlights[id]
|
||||
delete @state.content.highlights[id]
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
removeFromLineDecorationCaches: (decoration, range) ->
|
||||
for row in [range.start.row..range.end.row] by 1
|
||||
@@ -883,7 +920,7 @@ class TextEditorPresenter
|
||||
|
||||
if decoration.isDestroyed() or not marker.isValid() or range.isEmpty() or not range.intersectsRowRange(@startRow, @endRow - 1)
|
||||
delete @state.content.highlights[decoration.id]
|
||||
@emitter.emit 'did-update-state'
|
||||
@emitDidUpdateState()
|
||||
return
|
||||
|
||||
if range.start.row < @startRow
|
||||
@@ -895,7 +932,7 @@ class TextEditorPresenter
|
||||
|
||||
if range.isEmpty()
|
||||
delete @state.content.highlights[decoration.id]
|
||||
@emitter.emit 'did-update-state'
|
||||
@emitDidUpdateState()
|
||||
return
|
||||
|
||||
highlightState = @state.content.highlights[decoration.id] ?= {
|
||||
@@ -906,8 +943,8 @@ class TextEditorPresenter
|
||||
highlightState.class = properties.class
|
||||
highlightState.deprecatedRegionClass = properties.deprecatedRegionClass
|
||||
highlightState.regions = @buildHighlightRegions(range)
|
||||
@emitDidUpdateState()
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
true
|
||||
|
||||
buildHighlightRegions: (screenRange) ->
|
||||
@@ -993,10 +1030,10 @@ class TextEditorPresenter
|
||||
|
||||
toggleCursorBlink: ->
|
||||
@state.content.cursorsVisible = not @state.content.cursorsVisible
|
||||
@emitter.emit 'did-update-state'
|
||||
@emitDidUpdateState()
|
||||
|
||||
pauseCursorBlinking: ->
|
||||
@stopBlinkingCursors(true)
|
||||
@startBlinkingCursorsAfterDelay ?= _.debounce(@startBlinkingCursors, @getCursorBlinkResumeDelay())
|
||||
@startBlinkingCursorsAfterDelay()
|
||||
@emitter.emit 'did-update-state'
|
||||
@emitDidUpdateState()
|
||||
|
||||
@@ -834,7 +834,8 @@ class TextEditor extends Model
|
||||
# argument will be a {Selection} and the second argument will be the
|
||||
# {Number} index of that selection.
|
||||
mutateSelectedText: (fn) ->
|
||||
@transact => fn(selection, index) for selection, index in @getSelections()
|
||||
@mergeIntersectingSelections =>
|
||||
@transact => fn(selection, index) for selection, index in @getSelections()
|
||||
|
||||
# Move lines intersection the most recent selection up by one row in screen
|
||||
# coordinates.
|
||||
@@ -993,17 +994,18 @@ class TextEditor extends Model
|
||||
# selections to create multiple single-line selections that cumulatively cover
|
||||
# the same original area.
|
||||
splitSelectionsIntoLines: ->
|
||||
for selection in @getSelections()
|
||||
range = selection.getBufferRange()
|
||||
continue if range.isSingleLine()
|
||||
@mergeIntersectingSelections =>
|
||||
for selection in @getSelections()
|
||||
range = selection.getBufferRange()
|
||||
continue if range.isSingleLine()
|
||||
|
||||
selection.destroy()
|
||||
{start, end} = range
|
||||
@addSelectionForBufferRange([start, [start.row, Infinity]])
|
||||
{row} = start
|
||||
while ++row < end.row
|
||||
@addSelectionForBufferRange([[row, 0], [row, Infinity]])
|
||||
@addSelectionForBufferRange([[end.row, 0], [end.row, end.column]]) unless end.column is 0
|
||||
selection.destroy()
|
||||
{start, end} = range
|
||||
@addSelectionForBufferRange([start, [start.row, Infinity]])
|
||||
{row} = start
|
||||
while ++row < end.row
|
||||
@addSelectionForBufferRange([[row, 0], [row, Infinity]])
|
||||
@addSelectionForBufferRange([[end.row, 0], [end.row, end.column]]) unless end.column is 0
|
||||
|
||||
# Extended: For each selection, transpose the selected text.
|
||||
#
|
||||
@@ -1140,7 +1142,8 @@ class TextEditor extends Model
|
||||
# with a positive `groupingInterval` is committed while the previous transaction is
|
||||
# still 'groupable', the two transactions are merged with respect to undo and redo.
|
||||
# * `fn` A {Function} to call inside the transaction.
|
||||
transact: (groupingInterval, fn) -> @buffer.transact(groupingInterval, fn)
|
||||
transact: (groupingInterval, fn) ->
|
||||
@buffer.transact(groupingInterval, fn)
|
||||
|
||||
# Deprecated: Start an open-ended transaction.
|
||||
beginTransaction: (groupingInterval) -> @buffer.beginTransaction(groupingInterval)
|
||||
@@ -2228,6 +2231,7 @@ class TextEditor extends Model
|
||||
|
||||
[head, tail...] = @getSelectionsOrderedByBufferPosition()
|
||||
_.reduce(tail, reducer, [head])
|
||||
return result if fn?
|
||||
|
||||
# Add a {Selection} based on the given {Marker}.
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user