Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Commit

Permalink
Make LinesComponent a normal object instead of a React component
Browse files Browse the repository at this point in the history
Also, remove ability to disable hardware acceleration since there’s
no longer a need for it and it complicated this conversion.
  • Loading branch information
Nathan Sobo committed Feb 20, 2015
1 parent da793e8 commit c06e100
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 106 deletions.
2 changes: 1 addition & 1 deletion spec/text-editor-component-spec.coffee
Expand Up @@ -2558,7 +2558,7 @@ describe "TextEditorComponent", ->
expect(wrapperNode.classList.contains('mini')).toBe true expect(wrapperNode.classList.contains('mini')).toBe true


it "does not have an opaque background on lines", -> 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", -> it "does not render invisible characters", ->
atom.config.set('editor.invisibles', eol: 'E') atom.config.set('editor.invisibles', eol: 'E')
Expand Down
4 changes: 0 additions & 4 deletions src/config-schema.coffee
Expand Up @@ -162,10 +162,6 @@ module.exports =
default: 300 default: 300
minimum: 0 minimum: 0
description: 'Time interval in milliseconds within which operations will be grouped together in the undo history' 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: useShadowDOM:
type: 'boolean' type: 'boolean'
default: true default: true
Expand Down
7 changes: 1 addition & 6 deletions src/gutter-component.coffee
Expand Up @@ -30,13 +30,8 @@ GutterComponent = React.createClass
backgroundColor: backgroundColor backgroundColor: backgroundColor


getTransform: -> getTransform: ->
{useHardwareAcceleration} = @props
{scrollTop} = @newState {scrollTop} = @newState

"translate3d(0px, #{-scrollTop}px, 0px)"
if useHardwareAcceleration
"translate3d(0px, #{-scrollTop}px, 0px)"
else
"translate(0px, #{-scrollTop}px)"


componentWillMount: -> componentWillMount: ->
@lineNumberNodesById = {} @lineNumberNodesById = {}
Expand Down
101 changes: 33 additions & 68 deletions src/lines-component.coffee
@@ -1,7 +1,5 @@
_ = require 'underscore-plus' _ = require 'underscore-plus'
React = require 'react-atom-fork' {toArray} = require 'underscore-plus'
{div, span} = require 'reactionary-atom-fork'
{debounce, isEqual, isEqualForProperties, multiplyString, toArray} = require 'underscore-plus'
{$$} = require 'space-pen' {$$} = require 'space-pen'


CursorsComponent = require './cursors-component' CursorsComponent = require './cursors-component'
Expand All @@ -13,76 +11,58 @@ AcceptFilter = {acceptNode: -> NodeFilter.FILTER_ACCEPT}
WrapperDiv = document.createElement('div') WrapperDiv = document.createElement('div')


module.exports = module.exports =
LinesComponent = React.createClass class LinesComponent
displayName: 'LinesComponent'
placeholderTextDiv: null placeholderTextDiv: null


render: -> constructor: ({@presenter, @hostElement, @useShadowDOM}) ->
div {className: 'lines'}

getTransform: (scrollTop, scrollLeft) ->
{useHardwareAcceleration} = @props

if useHardwareAcceleration
"translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
else
"translate(#{-scrollLeft}px, #{-scrollTop}px)"

componentWillMount: ->
@measuredLines = new Set @measuredLines = new Set
@lineNodesByLineId = {} @lineNodesByLineId = {}
@screenRowsByLineId = {} @screenRowsByLineId = {}
@lineIdsByScreenRow = {} @lineIdsByScreenRow = {}
@renderedDecorationsByLineId = {} @renderedDecorationsByLineId = {}


componentDidMount: -> @domNode = document.createElement('div')
node = @getDOMNode() @domNode.classList.add('lines')


@cursorsComponent = new CursorsComponent(@props.presenter) @cursorsComponent = new CursorsComponent(@presenter)
node.appendChild(@cursorsComponent.domNode) @domNode.appendChild(@cursorsComponent.domNode)


