mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Make LinesComponent a normal object instead of a React component
Also, remove ability to disable hardware acceleration since there’s no longer a need for it and it complicated this conversion.
This commit is contained in:
@@ -2558,7 +2558,7 @@ describe "TextEditorComponent", ->
|
||||
expect(wrapperNode.classList.contains('mini')).toBe true
|
||||
|
||||
it "does not have an opaque background on lines", ->
|
||||
expect(component.refs.lines.getDOMNode().getAttribute('style')).not.toContain 'background-color'
|
||||
expect(component.linesComponent.domNode.getAttribute('style')).not.toContain 'background-color'
|
||||
|
||||
it "does not render invisible characters", ->
|
||||
atom.config.set('editor.invisibles', eol: 'E')
|
||||
|
||||
@@ -162,10 +162,6 @@ module.exports =
|
||||
default: 300
|
||||
minimum: 0
|
||||
description: 'Time interval in milliseconds within which operations will be grouped together in the undo history'
|
||||
useHardwareAcceleration:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
description: 'Disabling will improve editor font rendering but reduce scrolling performance.'
|
||||
useShadowDOM:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
|
||||
@@ -30,13 +30,8 @@ GutterComponent = React.createClass
|
||||
backgroundColor: backgroundColor
|
||||
|
||||
getTransform: ->
|
||||
{useHardwareAcceleration} = @props
|
||||
{scrollTop} = @newState
|
||||
|
||||
if useHardwareAcceleration
|
||||
"translate3d(0px, #{-scrollTop}px, 0px)"
|
||||
else
|
||||
"translate(0px, #{-scrollTop}px)"
|
||||
"translate3d(0px, #{-scrollTop}px, 0px)"
|
||||
|
||||
componentWillMount: ->
|
||||
@lineNumberNodesById = {}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
_ = require 'underscore-plus'
|
||||
React = require 'react-atom-fork'
|
||||
{div, span} = require 'reactionary-atom-fork'
|
||||
{debounce, isEqual, isEqualForProperties, multiplyString, toArray} = require 'underscore-plus'
|
||||
{toArray} = require 'underscore-plus'
|
||||
{$$} = require 'space-pen'
|
||||
|
||||
CursorsComponent = require './cursors-component'
|
||||
@@ -13,76 +11,58 @@ AcceptFilter = {acceptNode: -> NodeFilter.FILTER_ACCEPT}
|
||||
WrapperDiv = document.createElement('div')
|
||||
|
||||
module.exports =
|
||||
LinesComponent = React.createClass
|
||||
displayName: 'LinesComponent'
|
||||
class LinesComponent
|
||||
placeholderTextDiv: null
|
||||
|
||||
render: ->
|
||||
div {className: 'lines'}
|
||||
|
||||
getTransform: (scrollTop, scrollLeft) ->
|
||||
{useHardwareAcceleration} = @props
|
||||
|
||||
if useHardwareAcceleration
|
||||
"translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
|
||||
else
|
||||
"translate(#{-scrollLeft}px, #{-scrollTop}px)"
|
||||
|
||||
componentWillMount: ->
|
||||
constructor: ({@presenter, @hostElement, @useShadowDOM}) ->
|
||||
@measuredLines = new Set
|
||||
@lineNodesByLineId = {}
|
||||
@screenRowsByLineId = {}
|
||||
@lineIdsByScreenRow = {}
|
||||
@renderedDecorationsByLineId = {}
|
||||
|
||||
componentDidMount: ->
|
||||
node = @getDOMNode()
|
||||
@domNode = document.createElement('div')
|
||||
@domNode.classList.add('lines')
|
||||
|
||||
@cursorsComponent = new CursorsComponent(@props.presenter)
|
||||
node.appendChild(@cursorsComponent.domNode)
|
||||
@cursorsComponent = new CursorsComponent(@presenter)
|
||||
@domNode.appendChild(@cursorsComponent.domNode)
|
||||
|
||||
@highlightsComponent = new HighlightsComponent(@props.presenter)
|
||||
node.appendChild(@highlightsComponent.domNode)
|
||||
@highlightsComponent = new HighlightsComponent(@presenter)
|
||||
@domNode.appendChild(@highlightsComponent.domNode)
|
||||
|
||||
if @props.useShadowDOM
|
||||
if @useShadowDOM
|
||||
insertionPoint = document.createElement('content')
|
||||
insertionPoint.setAttribute('select', '.overlayer')
|
||||
node.appendChild(insertionPoint)
|
||||
@domNode.appendChild(insertionPoint)
|
||||
|
||||
insertionPoint = document.createElement('content')
|
||||
insertionPoint.setAttribute('select', 'atom-overlay')
|
||||
@overlayManager = new OverlayManager(@props.hostElement)
|
||||
node.appendChild(insertionPoint)
|
||||
@overlayManager = new OverlayManager(@hostElement)
|
||||
@domNode.appendChild(insertionPoint)
|
||||
else
|
||||
@overlayManager = new OverlayManager(node)
|
||||
@overlayManager = new OverlayManager(@domNode)
|
||||
|
||||
@updateSync()
|
||||
|
||||
componentDidUpdate: ->
|
||||
@updateSync()
|
||||
|
||||
updateSync: ->
|
||||
{visible, presenter} = @props
|
||||
@newState = presenter.state.content
|
||||
updateSync: (visible) ->
|
||||
@newState = @presenter.state.content
|
||||
@oldState ?= {lines: {}}
|
||||
|
||||
node = @getDOMNode()
|
||||
|
||||
if @newState.scrollHeight isnt @oldState.scrollHeight
|
||||
node.style.height = @newState.scrollHeight + 'px'
|
||||
@domNode.style.height = @newState.scrollHeight + 'px'
|
||||
@oldState.scrollHeight = @newState.scrollHeight
|
||||
|
||||
if @newState.scrollWidth isnt @oldState.scrollWidth
|
||||
node.style.width = @newState.scrollWidth + 'px'
|
||||
@domNode.style.width = @newState.scrollWidth + 'px'
|
||||
@oldState.scrollWidth = @newState.scrollWidth
|
||||
|
||||
if @newState.scrollTop isnt @oldState.scrollTop or @newState.scrollLeft isnt @oldState.scrollLeft
|
||||
node.style['-webkit-transform'] = @getTransform(@newState.scrollTop, @newState.scrollLeft)
|
||||
@domNode.style['-webkit-transform'] = "translate3d(#{-@newState.scrollLeft}px, #{-@newState.scrollTop}px, 0px)"
|
||||
@oldState.scrollTop = @newState.scrollTop
|
||||
@oldState.scrollLeft = @newState.scrollLeft
|
||||
|
||||
if @newState.backgroundColor isnt @oldState.backgroundColor
|
||||
node.style.backgroundColor = @newState.backgroundColor
|
||||
@domNode.style.backgroundColor = @newState.backgroundColor
|
||||
@oldState.backgroundColor = @newState.backgroundColor
|
||||
|
||||
if @newState.placeholderText isnt @oldState.placeholderText
|
||||
@@ -91,7 +71,7 @@ LinesComponent = React.createClass
|
||||
@placeholderTextDiv = document.createElement('div')
|
||||
@placeholderTextDiv.classList.add('placeholder-text')
|
||||
@placeholderTextDiv.textContent = @newState.placeholderText
|
||||
node.appendChild(@placeholderTextDiv)
|
||||
@domNode.appendChild(@placeholderTextDiv)
|
||||
|
||||
@removeLineNodes() unless @oldState.indentGuidesVisible is @newState.indentGuidesVisible
|
||||
@updateLineNodes()
|
||||
@@ -100,15 +80,11 @@ LinesComponent = React.createClass
|
||||
@cursorsComponent.updateSync()
|
||||
@highlightsComponent.updateSync()
|
||||
|
||||
@overlayManager?.render(@props)
|
||||
@overlayManager?.render(@presenter)
|
||||
|
||||
@oldState.indentGuidesVisible = @newState.indentGuidesVisible
|
||||
@oldState.scrollWidth = @newState.scrollWidth
|
||||
|
||||
clearScreenRowCaches: ->
|
||||
@screenRowsByLineId = {}
|
||||
@lineIdsByScreenRow = {}
|
||||
|
||||
removeLineNodes: ->
|
||||
@removeLineNode(id) for id of @oldState.lines
|
||||
|
||||
@@ -120,8 +96,6 @@ LinesComponent = React.createClass
|
||||
delete @oldState.lines[id]
|
||||
|
||||
updateLineNodes: ->
|
||||
{presenter} = @props
|
||||
|
||||
for id of @oldState.lines
|
||||
unless @newState.lines.hasOwnProperty(id)
|
||||
@removeLineNode(id)
|
||||
@@ -144,15 +118,13 @@ LinesComponent = React.createClass
|
||||
return unless newLineIds?
|
||||
|
||||
WrapperDiv.innerHTML = newLinesHTML
|
||||
newLineNodes = toArray(WrapperDiv.children)
|
||||
node = @getDOMNode()
|
||||
newLineNodes = _.toArray(WrapperDiv.children)
|
||||
for id, i in newLineIds
|
||||
lineNode = newLineNodes[i]
|
||||
@lineNodesByLineId[id] = lineNode
|
||||
node.appendChild(lineNode)
|
||||
@domNode.appendChild(lineNode)
|
||||
|
||||
buildLineHTML: (id) ->
|
||||
{presenter} = @props
|
||||
{scrollWidth} = @newState
|
||||
{screenRow, tokens, text, top, lineEnding, fold, isSoftWrapped, indentLevel, decorationClasses} = @newState.lines[id]
|
||||
|
||||
@@ -197,7 +169,6 @@ LinesComponent = React.createClass
|
||||
@buildEndOfLineHTML(id) or ' '
|
||||
|
||||
buildLineInnerHTML: (id) ->
|
||||
{editor} = @props
|
||||
{indentGuidesVisible} = @newState
|
||||
{tokens, text, isOnlyWhitespace} = @newState.lines[id]
|
||||
innerHTML = ""
|
||||
@@ -275,26 +246,22 @@ LinesComponent = React.createClass
|
||||
@lineNodesByLineId[@lineIdsByScreenRow[screenRow]]
|
||||
|
||||
measureLineHeightAndDefaultCharWidth: ->
|
||||
node = @getDOMNode()
|
||||
node.appendChild(DummyLineNode)
|
||||
@domNode.appendChild(DummyLineNode)
|
||||
lineHeightInPixels = DummyLineNode.getBoundingClientRect().height
|
||||
charWidth = DummyLineNode.firstChild.getBoundingClientRect().width
|
||||
node.removeChild(DummyLineNode)
|
||||
@domNode.removeChild(DummyLineNode)
|
||||
|
||||
{editor, presenter} = @props
|
||||
presenter.setLineHeight(lineHeightInPixels)
|
||||
presenter.setBaseCharacterWidth(charWidth)
|
||||
@presenter.setLineHeight(lineHeightInPixels)
|
||||
@presenter.setBaseCharacterWidth(charWidth)
|
||||
|
||||
remeasureCharacterWidths: ->
|
||||
return unless @props.presenter.baseCharacterWidth
|
||||
return unless @presenter.baseCharacterWidth
|
||||
|
||||
@clearScopedCharWidths()
|
||||
@measureCharactersInNewLines()
|
||||
|
||||
measureCharactersInNewLines: ->
|
||||
{presenter} = @props
|
||||
|
||||
presenter.batchCharacterMeasurement =>
|
||||
@presenter.batchCharacterMeasurement =>
|
||||
for id, lineState of @oldState.lines
|
||||
unless @measuredLines.has(id)
|
||||
lineNode = @lineNodesByLineId[id]
|
||||
@@ -302,13 +269,12 @@ LinesComponent = React.createClass
|
||||
return
|
||||
|
||||
measureCharactersInLine: (tokenizedLine, lineNode) ->
|
||||
{editor} = @props
|
||||
rangeForMeasurement = null
|
||||
iterator = null
|
||||
charIndex = 0
|
||||
|
||||
for {value, scopes, hasPairedCharacter} in tokenizedLine.tokens
|
||||
charWidths = editor.getScopedCharWidths(scopes)
|
||||
charWidths = @presenter.getScopedCharacterWidths(scopes)
|
||||
|
||||
valueIndex = 0
|
||||
while valueIndex < value.length
|
||||
@@ -340,7 +306,7 @@ LinesComponent = React.createClass
|
||||
rangeForMeasurement.setStart(textNode, i)
|
||||
rangeForMeasurement.setEnd(textNode, i + charLength)
|
||||
charWidth = rangeForMeasurement.getBoundingClientRect().width
|
||||
@props.presenter.setScopedCharacterWidth(scopes, char, charWidth)
|
||||
@presenter.setScopedCharacterWidth(scopes, char, charWidth)
|
||||
|
||||
charIndex += charLength
|
||||
|
||||
@@ -348,5 +314,4 @@ LinesComponent = React.createClass
|
||||
|
||||
clearScopedCharWidths: ->
|
||||
@measuredLines.clear()
|
||||
@props.editor.clearScopedCharWidths()
|
||||
@props.presenter.clearScopedCharacterWidths()
|
||||
@presenter.clearScopedCharacterWidths()
|
||||
|
||||
@@ -3,9 +3,7 @@ class OverlayManager
|
||||
constructor: (@container) ->
|
||||
@overlayNodesById = {}
|
||||
|
||||
render: (props) ->
|
||||
{presenter} = props
|
||||
|
||||
render: (presenter) ->
|
||||
for decorationId, {pixelPosition, item} of presenter.state.content.overlays
|
||||
@renderOverlay(presenter, decorationId, item, pixelPosition)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ ScrollbarComponent = React.createClass
|
||||
displayName: 'ScrollbarComponent'
|
||||
|
||||
render: ->
|
||||
{presenter, orientation, className, useHardwareAcceleration} = @props
|
||||
{presenter, orientation, className} = @props
|
||||
|
||||
switch orientation
|
||||
when 'vertical'
|
||||
@@ -18,7 +18,7 @@ ScrollbarComponent = React.createClass
|
||||
style = {}
|
||||
|
||||
style.display = 'none' unless @newState.visible
|
||||
style.transform = 'translateZ(0)' if useHardwareAcceleration # See atom/atom#3559
|
||||
style.transform = 'translateZ(0)' # See atom/atom#3559
|
||||
switch orientation
|
||||
when 'vertical'
|
||||
style.width = @newState.width
|
||||
|
||||
@@ -50,10 +50,8 @@ TextEditorComponent = React.createClass
|
||||
@performedInitialMeasurement = false if editor.isDestroyed()
|
||||
|
||||
if @performedInitialMeasurement
|
||||
visible = @isVisible()
|
||||
|
||||
hiddenInputStyle = @getHiddenInputPosition()
|
||||
hiddenInputStyle.WebkitTransform = 'translateZ(0)' if @useHardwareAcceleration
|
||||
hiddenInputStyle.WebkitTransform = 'translateZ(0)'
|
||||
style.height = @presenter.state.height if @presenter.state.height?
|
||||
|
||||
if useShadowDOM
|
||||
@@ -67,7 +65,7 @@ TextEditorComponent = React.createClass
|
||||
if @gutterVisible
|
||||
GutterComponent {
|
||||
ref: 'gutter', onMouseDown: @onGutterMouseDown,
|
||||
@presenter, editor, @useHardwareAcceleration
|
||||
@presenter, editor
|
||||
}
|
||||
|
||||
div ref: 'scrollView', className: 'scroll-view',
|
||||
@@ -76,17 +74,12 @@ TextEditorComponent = React.createClass
|
||||
className: 'hidden-input'
|
||||
style: hiddenInputStyle
|
||||
|
||||
LinesComponent {
|
||||
ref: 'lines', @presenter, editor, hostElement, @useHardwareAcceleration, useShadowDOM, visible
|
||||
}
|
||||
|
||||
ScrollbarComponent
|
||||
ref: 'horizontalScrollbar'
|
||||
className: 'horizontal-scrollbar'
|
||||
orientation: 'horizontal'
|
||||
presenter: @presenter
|
||||
onScroll: @onHorizontalScroll
|
||||
useHardwareAcceleration: @useHardwareAcceleration
|
||||
|
||||
ScrollbarComponent
|
||||
ref: 'verticalScrollbar'
|
||||
@@ -94,7 +87,6 @@ TextEditorComponent = React.createClass
|
||||
orientation: 'vertical'
|
||||
presenter: @presenter
|
||||
onScroll: @onVerticalScroll
|
||||
useHardwareAcceleration: @useHardwareAcceleration
|
||||
|
||||
# Also used to measure the height/width of scrollbars after the initial render
|
||||
ScrollbarCornerComponent
|
||||
@@ -126,9 +118,14 @@ TextEditorComponent = React.createClass
|
||||
stoppedScrollingDelay: 200
|
||||
@presenter.onDidUpdateState(@requestUpdate)
|
||||
|
||||
|
||||
componentDidMount: ->
|
||||
{editor, stylesElement} = @props
|
||||
{editor, stylesElement, hostElement, useShadowDOM} = @props
|
||||
|
||||
@linesComponent = new LinesComponent({@presenter, hostElement, useShadowDOM})
|
||||
scrollViewNode = @refs.scrollView.getDOMNode()
|
||||
horizontalScrollbarNode = @refs.horizontalScrollbar.getDOMNode()
|
||||
scrollViewNode.insertBefore(@linesComponent.domNode, horizontalScrollbarNode)
|
||||
@linesComponent.updateSync(@isVisible())
|
||||
|
||||
@observeEditor()
|
||||
@listenForDOMEvents()
|
||||
@@ -161,6 +158,8 @@ TextEditorComponent = React.createClass
|
||||
@cursorMoved = false
|
||||
@selectionChanged = false
|
||||
|
||||
@linesComponent.updateSync(@isVisible())
|
||||
|
||||
if @props.editor.isAlive()
|
||||
@updateParentViewFocusedClassIfNeeded(prevState)
|
||||
@updateParentViewMiniClass()
|
||||
@@ -289,7 +288,6 @@ TextEditorComponent = React.createClass
|
||||
timeoutId = setTimeout(writeSelectedTextToSelectionClipboard)
|
||||
|
||||
observeConfig: ->
|
||||
@subscribe atom.config.observe 'editor.useHardwareAcceleration', @setUseHardwareAcceleration
|
||||
@subscribe atom.config.onDidChange 'editor.fontSize', @sampleFontStyling
|
||||
@subscribe atom.config.onDidChange 'editor.fontFamily', @sampleFontStyling
|
||||
@subscribe atom.config.onDidChange 'editor.lineHeight', @sampleFontStyling
|
||||
@@ -689,14 +687,14 @@ TextEditorComponent = React.createClass
|
||||
measureLineHeightAndDefaultCharWidth: ->
|
||||
if @isVisible()
|
||||
@measureLineHeightAndDefaultCharWidthWhenShown = false
|
||||
@refs.lines.measureLineHeightAndDefaultCharWidth()
|
||||
@linesComponent.measureLineHeightAndDefaultCharWidth()
|
||||
else
|
||||
@measureLineHeightAndDefaultCharWidthWhenShown = true
|
||||
|
||||
remeasureCharacterWidths: ->
|
||||
if @isVisible()
|
||||
@remeasureCharacterWidthsWhenShown = false
|
||||
@refs.lines.remeasureCharacterWidths()
|
||||
@linesComponent.remeasureCharacterWidths()
|
||||
else
|
||||
@remeasureCharacterWidthsWhenShown = true
|
||||
|
||||
@@ -761,7 +759,7 @@ TextEditorComponent = React.createClass
|
||||
consolidateSelections: (e) ->
|
||||
e.abortKeyBinding() unless @props.editor.consolidateSelections()
|
||||
|
||||
lineNodeForScreenRow: (screenRow) -> @refs.lines.lineNodeForScreenRow(screenRow)
|
||||
lineNodeForScreenRow: (screenRow) -> @linesComponent.lineNodeForScreenRow(screenRow)
|
||||
|
||||
lineNumberNodeForScreenRow: (screenRow) -> @refs.gutter.lineNumberNodeForScreenRow(screenRow)
|
||||
|
||||
@@ -816,11 +814,6 @@ TextEditorComponent = React.createClass
|
||||
if scrollSensitivity = parseInt(scrollSensitivity)
|
||||
@scrollSensitivity = Math.abs(scrollSensitivity) / 100
|
||||
|
||||
setUseHardwareAcceleration: (useHardwareAcceleration=true) ->
|
||||
unless @useHardwareAcceleration is useHardwareAcceleration
|
||||
@useHardwareAcceleration = useHardwareAcceleration
|
||||
@requestUpdate()
|
||||
|
||||
screenPositionForMouseEvent: (event) ->
|
||||
pixelPosition = @pixelPositionForMouseEvent(event)
|
||||
@props.editor.screenPositionForPixelPosition(pixelPosition)
|
||||
@@ -829,7 +822,7 @@ TextEditorComponent = React.createClass
|
||||
{editor} = @props
|
||||
{clientX, clientY} = event
|
||||
|
||||
linesClientRect = @refs.lines.getDOMNode().getBoundingClientRect()
|
||||
linesClientRect = @linesComponent.domNode.getBoundingClientRect()
|
||||
top = clientY - linesClientRect.top
|
||||
left = clientX - linesClientRect.left
|
||||
{top, left}
|
||||
|
||||
@@ -631,6 +631,7 @@ class TextEditorPresenter
|
||||
|
||||
clearScopedCharacterWidths: ->
|
||||
@characterWidthsByScope = {}
|
||||
@model.clearScopedCharWidths()
|
||||
|
||||
hasPixelPositionRequirements: ->
|
||||
@lineHeight? and @baseCharacterWidth?
|
||||
|
||||
Reference in New Issue
Block a user