mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Merge branch 'master' into as-double-reflow-measurements
# Conflicts: # src/text-editor-presenter.coffee
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
_ = require 'underscore-plus'
|
||||
scrollbarStyle = require 'scrollbar-style'
|
||||
{Range, Point} = require 'text-buffer'
|
||||
grim = require 'grim'
|
||||
{CompositeDisposable} = require 'event-kit'
|
||||
ipc = require 'ipc'
|
||||
|
||||
@@ -28,8 +27,6 @@ class TextEditorComponent
|
||||
updatesPaused: false
|
||||
updateRequestedWhilePaused: false
|
||||
heightAndWidthMeasurementRequested: false
|
||||
cursorMoved: false
|
||||
selectionChanged: false
|
||||
inputEnabled: true
|
||||
measureScrollbarsWhenShown: true
|
||||
measureLineHeightAndDefaultCharWidthWhenShown: true
|
||||
@@ -37,6 +34,13 @@ class TextEditorComponent
|
||||
stylingChangeAnimationFrameRequested: false
|
||||
gutterComponent: null
|
||||
mounted: true
|
||||
initialized: false
|
||||
|
||||
Object.defineProperty @prototype, "domNode",
|
||||
get: -> @domNodeValue
|
||||
set: (domNode) ->
|
||||
atom.assert domNode?, "TextEditorComponent::domNode was set to null."
|
||||
@domNodeValue = domNode
|
||||
|
||||
constructor: ({@editor, @hostElement, @rootElement, @stylesElement, @useShadowDOM, tileSize}) ->
|
||||
@tileSize = tileSize if tileSize?
|
||||
@@ -47,8 +51,10 @@ class TextEditorComponent
|
||||
|
||||
@presenter = new TextEditorPresenter
|
||||
model: @editor
|
||||
scrollTop: @editor.getScrollTop()
|
||||
scrollLeft: @editor.getScrollLeft()
|
||||
scrollTop: 0
|
||||
scrollLeft: 0
|
||||
scrollRow: @editor.getScrollRow()
|
||||
scrollColumn: @editor.getScrollColumn()
|
||||
tileSize: tileSize
|
||||
cursorBlinkPeriod: @cursorBlinkPeriod
|
||||
cursorBlinkResumeDelay: @cursorBlinkResumeDelay
|
||||
@@ -106,6 +112,7 @@ class TextEditorComponent
|
||||
|
||||
@updateSync()
|
||||
@checkForVisibilityChange()
|
||||
@initialized = true
|
||||
|
||||
destroy: ->
|
||||
@mounted = false
|
||||
@@ -121,11 +128,6 @@ class TextEditorComponent
|
||||
@oldState ?= {}
|
||||
@newState = @presenter.getState()
|
||||
|
||||
cursorMoved = @cursorMoved
|
||||
selectionChanged = @selectionChanged
|
||||
@cursorMoved = false
|
||||
@selectionChanged = false
|
||||
|
||||
if @editor.getLastSelection()? and not @editor.getLastSelection().isEmpty()
|
||||
@domNode.classList.add('has-selection')
|
||||
else
|
||||
@@ -221,8 +223,6 @@ class TextEditorComponent
|
||||
|
||||
observeEditor: ->
|
||||
@disposables.add @editor.observeGrammar(@onGrammarChanged)
|
||||
@disposables.add @editor.observeCursors(@onCursorAdded)
|
||||
@disposables.add @editor.observeSelections(@onSelectionAdded)
|
||||
|
||||
listenForDOMEvents: ->
|
||||
@domNode.addEventListener 'mousewheel', @onMouseWheel
|
||||
@@ -318,7 +318,7 @@ class TextEditorComponent
|
||||
inputNode.value = event.data if insertedRange
|
||||
|
||||
onVerticalScroll: (scrollTop) =>
|
||||
return if @updateRequested or scrollTop is @editor.getScrollTop()
|
||||
return if @updateRequested or scrollTop is @presenter.getScrollTop()
|
||||
|
||||
animationFramePending = @pendingScrollTop?
|
||||
@pendingScrollTop = scrollTop
|
||||
@@ -327,15 +327,17 @@ class TextEditorComponent
|
||||
pendingScrollTop = @pendingScrollTop
|
||||
@pendingScrollTop = null
|
||||
@presenter.setScrollTop(pendingScrollTop)
|
||||
@presenter.commitPendingScrollTopPosition()
|
||||
|
||||
onHorizontalScroll: (scrollLeft) =>
|
||||
return if @updateRequested or scrollLeft is @editor.getScrollLeft()
|
||||
return if @updateRequested or scrollLeft is @presenter.getScrollLeft()
|
||||
|
||||
animationFramePending = @pendingScrollLeft?
|
||||
@pendingScrollLeft = scrollLeft
|
||||
unless animationFramePending
|
||||
@requestAnimationFrame =>
|
||||
@presenter.setScrollLeft(@pendingScrollLeft)
|
||||
@presenter.commitPendingScrollLeftPosition()
|
||||
@pendingScrollLeft = null
|
||||
|
||||
onMouseWheel: (event) =>
|
||||
@@ -354,14 +356,18 @@ class TextEditorComponent
|
||||
if Math.abs(wheelDeltaX) > Math.abs(wheelDeltaY)
|
||||
# Scrolling horizontally
|
||||
previousScrollLeft = @presenter.getScrollLeft()
|
||||
@presenter.setScrollLeft(previousScrollLeft - Math.round(wheelDeltaX * @scrollSensitivity))
|
||||
event.preventDefault() unless previousScrollLeft is @presenter.getScrollLeft()
|
||||
updatedScrollLeft = previousScrollLeft - Math.round(wheelDeltaX * @scrollSensitivity)
|
||||
|
||||
event.preventDefault() if @presenter.canScrollLeftTo(updatedScrollLeft)
|
||||
@presenter.setScrollLeft(updatedScrollLeft)
|
||||
else
|
||||
# Scrolling vertically
|
||||
@presenter.setMouseWheelScreenRow(@screenRowForNode(event.target))
|
||||
previousScrollTop = @presenter.getScrollTop()
|
||||
@presenter.setScrollTop(previousScrollTop - Math.round(wheelDeltaY * @scrollSensitivity))
|
||||
event.preventDefault() unless previousScrollTop is @presenter.getScrollTop()
|
||||
updatedScrollTop = previousScrollTop - Math.round(wheelDeltaY * @scrollSensitivity)
|
||||
|
||||
event.preventDefault() if @presenter.canScrollTopTo(updatedScrollTop)
|
||||
@presenter.setScrollTop(updatedScrollTop)
|
||||
|
||||
onScrollViewScroll: =>
|
||||
if @mounted
|
||||
@@ -369,6 +375,77 @@ class TextEditorComponent
|
||||
@scrollViewNode.scrollTop = 0
|
||||
@scrollViewNode.scrollLeft = 0
|
||||
|
||||
onDidChangeScrollTop: (callback) ->
|
||||
@presenter.onDidChangeScrollTop(callback)
|
||||
|
||||
onDidChangeScrollLeft: (callback) ->
|
||||
@presenter.onDidChangeScrollLeft(callback)
|
||||
|
||||
setScrollLeft: (scrollLeft) ->
|
||||
@presenter.setScrollLeft(scrollLeft)
|
||||
|
||||
setScrollRight: (scrollRight) ->
|
||||
@presenter.setScrollRight(scrollRight)
|
||||
|
||||
setScrollTop: (scrollTop) ->
|
||||
@presenter.setScrollTop(scrollTop)
|
||||
|
||||
setScrollBottom: (scrollBottom) ->
|
||||
@presenter.setScrollBottom(scrollBottom)
|
||||
|
||||
getScrollTop: ->
|
||||
@presenter.getScrollTop()
|
||||
|
||||
getScrollLeft: ->
|
||||
@presenter.getScrollLeft()
|
||||
|
||||
getScrollRight: ->
|
||||
@presenter.getScrollRight()
|
||||
|
||||
getScrollBottom: ->
|
||||
@presenter.getScrollBottom()
|
||||
|
||||
getScrollHeight: ->
|
||||
@presenter.getScrollHeight()
|
||||
|
||||
getScrollWidth: ->
|
||||
@presenter.getScrollWidth()
|
||||
|
||||
getVerticalScrollbarWidth: ->
|
||||
@presenter.getVerticalScrollbarWidth()
|
||||
|
||||
getHorizontalScrollbarHeight: ->
|
||||
@presenter.getHorizontalScrollbarHeight()
|
||||
|
||||
getVisibleRowRange: ->
|
||||
@presenter.getVisibleRowRange()
|
||||
|
||||
pixelPositionForScreenPosition: (screenPosition) ->
|
||||
position = @presenter.pixelPositionForScreenPosition(screenPosition)
|
||||
position.top += @presenter.getScrollTop()
|
||||
position.left += @presenter.getScrollLeft()
|
||||
position
|
||||
|
||||
screenPositionForPixelPosition: (pixelPosition) ->
|
||||
@presenter.screenPositionForPixelPosition(pixelPosition)
|
||||
|
||||
pixelRectForScreenRange: (screenRange) ->
|
||||
rect = @presenter.pixelRectForScreenRange(screenRange)
|
||||
rect.top += @presenter.getScrollTop()
|
||||
rect.bottom += @presenter.getScrollTop()
|
||||
rect.left += @presenter.getScrollLeft()
|
||||
rect.right += @presenter.getScrollLeft()
|
||||
rect
|
||||
|
||||
pixelRangeForScreenRange: (screenRange, clip=true) ->
|
||||
{start, end} = Range.fromObject(screenRange)
|
||||
{start: @pixelPositionForScreenPosition(start, clip), end: @pixelPositionForScreenPosition(end, clip)}
|
||||
|
||||
pixelPositionForBufferPosition: (bufferPosition) ->
|
||||
@pixelPositionForScreenPosition(
|
||||
@editor.screenPositionForBufferPosition(bufferPosition)
|
||||
)
|
||||
|
||||
onMouseDown: (event) =>
|
||||
unless event.button is 0 or (event.button is 1 and process.platform is 'linux')
|
||||
# Only handle mouse down events for left mouse button on all platforms
|
||||
@@ -488,29 +565,6 @@ class TextEditorComponent
|
||||
@sampleBackgroundColors()
|
||||
@remeasureCharacterWidths()
|
||||
|
||||
onSelectionAdded: (selection) =>
|
||||
selectionDisposables = new CompositeDisposable
|
||||
selectionDisposables.add selection.onDidChangeRange => @onSelectionChanged(selection)
|
||||
selectionDisposables.add selection.onDidDestroy =>
|
||||
@onSelectionChanged(selection)
|
||||
selectionDisposables.dispose()
|
||||
@disposables.remove(selectionDisposables)
|
||||
|
||||
@disposables.add(selectionDisposables)
|
||||
|
||||
if @editor.selectionIntersectsVisibleRowRange(selection)
|
||||
@selectionChanged = true
|
||||
|
||||
onSelectionChanged: (selection) =>
|
||||
if @editor.selectionIntersectsVisibleRowRange(selection)
|
||||
@selectionChanged = true
|
||||
|
||||
onCursorAdded: (cursor) =>
|
||||
@disposables.add cursor.onDidChangePosition @onCursorMoved
|
||||
|
||||
onCursorMoved: =>
|
||||
@cursorMoved = true
|
||||
|
||||
handleDragUntilMouseUp: (dragHandler) =>
|
||||
dragging = false
|
||||
lastMousePosition = {}
|
||||
@@ -573,9 +627,11 @@ class TextEditorComponent
|
||||
|
||||
if mouseYDelta?
|
||||
@presenter.setScrollTop(@presenter.getScrollTop() + yDirection * scaleScrollDelta(mouseYDelta))
|
||||
@presenter.commitPendingScrollTopPosition()
|
||||
|
||||
if mouseXDelta?
|
||||
@presenter.setScrollLeft(@presenter.getScrollLeft() + xDirection * scaleScrollDelta(mouseXDelta))
|
||||
@presenter.commitPendingScrollLeftPosition()
|
||||
|
||||
scaleScrollDelta = (scrollDelta) ->
|
||||
Math.pow(scrollDelta / 2, 3) / 280
|
||||
@@ -592,7 +648,11 @@ class TextEditorComponent
|
||||
disposables.add(@editor.onDidDestroy(stopDragging))
|
||||
|
||||
isVisible: ->
|
||||
@domNode.offsetHeight > 0 or @domNode.offsetWidth > 0
|
||||
# Investigating an exception that occurs here due to ::domNode being null.
|
||||
atom.assert @domNode?, "TextEditorComponent::domNode was null.", (error) =>
|
||||
error.metadata = {@initialized}
|
||||
|
||||
@domNode? and (@domNode.offsetHeight > 0 or @domNode.offsetWidth > 0)
|
||||
|
||||
pollDOM: =>
|
||||
unless @checkForVisibilityChange()
|
||||
@@ -798,19 +858,22 @@ class TextEditorComponent
|
||||
|
||||
screenPositionForMouseEvent: (event, linesClientRect) ->
|
||||
pixelPosition = @pixelPositionForMouseEvent(event, linesClientRect)
|
||||
@editor.screenPositionForPixelPosition(pixelPosition)
|
||||
@presenter.screenPositionForPixelPosition(pixelPosition)
|
||||
|
||||
pixelPositionForMouseEvent: (event, linesClientRect) ->
|
||||
{clientX, clientY} = event
|
||||
|
||||
linesClientRect ?= @linesComponent.getDomNode().getBoundingClientRect()
|
||||
top = clientY - linesClientRect.top + @presenter.scrollTop
|
||||
left = clientX - linesClientRect.left + @presenter.scrollLeft
|
||||
bottom = linesClientRect.top + @presenter.scrollTop + linesClientRect.height - clientY
|
||||
right = linesClientRect.left + @presenter.scrollLeft + linesClientRect.width - clientX
|
||||
top = clientY - linesClientRect.top + @presenter.getRealScrollTop()
|
||||
left = clientX - linesClientRect.left + @presenter.getRealScrollLeft()
|
||||
bottom = linesClientRect.top + @presenter.getRealScrollTop() + linesClientRect.height - clientY
|
||||
right = linesClientRect.left + @presenter.getRealScrollLeft() + linesClientRect.width - clientX
|
||||
|
||||
{top, left, bottom, right}
|
||||
|
||||
getGutterWidth: ->
|
||||
@presenter.getGutterWidth()
|
||||
|
||||
getModel: ->
|
||||
@editor
|
||||
|
||||
@@ -830,12 +893,3 @@ class TextEditorComponent
|
||||
updateParentViewMiniClass: ->
|
||||
@hostElement.classList.toggle('mini', @editor.isMini())
|
||||
@rootElement.classList.toggle('mini', @editor.isMini())
|
||||
|
||||
if grim.includeDeprecatedAPIs
|
||||
TextEditorComponent::setInvisibles = (invisibles={}) ->
|
||||
grim.deprecate "Use config.set('editor.invisibles', invisibles) instead"
|
||||
atom.config.set('editor.invisibles', invisibles)
|
||||
|
||||
TextEditorComponent::setShowInvisibles = (showInvisibles) ->
|
||||
grim.deprecate "Use config.set('editor.showInvisibles', showInvisibles) instead"
|
||||
atom.config.set('editor.showInvisibles', showInvisibles)
|
||||
|
||||
Reference in New Issue
Block a user