@highlightsComponent = new HighlightsComponent(@props.presenter) @highlightsComponent = new HighlightsComponent(@presenter)
node.appendChild(@highlightsComponent.domNode) @domNode.appendChild(@highlightsComponent.domNode)


if @props.useShadowDOM if @useShadowDOM
insertionPoint = document.createElement('content') insertionPoint = document.createElement('content')
insertionPoint.setAttribute('select', '.overlayer') insertionPoint.setAttribute('select', '.overlayer')
node.appendChild(insertionPoint) @domNode.appendChild(insertionPoint)


insertionPoint = document.createElement('content') insertionPoint = document.createElement('content')
insertionPoint.setAttribute('select', 'atom-overlay') insertionPoint.setAttribute('select', 'atom-overlay')
@overlayManager = new OverlayManager(@props.hostElement) @overlayManager = new OverlayManager(@hostElement)
node.appendChild(insertionPoint) @domNode.appendChild(insertionPoint)
else else
@overlayManager = new OverlayManager(node) @overlayManager = new OverlayManager(@domNode)

@updateSync()


componentDidUpdate: ->
@updateSync() @updateSync()


updateSync: -> updateSync: (visible) ->
{visible, presenter} = @props @newState = @presenter.state.content
@newState = presenter.state.content
@oldState ?= {lines: {}} @oldState ?= {lines: {}}


node = @getDOMNode()

if @newState.scrollHeight isnt @oldState.scrollHeight if @newState.scrollHeight isnt @oldState.scrollHeight
node.style.height = @newState.scrollHeight + 'px' @domNode.style.height = @newState.scrollHeight + 'px'
@oldState.scrollHeight = @newState.scrollHeight @oldState.scrollHeight = @newState.scrollHeight


if @newState.scrollWidth isnt @oldState.scrollWidth if @newState.scrollWidth isnt @oldState.scrollWidth
node.style.width = @newState.scrollWidth + 'px' @domNode.style.width = @newState.scrollWidth + 'px'
@oldState.scrollWidth = @newState.scrollWidth @oldState.scrollWidth = @newState.scrollWidth


if @newState.scrollTop isnt @oldState.scrollTop or @newState.scrollLeft isnt @oldState.scrollLeft 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.scrollTop = @newState.scrollTop
@oldState.scrollLeft = @newState.scrollLeft @oldState.scrollLeft = @newState.scrollLeft


if @newState.backgroundColor isnt @oldState.backgroundColor if @newState.backgroundColor isnt @oldState.backgroundColor
node.style.backgroundColor = @newState.backgroundColor @domNode.style.backgroundColor = @newState.backgroundColor
@oldState.backgroundColor = @newState.backgroundColor @oldState.backgroundColor = @newState.backgroundColor


if @newState.placeholderText isnt @oldState.placeholderText if @newState.placeholderText isnt @oldState.placeholderText
Expand All @@ -91,7 +71,7 @@ LinesComponent = React.createClass
@placeholderTextDiv = document.createElement('div') @placeholderTextDiv = document.createElement('div')
@placeholderTextDiv.classList.add('placeholder-text') @placeholderTextDiv.classList.add('placeholder-text')
@placeholderTextDiv.textContent = @newState.placeholderText @placeholderTextDiv.textContent = @newState.placeholderText
node.appendChild(@placeholderTextDiv) @domNode.appendChild(@placeholderTextDiv)


@removeLineNodes() unless @oldState.indentGuidesVisible is @newState.indentGuidesVisible @removeLineNodes() unless @oldState.indentGuidesVisible is @newState.indentGuidesVisible
@updateLineNodes() @updateLineNodes()
Expand All @@ -100,15 +80,11 @@ LinesComponent = React.createClass
@cursorsComponent.updateSync() @cursorsComponent.updateSync()
@highlightsComponent.updateSync() @highlightsComponent.updateSync()


