🐎 Cache gutterVisible state in React component

This avoids a config read on every render.
This commit is contained in:
Nathan Sobo 2015-01-12 11:13:51 -07:00
parent f00b0b7f7a
commit 002918049d
5 changed files with 38 additions and 29 deletions

View File

@ -561,12 +561,12 @@ describe "TextEditorComponent", ->
expect(component.refs.gutter?).toBe false
atom.config.set("editor.showLineNumbers", false)
nextAnimationFrame()
expect(nextAnimationFrame).toBe noAnimationFrame
expect(component.refs.gutter?).toBe false
editor.setGutterVisible(true)
nextAnimationFrame()
expect(nextAnimationFrame).toBe noAnimationFrame
expect(component.refs.gutter?).toBe false
@ -2517,7 +2517,8 @@ describe "TextEditorComponent", ->
describe "when the 'mini' property is true", ->
beforeEach ->
component.setProps(mini: true)
editor.setMini(true)
nextAnimationFrame()
it "does not render the gutter", ->
expect(componentNode.querySelector('.gutter')).toBeNull()

View File

@ -23,12 +23,12 @@ LinesComponent = React.createClass
if performedInitialMeasurement
{editor, overlayDecorations, highlightDecorations, scrollHeight, scrollWidth, placeholderText, backgroundColor} = @props
{lineHeightInPixels, defaultCharWidth, scrollViewHeight, scopedCharacterWidthsChangeCount} = @props
{scrollTop, scrollLeft, cursorPixelRects, mini} = @props
{scrollTop, scrollLeft, cursorPixelRects} = @props
style =
height: Math.max(scrollHeight, scrollViewHeight)
width: scrollWidth
WebkitTransform: @getTransform()
backgroundColor: if mini then null else backgroundColor
backgroundColor: if editor.isMini() then null else backgroundColor
div {className: 'lines', style},
div className: 'placeholder-text', placeholderText if placeholderText?
@ -162,7 +162,7 @@ LinesComponent = React.createClass
@lineNodesByLineId.hasOwnProperty(lineId)
buildLineHTML: (line, screenRow) ->
{mini, showIndentGuide, lineHeightInPixels, lineDecorations, lineWidth} = @props
{showIndentGuide, lineHeightInPixels, lineDecorations, lineWidth} = @props
{tokens, text, lineEnding, fold, isSoftWrapped, indentLevel} = line
classes = ''
@ -208,7 +208,7 @@ LinesComponent = React.createClass
@buildEndOfLineHTML(line) or ' '
buildLineInnerHTML: (line) ->
{mini, showIndentGuide} = @props
{editor, showIndentGuide} = @props
{tokens, text} = line
innerHTML = ""
@ -217,7 +217,7 @@ LinesComponent = React.createClass
lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0
for token in tokens
innerHTML += @updateScopeStack(scopeStack, token.scopes)
hasIndentGuide = not mini and showIndentGuide and (token.hasLeadingWhitespace() or (token.hasTrailingWhitespace() and lineIsWhitespaceOnly))
hasIndentGuide = not editor.isMini() and showIndentGuide and (token.hasLeadingWhitespace() or (token.hasTrailingWhitespace() and lineIsWhitespaceOnly))
innerHTML += token.getValueAsHtml({hasIndentGuide})
innerHTML += @popScope(scopeStack) while scopeStack.length > 0

View File