@overlayManager?.render(@props) @overlayManager?.render(@presenter)


@oldState.indentGuidesVisible = @newState.indentGuidesVisible @oldState.indentGuidesVisible = @newState.indentGuidesVisible
@oldState.scrollWidth = @newState.scrollWidth @oldState.scrollWidth = @newState.scrollWidth


clearScreenRowCaches: ->
@screenRowsByLineId = {}
@lineIdsByScreenRow = {}

removeLineNodes: -> removeLineNodes: ->
@removeLineNode(id) for id of @oldState.lines @removeLineNode(id) for id of @oldState.lines


Expand All @@ -120,8 +96,6 @@ LinesComponent = React.createClass
delete @oldState.lines[id] delete @oldState.lines[id]


updateLineNodes: -> updateLineNodes: ->
{presenter} = @props

for id of @oldState.lines for id of @oldState.lines
unless @newState.lines.hasOwnProperty(id) unless @newState.lines.hasOwnProperty(id)
@removeLineNode(id) @removeLineNode(id)
Expand All @@ -144,15 +118,13 @@ LinesComponent = React.createClass
return unless newLineIds? return unless newLineIds?


WrapperDiv.innerHTML = newLinesHTML WrapperDiv.innerHTML = newLinesHTML
newLineNodes = toArray(WrapperDiv.children) newLineNodes = _.toArray(WrapperDiv.children)
node = @getDOMNode()
for id, i in newLineIds for id, i in newLineIds
lineNode = newLineNodes[i] lineNode = newLineNodes[i]
@lineNodesByLineId[id] = lineNode @lineNodesByLineId[id] = lineNode
node.appendChild(lineNode) @domNode.appendChild(lineNode)


buildLineHTML: (id) -> buildLineHTML: (id) ->
{presenter} = @props
{scrollWidth} = @newState {scrollWidth} = @newState
{screenRow, tokens, text, top, lineEnding, fold, isSoftWrapped, indentLevel, decorationClasses} = @newState.lines[id] {screenRow, tokens, text, top, lineEnding, fold, isSoftWrapped, indentLevel, decorationClasses} = @newState.lines[id]


Expand Down Expand Up @@ -197,7 +169,6 @@ LinesComponent = React.createClass
@buildEndOfLineHTML(id) or ' ' @buildEndOfLineHTML(id) or ' '


buildLineInnerHTML: (id) -> buildLineInnerHTML: (id) ->
{editor} = @props
{indentGuidesVisible} = @newState {indentGuidesVisible} = @newState
{tokens, text, isOnlyWhitespace} = @newState.lines[id] {tokens, text, isOnlyWhitespace} = @newState.lines[id]
innerHTML = "" innerHTML = ""
Expand Down Expand Up @@ -275,40 +246,35 @@ LinesComponent = React.createClass
@lineNodesByLineId[@lineIdsByScreenRow[screenRow]] @lineNodesByLineId[@lineIdsByScreenRow[screenRow]]


measureLineHeightAndDefaultCharWidth: -> measureLineHeightAndDefaultCharWidth: ->
node = @getDOMNode() @domNode.appendChild(DummyLineNode)
node.appendChild(DummyLineNode)
lineHeightInPixels = DummyLineNode.getBoundingClientRect().height lineHeightInPixels = DummyLineNode.getBoundingClientRect().height
charWidth = DummyLineNode.firstChild.getBoundingClientRect().width charWidth = DummyLineNode.firstChild.getBoundingClientRect().width
node.removeChild(DummyLineNode) @domNode.removeChild(DummyLineNode)


{editor, presenter} = @props @presenter.setLineHeight(lineHeightInPixels)
presenter.setLineHeight(lineHeightInPixels) @presenter.setBaseCharacterWidth(charWidth)
presenter.setBaseCharacterWidth(charWidth)


remeasureCharacterWidths: -> remeasureCharacterWidths: ->
return unless @props.presenter.baseCharacterWidth return unless @presenter.baseCharacterWidth


@clearScopedCharWidths() @clearScopedCharWidths()
@measureCharactersInNewLines() @measureCharactersInNewLines()


measureCharactersInNewLines: -> measureCharactersInNewLines: ->
{presenter} = @props @presenter.batchCharacterMeasurement =>

presenter.batchCharacterMeasurement =>
for id, lineState of @oldState.lines for id, lineState of @oldState.lines
unless @measuredLines.has(id) unless @measuredLines.has(id)
lineNode = @lineNodesByLineId[id] lineNode = @lineNodesByLineId[id]
@measureCharactersInLine(lineState, lineNode) @measureCharactersInLine(lineState, lineNode)
return return


measureCharactersInLine: (tokenizedLine, lineNode) -> measureCharactersInLine: (tokenizedLine, lineNode) ->
{editor} = @props
rangeForMeasurement = null rangeForMeasurement = null
iterator = null iterator = null
charIndex = 0 charIndex = 0


for {value, scopes, hasPairedCharacter} in tokenizedLine.tokens for {value, scopes, hasPairedCharacter} in tokenizedLine.tokens
charWidths = editor.getScopedCharWidths(scopes) charWidths = @presenter.getScopedCharacterWidths(scopes)


valueIndex = 0 valueIndex = 0
while valueIndex < value.length while valueIndex < value.length
Expand Down Expand Up @@ -340,13 +306,12 @@ LinesComponent = React.createClass
rangeForMeasurement.setStart(textNode, i) rangeForMeasurement.setStart(textNode, i)
rangeForMeasurement.setEnd(textNode, i + charLength) rangeForMeasurement.setEnd(textNode, i + charLength)
charWidth = rangeForMeasurement.getBoundingClientRect().width charWidth = rangeForMeasurement.getBoundingClientRect().width
@props.presenter.setScopedCharacterWidth(scopes, char, charWidth) @presenter.setScopedCharacterWidth(scopes, char, charWidth)


charIndex += charLength charIndex += charLength


@measuredLines.add(tokenizedLine.id) @measuredLines.add(tokenizedLine.id)


clearScopedCharWidths: -> clearScopedCharWidths: ->
@measuredLines.clear() @measuredLines.clear()
@props.editor.clearScopedCharWidths() @presenter.clearScopedCharacterWidths()
@props.presenter.clearScopedCharacterWidths()
4 changes: 1 addition & 3 deletions src/overlay-manager.coffee
Expand Up @@ -3,9 +3,7 @@ class OverlayManager
constructor: (@container) -> constructor: (@container) ->
@overlayNodesById = {} @overlayNodesById = {}


render: (props) -> render: (presenter) ->
{presenter} = props

for decorationId, {pixelPosition, item} of presenter.state.content.overlays for decorationId, {pixelPosition, item} of presenter.state.content.overlays
@renderOverlay(presenter, decorationId, item, pixelPosition) @renderOverlay(presenter, decorationId, item, pixelPosition)


Expand Down
4 changes: 2 additions & 2 deletions src/scrollbar-component.coffee
Expand Up @@ -7,7 +7,7 @@ ScrollbarComponent = React.createClass
displayName: 'ScrollbarComponent' displayName: 'ScrollbarComponent'


render: -> render: ->
{presenter, orientation, className, useHardwareAcceleration} = @props {presenter, orientation, className} = @props


switch orientation switch orientation
when 'vertical' when 'vertical'
Expand All @@ -18,7 +18,7 @@ ScrollbarComponent = React.createClass
style = {} style = {}


style.display = 'none' unless @newState.visible 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 switch orientation
when 'vertical' when 'vertical'
style.width = @newState.width style.width = @newState.width
Expand Down

0 comments on commit c06e100

Please sign in to comment.