@ -48,7 +48,7 @@ TextEditorComponent = React.createClass
render: ->
{focused, showIndentGuide, showLineNumbers, visible} = @state
{editor, mini, cursorBlinkPeriod, cursorBlinkResumeDelay, hostElement, useShadowDOM} = @props
{editor, cursorBlinkPeriod, cursorBlinkResumeDelay, hostElement, useShadowDOM} = @props
maxLineNumberDigits = editor.getLineCount().toString().length
hasSelection = editor.getLastSelection()? and !editor.getLastSelection().isEmpty()
style = {}
@ -96,7 +96,7 @@ TextEditorComponent = React.createClass
className += ' has-selection' if hasSelection
div {className, style},
if @shouldRenderGutter()
if @gutterVisible
GutterComponent {
ref: 'gutter', onMouseDown: @onGutterMouseDown, lineDecorations,
defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
@ -118,7 +118,7 @@ TextEditorComponent = React.createClass
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow,
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth, @useHardwareAcceleration,
placeholderText, @performedInitialMeasurement, @backgroundColor, cursorPixelRects,
cursorBlinkPeriod, cursorBlinkResumeDelay, mini, useShadowDOM
cursorBlinkPeriod, cursorBlinkResumeDelay, useShadowDOM
}
ScrollbarComponent
@ -159,9 +159,6 @@ TextEditorComponent = React.createClass
{editor} = @props
Math.max(1, Math.ceil(editor.getHeight() / editor.getLineHeightInPixels()))
shouldRenderGutter: ->
not @props.mini and @props.editor.isGutterVisible() and atom.config.get('editor.showLineNumbers')
getInitialState: -> {}
getDefaultProps: ->
@ -190,7 +187,7 @@ TextEditorComponent = React.createClass
@domPollingIntervalId = setInterval(@pollDOM, @domPollingInterval)
@updateParentViewFocusedClassIfNeeded({})
@updateParentViewMiniClassIfNeeded({})
@updateParentViewMiniClass()
@checkForVisibilityChange()
componentWillUnmount: ->
@ -202,9 +199,6 @@ TextEditorComponent = React.createClass
clearInterval(@domPollingIntervalId)
@domPollingIntervalId = null
componentWillReceiveProps: (newProps) ->
@props.editor.setMini(newProps.mini)
componentDidUpdate: (prevProps, prevState) ->
cursorMoved = @cursorMoved
selectionChanged = @selectionChanged
@ -214,7 +208,7 @@ TextEditorComponent = React.createClass
if @props.editor.isAlive()
@updateParentViewFocusedClassIfNeeded(prevState)
@updateParentViewMiniClassIfNeeded(prevState)
@updateParentViewMiniClass()
@props.hostElement.__spacePenView.trigger 'cursor:moved' if cursorMoved
@props.hostElement.__spacePenView.trigger 'selection:changed' if selectionChanged
@props.hostElement.__spacePenView.trigger 'editor:display-updated'
@ -308,8 +302,8 @@ TextEditorComponent = React.createClass
cursorPixelRects
getLineDecorations: (decorationsByMarkerId) ->
{editor, mini} = @props
return {} if mini
{editor} = @props
return {} if editor.isMini()
decorationsByScreenRow = {}
for markerId, decorations of decorationsByMarkerId
@ -377,6 +371,8 @@ TextEditorComponent = React.createClass
observeEditor: ->
{editor} = @props
@subscribe editor.onDidChange(@onScreenLinesChanged)
@subscribe editor.onDidChangeGutterVisible(@updateGutterVisible)
@subscribe editor.onDidChangeMini(@setMini)
@subscribe editor.observeGrammar(@onGrammarChanged)
@subscribe editor.observeCursors(@onCursorAdded)
@subscribe editor.observeSelections(@onSelectionAdded)
@ -463,8 +459,7 @@ TextEditorComponent = React.createClass
scopeDescriptor = editor.getRootScopeDescriptor()
subscriptions.add atom.config.observe 'editor.showIndentGuide', scope: scopeDescriptor, @setShowIndentGuide
subscriptions.add atom.config.onDidChange 'editor.showLineNumbers', scope: scopeDescriptor, @requestUpdate
subscriptions.add editor.onDidChangeGutterVisible @requestUpdate
subscriptions.add atom.config.observe 'editor.showLineNumbers', scope: scopeDescriptor, @updateGutterVisible
subscriptions.add atom.config.observe 'editor.scrollSensitivity', scope: scopeDescriptor, @setScrollSensitivity
focused: ->
@ -882,7 +877,7 @@ TextEditorComponent = React.createClass
@backgroundColor = backgroundColor
@requestUpdate() unless suppressUpdate
if @shouldRenderGutter()
if @refs.gutter?
gutterBackgroundColor = getComputedStyle(@refs.gutter.getDOMNode()).backgroundColor
if gutterBackgroundColor isnt @gutterBackgroundColor
@gutterBackgroundColor = gutterBackgroundColor
@ -1002,6 +997,16 @@ TextEditorComponent = React.createClass
setShowIndentGuide: (showIndentGuide) ->
@setState({showIndentGuide})
setMini: ->
@updateGutterVisible()
@requestUpdate()
updateGutterVisible: ->
gutterVisible = not @props.editor.isMini() and @props.editor.isGutterVisible() and atom.config.get('editor.showLineNumbers')
if gutterVisible isnt @gutterVisible
@gutterVisible = gutterVisible
@requestUpdate()
# Deprecated
setInvisibles: (invisibles={}) ->
grim.deprecate "Use config.set('editor.invisibles', invisibles) instead"
@ -1045,10 +1050,9 @@ TextEditorComponent = React.createClass
@props.hostElement.classList.toggle('is-focused', @state.focused)
@props.rootElement.classList.toggle('is-focused', @state.focused)
updateParentViewMiniClassIfNeeded: (prevProps) ->
if prevProps.mini isnt @props.mini
@props.hostElement.classList.toggle('mini', @props.mini)
@props.rootElement.classList.toggle('mini', @props.mini)
updateParentViewMiniClass: ->
@props.hostElement.classList.toggle('mini', @props.editor.isMini())
@props.rootElement.classList.toggle('mini', @props.editor.isMini())
runScrollBenchmark: ->
unless process.env.NODE_ENV is 'production'

View File

@ -109,7 +109,6 @@ class TextEditorElement extends HTMLElement
rootElement: @rootElement
stylesElement: @stylesElement
editor: @model
mini: @model.mini
lineOverdrawMargin: @lineOverdrawMargin
useShadowDOM: @useShadowDOM
)

View File

@ -533,9 +533,14 @@ class TextEditor extends Model
if mini isnt @mini
@mini = mini
@updateInvisibles()
@emitter.emit 'did-change-mini', @mini
@mini
isMini: -> @mini
onDidChangeMini: (callback) ->
@emitter.on 'did-change-mini', callback
setGutterVisible: (gutterVisible) ->
unless gutterVisible is @gutterVisible
@gutterVisible = gutterVisible